From aa5663006cfb555dd17f4933552b4554782dfa4b Mon Sep 17 00:00:00 2001 From: Rainer Wittmann Date: Mon, 25 Oct 2021 13:56:46 +0200 Subject: [PATCH 1/2] add correlationId filter to instance view (#2406) --- .../elsa-workflows-studio/src/components.d.ts | 2 + .../elsa-workflow-instance-list-screen.tsx | 40 ++++++++++++++----- .../src/services/elsa-client.ts | 7 +++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/designer/elsa-workflows-studio/src/components.d.ts b/src/designer/elsa-workflows-studio/src/components.d.ts index 6ad0fbc5b..f1803f8ee 100644 --- a/src/designer/elsa-workflows-studio/src/components.d.ts +++ b/src/designer/elsa-workflows-studio/src/components.d.ts @@ -291,6 +291,7 @@ export namespace Components { } interface ElsaWorkflowInstanceListScreen { "basePath": string; + "correlationId"?: string; "culture": string; "getSelectedWorkflowInstanceIds": () => Promise; "history"?: RouterHistory; @@ -1008,6 +1009,7 @@ declare namespace LocalJSX { } interface ElsaWorkflowInstanceListScreen { "basePath"?: string; + "correlationId"?: string; "culture"?: string; "history"?: RouterHistory; "orderBy"?: OrderBy; diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-list/elsa-workflow-instance-list-screen/elsa-workflow-instance-list-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-list/elsa-workflow-instance-list-screen/elsa-workflow-instance-list-screen.tsx index e5fd6ba09..b121ca103 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-list/elsa-workflow-instance-list-screen/elsa-workflow-instance-list-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-list/elsa-workflow-instance-list-screen/elsa-workflow-instance-list-screen.tsx @@ -35,6 +35,7 @@ export class ElsaWorkflowInstanceListScreen { @Prop() serverUrl: string; @Prop() basePath: string; @Prop() workflowId?: string; + @Prop() correlationId?: string; @Prop() workflowStatus?: WorkflowStatus; @Prop() orderBy?: OrderBy = OrderBy.Started; @Prop() culture: string; @@ -42,10 +43,12 @@ export class ElsaWorkflowInstanceListScreen { @State() workflowBlueprints: Array = []; @State() workflowInstances: PagedList = {items: [], page: 1, pageSize: 50, totalCount: 0}; @State() selectedWorkflowId?: string; + @State() selectedCorrelationId?: string; @State() selectedWorkflowStatus?: WorkflowStatus; @State() selectedOrderByState?: OrderBy = OrderBy.Started; @State() selectedWorkflowInstanceIds: Array = []; @State() selectAllChecked: boolean; + @State() currentPage: number = 0; @State() currentPageSize: number = ElsaWorkflowInstanceListScreen.DEFAULT_PAGE_SIZE; @State() currentSearchTerm?: string; @@ -96,6 +99,12 @@ export class ElsaWorkflowInstanceListScreen { await this.loadWorkflowInstances(); } + @Watch("correlationId") + async handleCorrelationIdChanged(value: string) { + this.selectedCorrelationId = value; + await this.loadWorkflowInstances(); + } + @Watch("workflowStatus") async handleWorkflowStatusChanged(value: WorkflowStatus) { this.selectedWorkflowStatus = value; @@ -122,6 +131,7 @@ export class ElsaWorkflowInstanceListScreen { const query = parseQuery(queryString); this.selectedWorkflowId = query.workflow; + this.correlationId = query.correlationId; this.selectedWorkflowStatus = query.status; this.selectedOrderByState = query.orderBy ?? OrderBy.Started; this.currentPage = !!query.page ? parseInt(query.page) : 0; @@ -143,11 +153,11 @@ export class ElsaWorkflowInstanceListScreen { this.currentPage = Math.max(this.currentPage, ElsaWorkflowInstanceListScreen.START_PAGE); this.currentPageSize = isNaN(this.currentPageSize) ? ElsaWorkflowInstanceListScreen.DEFAULT_PAGE_SIZE : this.currentPageSize; const elsaClient = await this.createClient(); - this.workflowInstances = await elsaClient.workflowInstancesApi.list(this.currentPage, this.currentPageSize, this.selectedWorkflowId, this.selectedWorkflowStatus, this.selectedOrderByState, this.currentSearchTerm); + this.workflowInstances = await elsaClient.workflowInstancesApi.list(this.currentPage, this.currentPageSize, this.selectedWorkflowId, this.selectedWorkflowStatus, this.selectedOrderByState, this.currentSearchTerm, this.correlationId); const maxPage = Math.floor(this.workflowInstances.totalCount / this.currentPageSize); if (this.currentPage > maxPage) { this.currentPage = maxPage; - this.workflowInstances = await elsaClient.workflowInstancesApi.list(this.currentPage, this.currentPageSize, this.selectedWorkflowId, this.selectedWorkflowStatus, this.selectedOrderByState, this.currentSearchTerm); + this.workflowInstances = await elsaClient.workflowInstancesApi.list(this.currentPage, this.currentPageSize, this.selectedWorkflowId, this.selectedWorkflowStatus, this.selectedOrderByState, this.currentSearchTerm, this.correlationId); } this.setSelectAllIndeterminateState(); } @@ -161,9 +171,12 @@ export class ElsaWorkflowInstanceListScreen { return collection.map(groups, x => array.first(collection.sortBy(x, 'version', 'desc'))); } - buildFilterUrl(workflowId?: string, workflowStatus?: WorkflowStatus, orderBy?: OrderBy, pageSize?: number) { + buildFilterUrl(workflowId?: string, workflowStatus?: WorkflowStatus, orderBy?: OrderBy, pageSize?: number, correlationId?: string) { const filters: Map = {}; + if (!!correlationId) + filters['correlationId'] = correlationId; + if (!!workflowId) filters['workflow'] = workflowId; @@ -510,6 +523,8 @@ export class ElsaWorkflowInstanceListScreen { const displayName = workflowBlueprint.displayName || workflowBlueprint.name || 'Untitled'; const statusColor = this.getStatusColor(workflowInstance.workflowStatus); const instanceViewUrl = `${basePath}/workflow-instances/${workflowInstance.id}`; + const correlationId = !!workflowInstance.correlationId ? workflowInstance.correlationId : '' + const correlationListViewUrl = `${basePath}/workflow-instances?correlationId=${correlationId}`; const blueprintViewUrl = `${basePath}/workflow-registry/${workflowInstance.definitionId}`; const instanceName = !workflowInstance.name ? '' : workflowInstance.name; const isSelected = this.selectedWorkflowInstanceIds.findIndex(x => x === workflowInstance.id) >= 0; @@ -531,8 +546,9 @@ export class ElsaWorkflowInstanceListScreen { anchorClass="elsa-truncate hover:elsa-text-gray-600">{workflowInstance.id} - {!!workflowInstance.correlationId ? workflowInstance.correlationId : ''} + class="elsa-px-6 elsa-py-3 elsa-whitespace-no-wrap elsa-text-sm elsa-leading-5 elsa-font-medium elsa-text-gray-900"> + {correlationId} @@ -616,6 +632,7 @@ export class ElsaWorkflowInstanceListScreen { renderWorkflowFilter() { const t = this.t; const latestWorkflowBlueprints = this.getLatestWorkflowBlueprintVersions(); + const selectedCorrelationId = this.selectedCorrelationId; const selectedWorkflowId = this.selectedWorkflowId; const selectedWorkflow = latestWorkflowBlueprints.find(x => x.id == selectedWorkflowId); const selectedWorkflowText = !selectedWorkflowId ? t('Filters.Workflow.Label') : !!selectedWorkflow && (selectedWorkflow.name || selectedWorkflow.displayName) ? (selectedWorkflow.displayName || selectedWorkflow.name) : t('Untitled'); @@ -628,7 +645,7 @@ export class ElsaWorkflowInstanceListScreen { const item: DropdownButtonItem = {text: displayName, value: x.id, isSelected: x.id == selectedWorkflowId}; if (!!history) - item.url = this.buildFilterUrl(x.id, selectedWorkflowStatus, selectedOrderBy, null); + item.url = this.buildFilterUrl(x.id, selectedWorkflowStatus, selectedOrderBy, null, selectedCorrelationId); return item; }); @@ -636,7 +653,7 @@ export class ElsaWorkflowInstanceListScreen { const allItem: DropdownButtonItem = {text: t('Filters.Workflow.All'), value: null, isSelected: !selectedWorkflowId}; if (!!history) - allItem.url = this.buildFilterUrl(null, selectedWorkflowStatus, selectedOrderBy, null); + allItem.url = this.buildFilterUrl(null, selectedWorkflowStatus, selectedOrderBy, null, selectedCorrelationId); items = [allItem, ...items]; @@ -658,6 +675,7 @@ export class ElsaWorkflowInstanceListScreen { renderStatusFilter() { const t = this.t; + const selectedCorrelationId = this.correlationId; const selectedWorkflowStatus = this.selectedWorkflowStatus; const selectedWorkflowStatusText = !!selectedWorkflowStatus ? selectedWorkflowStatus : t('Filters.Status.Label'); const statuses: Array = [null, WorkflowStatus.Running, WorkflowStatus.Suspended, WorkflowStatus.Finished, WorkflowStatus.Faulted, WorkflowStatus.Cancelled, WorkflowStatus.Idle]; @@ -668,7 +686,7 @@ export class ElsaWorkflowInstanceListScreen { const item: DropdownButtonItem = {text: text, isSelected: x == selectedWorkflowStatus, value: x}; if (!!history) - item.url = this.buildFilterUrl(this.selectedWorkflowId, x, this.selectedOrderByState, null); + item.url = this.buildFilterUrl(this.selectedWorkflowId, x, this.selectedOrderByState, null, selectedCorrelationId); return item; }); @@ -688,6 +706,7 @@ export class ElsaWorkflowInstanceListScreen { renderPageSizeFilter() { const t = this.t; + const selectedCorrelationId = this.correlationId; const currentPageSize = this.currentPageSize; const currentPageSizeText = t('Filters.PageSize.SelectedLabel', {Size: currentPageSize}); const pageSizes: Array = [5, 10, 15, 20, 30, 50, 100]; @@ -698,7 +717,7 @@ export class ElsaWorkflowInstanceListScreen { const item: DropdownButtonItem = {text: text, isSelected: x == currentPageSize, value: x}; if (!!history) - item.url = this.buildFilterUrl(this.selectedWorkflowId, this.selectedWorkflowStatus, this.selectedOrderByState, x); + item.url = this.buildFilterUrl(this.selectedWorkflowId, this.selectedWorkflowStatus, this.selectedOrderByState, x, selectedCorrelationId); return item; }); @@ -717,6 +736,7 @@ export class ElsaWorkflowInstanceListScreen { renderOrderByFilter() { const t = this.t; + const selectedCorrelationId = this.correlationId; const selectedOrderBy = this.selectedOrderByState; const selectedOrderByText = !!selectedOrderBy ? t('Filters.Sort.SelectedLabel', {Key: selectedOrderBy}) : t('Filters.Sort.Label'); const orderByValues: Array = [OrderBy.Finished, OrderBy.LastExecuted, OrderBy.Started]; @@ -726,7 +746,7 @@ export class ElsaWorkflowInstanceListScreen { const item: DropdownButtonItem = {text: x, value: x, isSelected: x == selectedOrderBy}; if (!!history) - item.url = this.buildFilterUrl(this.selectedWorkflowId, this.selectedWorkflowStatus, x, null); + item.url = this.buildFilterUrl(this.selectedWorkflowId, this.selectedWorkflowStatus, x, null, selectedCorrelationId); return item; }); diff --git a/src/designer/elsa-workflows-studio/src/services/elsa-client.ts b/src/designer/elsa-workflows-studio/src/services/elsa-client.ts index 2aceab837..43ef7d793 100644 --- a/src/designer/elsa-workflows-studio/src/services/elsa-client.ts +++ b/src/designer/elsa-workflows-studio/src/services/elsa-client.ts @@ -137,12 +137,15 @@ export const createElsaClient = async function (serverUrl: string): Promise> => { + list: async (page?: number, pageSize?: number, workflowDefinitionId?: string, workflowStatus?: WorkflowStatus, orderBy?: OrderBy, searchTerm?: string, correlationId?: string): Promise> => { const queryString = {}; if (!!workflowDefinitionId) queryString['workflow'] = workflowDefinitionId; + if (!!correlationId) + queryString['correlationId'] = correlationId; + if (workflowStatus != null) queryString['status'] = workflowStatus; @@ -292,7 +295,7 @@ export interface WorkflowRegistryApi { } export interface WorkflowInstancesApi { - list(page?: number, pageSize?: number, workflowDefinitionId?: string, workflowStatus?: WorkflowStatus, orderBy?: OrderBy, searchTerm?: string): Promise>; + list(page?: number, pageSize?: number, workflowDefinitionId?: string, workflowStatus?: WorkflowStatus, orderBy?: OrderBy, searchTerm?: string, correlationId?: string): Promise>; get(id: string): Promise; From 86dd2f91bb717d0d5eede1f73022c291198d7605 Mon Sep 17 00:00:00 2001 From: noxe Date: Tue, 26 Oct 2021 10:11:49 +0200 Subject: [PATCH 2/2] Change RunWorkflowInternalAsync to protected virtual (#2408) Co-authored-by: Martin --- src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs b/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs index 38049cf01..36bc813d9 100644 --- a/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs +++ b/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs @@ -69,8 +69,8 @@ namespace Elsa.Services.Workflows await workflowExecutionContext.WorkflowExecutionLog.FlushAsync(cancellationToken); return result; } - - private async Task RunWorkflowInternalAsync(WorkflowExecutionContext workflowExecutionContext, string? activityId = default, CancellationToken cancellationToken = default) + + protected virtual async Task RunWorkflowInternalAsync(WorkflowExecutionContext workflowExecutionContext, string? activityId = default, CancellationToken cancellationToken = default) { var workflowInstance = workflowExecutionContext.WorkflowInstance; @@ -175,7 +175,7 @@ namespace Elsa.Services.Workflows { _logger.LogWarning(e, "Failed to run workflow {WorkflowInstanceId}", workflowExecutionContext.WorkflowInstance.Id); workflowExecutionContext.Fault(e, activity.Id, null, false); - workflowExecutionContext.AddEntry(activity, "Faulted", null, SimpleException.FromException(e)); + workflowExecutionContext.AddEntry(activity, "Faulted", null, SimpleException.FromException(e)); } return new RunWorkflowResult(workflowExecutionContext.WorkflowInstance, activity.Id, false);