diff --git a/Caspian.WorkflowFramework.Package/Caspian.WorkflowFramework.Package.csproj b/Caspian.WorkflowFramework.Package/Caspian.WorkflowFramework.Package.csproj
index 3365e3d..bbe623d 100644
--- a/Caspian.WorkflowFramework.Package/Caspian.WorkflowFramework.Package.csproj
+++ b/Caspian.WorkflowFramework.Package/Caspian.WorkflowFramework.Package.csproj
@@ -5,7 +5,7 @@
enable
enable
Caspian.WorkflowFramework
- 1.1.0-preview.17
+ 1.1.0-preview.18
Behzad Alizadeh
Caspian
Caspian.WorkflowFramework
@@ -20,55 +20,55 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Caspian.WorkflowFramework.Package/Contracts/IWorkflowService.cs b/Caspian.WorkflowFramework.Package/Contracts/IWorkflowService.cs
index a20639f..0dc221b 100644
--- a/Caspian.WorkflowFramework.Package/Contracts/IWorkflowService.cs
+++ b/Caspian.WorkflowFramework.Package/Contracts/IWorkflowService.cs
@@ -48,5 +48,15 @@ namespace Caspian.WorkflowFramework.Contracts
/// Cancels the specified workflow instance.
///
Task> CancelInstanceAsync(CancelWorkflowInstanceModel input);
+
+ ///
+ /// Cancels the specified workflow instance.
+ ///
+ Task> ForceCancelInstanceAsync(CancelWorkflowInstanceModel input);
+
+ ///
+ /// Evicts a workflow definition from cache (optional, commented out in service).
+ ///
+ Task EvictDefFromCacheAsync(string name, CancellationToken cancellationToken = default);
}
}
diff --git a/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs b/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs
index aad096c..5819a6f 100644
--- a/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs
+++ b/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs
@@ -1,7 +1,4 @@
-using System.Diagnostics;
-using System.Dynamic;
-using System.Text.Json;
-using Caspian.WorkflowFramework.Contracts;
+using Caspian.WorkflowFramework.Contracts;
using Caspian.WorkflowFramework.Models;
using Caspian.WorkflowFramework.Utility;
using Elsa.Common.Entities;
@@ -11,11 +8,15 @@ using Elsa.Workflows.Management;
using Elsa.Workflows.Management.Filters;
using Elsa.Workflows.Models;
using Elsa.Workflows.Runtime;
+using Elsa.Workflows.Runtime.Filters;
using Elsa.Workflows.Runtime.Messages;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using San.MongoLogger;
+using System.Diagnostics;
+using System.Dynamic;
+using System.Text.Json;
namespace Caspian.WorkflowFramework.Services;
public class WorkflowService : IWorkflowService, ILoggable
@@ -29,6 +30,8 @@ public class WorkflowService : IWorkflowService, ILoggable
private readonly IWorkflowInstanceStore _workflowInstanceStore;
private readonly IEventPublisher _eventPublisher;
private readonly IWorkflowDefinitionCacheManager _workflowDefinitionCacheManager;
+ private readonly IBookmarkStore _bookmarkStore;
+ private readonly IActivityExecutionStore _activityExecutionStore;
private readonly IMdbLogger _logger;
#endregion
@@ -43,6 +46,8 @@ public class WorkflowService : IWorkflowService, ILoggable
_workflowInstanceManager = _serviceProvider.GetRequiredService();
_workflowInstanceStore = _serviceProvider.GetRequiredService();
_eventPublisher = _serviceProvider.GetRequiredService();
+ _bookmarkStore = _serviceProvider.GetRequiredService();
+ _activityExecutionStore = _serviceProvider.GetRequiredService();
_logger = logger;
}
#endregion
@@ -724,4 +729,117 @@ public class WorkflowService : IWorkflowService, ILoggable
}
}
#endregion
+
+ #region ForceCancelInstanceAsync
+ public async Task> ForceCancelInstanceAsync(CancelWorkflowInstanceModel input)
+ {
+ var sw = Stopwatch.StartNew();
+ try
+ {
+ _logger.Log("Start ForceCancelInstanceAsync", WFInstanceId: input.WorkflowInstanceId, input);
+
+ var instance = await _workflowInstanceManager.FindByIdAsync(input.WorkflowInstanceId);
+
+ if (instance == null)
+ return new WorkflowResponse { Status = 1, Message = "Instance not found", Data = false };
+
+ // جلوگری از Resume شدن دوباره
+ instance.Status = WorkflowStatus.Finished;
+ instance.SubStatus = WorkflowSubStatus.Cancelled;
+
+ // پاکسازی bookmarks از دیتابیس واقعی
+ var bookmarkFilter = new BookmarkFilter()
+ {
+ WorkflowInstanceId = input.WorkflowInstanceId
+ };
+ await _bookmarkStore.DeleteAsync(bookmarkFilter);
+
+ // پاکسازی scheduled activities (در صورتی که runtime distributed باشد)
+ var activityFilter = new ActivityExecutionRecordFilter()
+ {
+ WorkflowInstanceId = input.WorkflowInstanceId
+ };
+ await _activityExecutionStore.DeleteManyAsync(activityFilter);
+
+ //// پاکسازی incidents (در پروژههای بزرگ ضروری است)
+ //await _incidentStore.DeleteManyAsync(
+ // x => x.WorkflowInstanceId == input.WorkflowInstanceId
+ //);
+
+ // ذخیره instance تغییر یافته
+ await _workflowInstanceManager.SaveAsync(instance);
+
+ sw.Stop();
+
+ var response = new WorkflowResponse
+ {
+ Status = 0,
+ Message = "Force cancel completed",
+ Data = true
+ };
+
+ _logger.Log("End ForceCancelInstanceAsync", WFInstanceId: instance.Id, response, sw.ElapsedMilliseconds);
+
+ return response;
+ }
+ catch (Exception ex)
+ {
+ sw.Stop();
+
+ var response = new WorkflowResponse
+ {
+ Status = 100,
+ Message = ex.Message,
+ Data = false
+ };
+
+ _logger.Log("Exception in ForceCancelInstanceAsync", WFInstanceId: input.WorkflowInstanceId, response, sw.ElapsedMilliseconds, ex);
+
+ return response;
+ }
+ }
+
+ #endregion
+
+ #region EvictDefFromCacheAsync
+ ///
+ public async Task EvictDefFromCacheAsync(string name, CancellationToken cancellationToken = default)
+ {
+ var sw = Stopwatch.StartNew();
+
+ try
+ {
+ _logger.Log("Start of EvictDefFromCacheAsync", name);
+
+ var defFilter = new WorkflowDefinitionFilter()
+ {
+ Name = name,
+ VersionOptions = VersionOptions.Published
+ };
+
+ var definition = await _workflowDefinitionService
+ .FindWorkflowDefinitionAsync(defFilter);
+
+ await _workflowDefinitionCacheManager.EvictWorkflowDefinitionAsync(definition.DefinitionId);
+
+ var workflowDefinitionFilter = new WorkflowDefinitionFilter()
+ {
+ DefinitionHandle = WorkflowDefinitionHandle.ByDefinitionId(definition.DefinitionId, VersionOptions.Published)
+ };
+
+ var createWorkflowDefinitionFilterCacheKey = _workflowDefinitionCacheManager.CreateWorkflowDefinitionFilterCacheKey(workflowDefinitionFilter);
+ _workflowDefinitionCacheManager.Cache.Remove(createWorkflowDefinitionFilterCacheKey);
+
+
+ var createWorkflowFilterCacheKey = _workflowDefinitionCacheManager.CreateWorkflowFilterCacheKey(workflowDefinitionFilter);
+ _workflowDefinitionCacheManager.Cache.Remove(createWorkflowFilterCacheKey);
+ }
+ finally
+ {
+ sw.Stop();
+ _logger.Log("End of EvictDefFromCacheAsync", name, sw.ElapsedMilliseconds, null);
+ }
+ }
+
+ #endregion
}
\ No newline at end of file
diff --git a/NuGet.Config b/NuGet.Config
index 5af4652..5691179 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -9,5 +9,6 @@
+
\ No newline at end of file