Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ProcessMaker/Events/ImportLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public function __construct(
public $userId,
public $type,
public $message,
public $additionalParams = []
public $additionalParams = [],
public $operationId = null,
) {
}

Expand Down
18 changes: 17 additions & 1 deletion ProcessMaker/Http/Controllers/Api/DevLinkController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Http\Client\RequestException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use ProcessMaker\Events\CustomizeUiUpdated;
use ProcessMaker\Exception\ValidationException;
Expand Down Expand Up @@ -225,13 +226,15 @@ public function deleteBundle(Bundle $bundle)
public function installRemoteBundle(Request $request, DevLink $devLink, int $remoteBundleId)
{
$updateType = $request->input('updateType', DevLinkInstall::MODE_UPDATE);
$operationId = $this->operationId($request);
DevLinkInstall::dispatch(
$request->user()->id,
$devLink->id,
Bundle::class,
$remoteBundleId,
$updateType,
DevLinkInstall::TYPE_INSTALL_BUNDLE,
$operationId,
);

return [
Expand All @@ -242,13 +245,15 @@ public function installRemoteBundle(Request $request, DevLink $devLink, int $rem
public function reinstallBundle(Request $request, Bundle $bundle)
{
$updateType = $request->input('updateType', DevLinkInstall::MODE_UPDATE);
$operationId = $this->operationId($request);
DevLinkInstall::dispatch(
$request->user()->id,
$bundle->dev_link_id,
Bundle::class,
$bundle->id,
$updateType,
DevLinkInstall::TYPE_REINSTALL_BUNDLE,
$operationId,
);

return [
Expand Down Expand Up @@ -370,14 +375,16 @@ public function removeSharedAsset(int $id)
public function installRemoteAsset(Request $request, DevLink $devLink)
{
$updateType = $request->input('updateType', DevLinkInstall::MODE_UPDATE);
$operationId = $this->operationId($request);

DevLinkInstall::dispatch(
$request->user()->id,
$devLink->id,
$request->input('class'),
$request->input('id'),
$updateType,
DevLinkInstall::TYPE_IMPORT_ASSET
DevLinkInstall::TYPE_IMPORT_ASSET,
$operationId,
);

return [
Expand Down Expand Up @@ -502,4 +509,13 @@ public function refreshUi(Request $request)
CompileUI::dispatch($request->user()?->id);
CustomizeUiUpdated::dispatch([], [], false);
}

private function operationId(Request $request): string
{
$validated = $request->validate([
'operation_id' => ['nullable', 'string', 'max:100'],
]);

return $validated['operation_id'] ?? (string) Str::uuid();
}
}
13 changes: 11 additions & 2 deletions ProcessMaker/ImportExport/Logger.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ class Logger

public $userId = null;

public $operationId = null;

private $warnings = [];

private int $totalSteps = 1;

private int $currentStep = 1;

public function __construct($userId = null)
public function __construct($userId = null, $operationId = null)
{
$this->pid = getmypid();
$this->userId = $userId;
$this->operationId = $operationId;

if ($userId) {
Event::listen(MessageLogged::class, function (MessageLogged $e) {
Expand Down Expand Up @@ -71,7 +74,13 @@ private function dispatch($type, $message, $additionalParams = [])
return;
}

ImportLog::dispatch($this->userId, $type, substr($message, 0, 1000), $additionalParams);
ImportLog::dispatch(
$this->userId,
$type,
substr($message, 0, 1000),
$additionalParams,
$this->operationId,
);
$this->logToFile($type, $message, $additionalParams);
}

Expand Down
14 changes: 12 additions & 2 deletions ProcessMaker/Jobs/DevLinkInstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,24 @@ class DevLinkInstall implements ShouldQueue

public $maxExceptions = 1;

/**
* Correlates progress events with the DevLink operation that started them.
*
* This remains nullable so jobs queued before this property was introduced
* can still be processed after an application upgrade.
*/
public $operationId = null;

public function __construct(
public int $userId,
public int $devLinkId,
public string $class,
public int $id,
public string $importMode,
public string $type,
$operationId = null,
) {
$this->operationId = $operationId;
}

/**
Expand All @@ -51,7 +61,7 @@ public function handle(): void
//log
\Log::info('DevLinkInstall job started: ' . $this->devLinkId);
$devLink = DevLink::findOrFail($this->devLinkId);
$logger = new Logger($this->userId);
$logger = new Logger($this->userId, $this->operationId);

$lock = Cache::lock(ImportV2::CACHE_LOCK_KEY, ImportV2::RELEASE_LOCK_AFTER);

Expand Down Expand Up @@ -82,7 +92,7 @@ public function handle(): void

public function failed(Throwable $exception): void
{
(new Logger($this->userId))->exception($exception);
(new Logger($this->userId, $this->operationId))->exception($exception);

// Unlock the job
// We can't use $this->lock->release() here because this is run in a new instance
Expand Down
12 changes: 10 additions & 2 deletions resources/js/admin/devlink/components/AssetListing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import types from './assetTypes';
import moment from 'moment';
import Header from './Header.vue';
import InstallProgress from './InstallProgress.vue';
import createOperationId from '../createOperationId';

const route = useRoute();
const vue = getCurrentInstance().proxy;
Expand All @@ -20,6 +21,7 @@ const showInstallModal = ref(false);
const showConfirmModal = ref(false);
const selectedAsset = ref(null);
const installMode = ref('update');
const operationId = ref('');
const page = ref(1);
const perPage = ref(15);

Expand Down Expand Up @@ -89,12 +91,14 @@ const install = (asset) => {

const confirmInstall = () => {
if (selectedAsset.value) {
operationId.value = createOperationId();
showConfirmModal.value = false;
showInstallModal.value = true;
const params = {
class: typeConfig.class,
id: selectedAsset.value.id,
updateType: installMode.value
updateType: installMode.value,
operation_id: operationId.value,
};
ProcessMaker.apiClient
.post(`/devlink/${route.params.id}/install-remote-asset`, params)
Expand Down Expand Up @@ -210,7 +214,11 @@ const handleFilterChange = () => {

<!-- Progress Modal -->
<b-modal id="install-progress" size="lg" v-model="showInstallModal" :title="$t('Installation Progress')" hide-footer>
<install-progress />
<install-progress
v-if="operationId"
:key="operationId"
:operation-id="operationId"
/>
</b-modal>
</div>
</template>
Expand Down
8 changes: 8 additions & 0 deletions resources/js/admin/devlink/components/InstallProgress.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ import {
} from "vue";

const props = defineProps({
operationId: {
type: String,
required: true,
},
requestError: {
type: String,
default: "",
Expand Down Expand Up @@ -82,6 +86,10 @@ onMounted(() => {
window.Echo.private(`ProcessMaker.Models.User.${userId}`).listen(
'.ImportLog',
(response) => {
if (response.operationId !== props.operationId) {
return;
}

showSpinner.value = false;
if (response.type === 'progress') {
progress.value = response.message;
Expand Down
12 changes: 11 additions & 1 deletion resources/js/admin/devlink/components/Instance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import debounce from 'lodash/debounce';
import { useRouter, useRoute } from 'vue-router/composables';
import InstanceTabs from './InstanceTabs.vue';
import InstallProgress from './InstallProgress.vue';
import createOperationId from '../createOperationId';

const vue = getCurrentInstance().proxy;
const router = useRouter();
Expand All @@ -16,6 +17,7 @@ const warnings = ref([]);
const showInstallModal = ref(false);
const confirmUpdateVersion = ref(null);
const selectedOption = ref('update');
const operationId = ref('');
const bundleAttributes = {
id: null,
name: '',
Expand Down Expand Up @@ -88,20 +90,25 @@ const install = (bundle) => {
cancelTitle: vue.$t('Cancel')
}).then((confirm) => {
if (confirm) {
operationId.value = createOperationId();
showInstallModal.value = true;
ProcessMaker.apiClient
.post(`/devlink/${route.params.id}/remote-bundles/${bundle.id}/install`)
.post(`/devlink/${route.params.id}/remote-bundles/${bundle.id}/install`, {
operation_id: operationId.value,
})
.then((response) => {
// Handle the response as needed
});
}
});
};
const executeUpdate = (updateType) => {
operationId.value = createOperationId();
showInstallModal.value = true;
ProcessMaker.apiClient
.post(`/devlink/${route.params.id}/remote-bundles/${selected.value.id}/install`, {
updateType,
operation_id: operationId.value,
})
.then((response) => {
// Handle the response as needed
Expand Down Expand Up @@ -163,6 +170,9 @@ const executeUpdate = (updateType) => {
</div>
<b-modal id="install-progress" size="lg" v-model="showInstallModal" :title="$t('Installation Progress')" hide-footer>
<install-progress
v-if="operationId"
:key="operationId"
:operation-id="operationId"
@installation-complete="load"
/>
</b-modal>
Expand Down
10 changes: 7 additions & 3 deletions resources/js/admin/devlink/components/UpdateBundle.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<script setup>
import { ref, computed, getCurrentInstance, defineEmits, defineExpose } from 'vue';
import InstallProgress from './InstallProgress.vue';
import createOperationId from '../createOperationId';

const vue = getCurrentInstance().proxy;
const confirmUpdateVersion = ref(null);
const selected = ref(null);
const selectedOption = ref('update');
const showInstallModal = ref(false);
const installationInProgress = ref(false);
const installationAttempt = ref(0);
const requestError = ref("");
const reinstall = ref(false);
const operationId = ref('');
const title = computed(() => {
if (reinstall.value) {
return 'Reinstall Bundle';
Expand Down Expand Up @@ -48,8 +49,8 @@ const executeUpdate = (updateType) => {
}

installationInProgress.value = true;
installationAttempt.value += 1;
requestError.value = "";
operationId.value = createOperationId();
showInstallModal.value = true;
let url;
if (reinstall.value) {
Expand All @@ -61,6 +62,7 @@ const executeUpdate = (updateType) => {
ProcessMaker.apiClient
.post(url, {
updateType,
operation_id: operationId.value,
})
.catch((error) => {
const message = error?.response?.data?.message || error?.message;
Expand Down Expand Up @@ -125,7 +127,9 @@ const handleInstallationComplete = () => {
no-close-on-esc
>
<install-progress
:key="installationAttempt"
v-if="operationId"
:key="operationId"
:operation-id="operationId"
:request-error="requestError"
@installation-complete="handleInstallationComplete"
/>
Expand Down
9 changes: 9 additions & 0 deletions resources/js/admin/devlink/createOperationId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const createOperationId = () => {
if (typeof window.crypto?.randomUUID === "function") {
return window.crypto.randomUUID();
}

return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
};

export default createOperationId;
Loading
Loading