diff --git a/Caspian.WorkflowFramework.Package/Caspian.WorkflowFramework.Package.csproj b/Caspian.WorkflowFramework.Package/Caspian.WorkflowFramework.Package.csproj index e010b17..4ceae86 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.22 + 1.1.0-preview.25 Behzad Alizadeh Caspian Caspian.WorkflowFramework diff --git a/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs b/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs index 15ed277..09b9227 100644 --- a/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs +++ b/Caspian.WorkflowFramework.Package/Services/WorkflowService.cs @@ -6,7 +6,6 @@ using Elsa.Common.Models; using Elsa.Workflows; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Filters; -using Elsa.Workflows.Management.Services; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Filters; @@ -14,7 +13,6 @@ using Elsa.Workflows.Runtime.Messages; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Linq; using San.MongoLogger; using System.Diagnostics; using System.Dynamic; @@ -264,77 +262,119 @@ public class WorkflowService : IWorkflowService, ILoggable #endregion #region PublishEventAsync + /// - public async Task> PublishEventAsync(PublishEventModel input) + public async Task> PublishEventAsync( + PublishEventModel input) { var sw = Stopwatch.StartNew(); + try { - _logger.Log("Start of PublishEventAsync", WFInstanceId: input.WorkflowInstanceId, input); + _logger.Log( + "Start of PublishEventAsync", + WFInstanceId: input.WorkflowInstanceId, + input); - WorkflowResponse response; - - var instance = await _workflowInstanceManager.FindByIdAsync(input.WorkflowInstanceId); + var instance = await _workflowInstanceManager.FindByIdAsync( + input.WorkflowInstanceId); if (instance == null) { - var msg = $"Workflow instance with id '{input.WorkflowInstanceId}' not found"; - response = new WorkflowResponse() + var notFoundResponse = new WorkflowResponse { Status = 1, - Message = msg, + Message = + $"Workflow instance with id " + + $"'{input.WorkflowInstanceId}' not found", Data = null }; sw.Stop(); - _logger.Log("End of PublishEventAsync", WFInstanceId: input.WorkflowInstanceId, response, sw.ElapsedMilliseconds); + _logger.Log( + "End of PublishEventAsync", + WFInstanceId: input.WorkflowInstanceId, + notFoundResponse, + sw.ElapsedMilliseconds); - return response; + return notFoundResponse; } - ExpandoObject payload; + /* + * JsonElement + * ↓ + * ExpandoObject + * ↓ + * اضافه‌شدن SessionId + * ↓ + * PublishEvent + */ - var payloadObject = new JObject(); + ExpandoObject payload = new(); if (input.EventData.ValueKind is not JsonValueKind.Undefined and not JsonValueKind.Null) { if (input.EventData.ValueKind != JsonValueKind.Object) - throw new InvalidOperationException("EventData must be a JSON object."); + { + throw new InvalidOperationException( + "EventData must be a JSON object."); + } - payloadObject = JObject.Parse(input.EventData.GetRawText()); + var json = input.EventData.GetRawText(); + + var serializerSettings = new JsonSerializerSettings + { + Converters = + { + new ExpandoObjectConverter() + } + }; + + payload = + JsonConvert.DeserializeObject( + json, + serializerSettings) + ?? new ExpandoObject(); } + /* + * ExpandoObject پیاده‌سازی IDictionary است؛ + * بنابراین بدون Serialize/Deserialize مجدد می‌توانیم + * SessionId را به Payload اضافه کنیم. + */ if (!string.IsNullOrWhiteSpace(input.SessionId)) { - payloadObject["SessionId"] = input.SessionId; + var payloadDictionary = + (IDictionary)payload; + + payloadDictionary["SessionId"] = input.SessionId; } - var settings = new JsonSerializerSettings - { - Converters = { new ExpandoObjectConverter() } - }; + await _eventPublisher.PublishAsync( + eventName: input.EventName, + correlationId: null, + workflowInstanceId: input.WorkflowInstanceId, + activityInstanceId: null, + payload: payload, + asynchronous: false); - payload = JsonConvert.DeserializeObject( - payloadObject.ToString(Formatting.None), - settings - ) ?? new ExpandoObject(); + var variables = + await _workflowInstanceVariableManager.GetVariablesAsync( + input.WorkflowInstanceId); - //await _eventPublisher.PublishAsync(input.EventName, null, input.WorkflowInstanceId, null, input.EventData, asynchronous: true); - await _eventPublisher.PublishAsync(input.EventName, null, input.WorkflowInstanceId, null, payload); - - var variables = await _workflowInstanceVariableManager.GetVariablesAsync(input.WorkflowInstanceId); - - // تبدیل به دیکشنری - var dictionary = variables.ToDictionary(a => a.Variable.Name, a => a.Value); + var dictionary = variables.ToDictionary( + x => x.Variable.Name, + x => x.Value); var workflowModel = dictionary.ConvertToWorkflowModel(); + workflowModel.InstanceId = instance.Id; workflowModel.UserId = instance.ExternalUserId; workflowModel.InstanceMode = "exist"; - response = new WorkflowResponse() + var response = new WorkflowResponse { Status = 0, Message = "Success", @@ -343,26 +383,36 @@ public class WorkflowService : IWorkflowService, ILoggable sw.Stop(); - _logger.Log("End of PublishEventAsync", WFInstanceId: input.WorkflowInstanceId, response, sw.ElapsedMilliseconds); + _logger.Log( + "End of PublishEventAsync", + WFInstanceId: input.WorkflowInstanceId, + response, + sw.ElapsedMilliseconds); return response; } catch (Exception ex) { - var response = new WorkflowResponse() + sw.Stop(); + + var response = new WorkflowResponse { Status = 100, Message = ex.Message, Data = null }; - sw.Stop(); - - _logger.Log("Exception occurs in PublishEventAsync", WFInstanceId: input.WorkflowInstanceId, response, sw.ElapsedMilliseconds, ex); + _logger.Log( + "Exception occurs in PublishEventAsync", + WFInstanceId: input.WorkflowInstanceId, + response, + sw.ElapsedMilliseconds, + ex); return response; } } + #endregion #region InquiryStateAsync diff --git a/Caspian.WorkflowFramework.Package/Utility/WorkflowVariableExtensions.cs b/Caspian.WorkflowFramework.Package/Utility/WorkflowVariableExtensions.cs index eb19fd4..3751131 100644 --- a/Caspian.WorkflowFramework.Package/Utility/WorkflowVariableExtensions.cs +++ b/Caspian.WorkflowFramework.Package/Utility/WorkflowVariableExtensions.cs @@ -1,226 +1,28 @@ -using System.Collections; -using System.Text.Json; -using System.Text.Json.Nodes; -using Newtonsoft.Json.Linq; - -namespace Caspian.WorkflowFramework.Utility; +namespace Caspian.WorkflowFramework.Utility; public static class WorkflowVariableExtensions { private const string SessionIdKey = "SessionId"; /// - /// sessionId را از دیکشنری اصلی و تمام مقادیر تو در تو حذف می‌کند. + /// SessionId را فقط از سطح اول دیکشنری متغیرهای Workflow حذف می‌کند. + /// مقایسه نام کلید به حروف بزرگ و کوچک حساس نیست. /// public static Dictionary RemoveSessionId( this Dictionary variables) { - if (variables == null || variables.Count == 0) - return variables; + if (variables is null || variables.Count == 0) + return variables!; - RemoveSessionIdKeys(variables); + var sessionIdKey = variables.Keys.FirstOrDefault( + key => string.Equals( + key, + SessionIdKey, + StringComparison.OrdinalIgnoreCase)); - foreach (var key in variables.Keys.ToList()) - variables[key] = RemoveSessionIdRecursive(variables[key]); + if (sessionIdKey is not null) + variables.Remove(sessionIdKey); return variables; } - - private static object? RemoveSessionIdRecursive(object? value) - { - if (value == null) - return null; - - switch (value) - { - // Dictionary و ExpandoObject - case IDictionary dictionary: - { - RemoveSessionIdKeys(dictionary); - - foreach (var key in dictionary.Keys.ToList()) - dictionary[key] = RemoveSessionIdRecursive(dictionary[key]); - - return value; - } - - // System.Text.Json.Nodes - case JsonObject jsonObject: - { - RemoveSessionIdKeys(jsonObject); - - foreach (var property in jsonObject.ToList()) - jsonObject[property.Key] = - RemoveSessionIdFromJsonNode(property.Value); - - return jsonObject; - } - - case JsonArray jsonArray: - { - for (var i = 0; i < jsonArray.Count; i++) - { - jsonArray[i] = - RemoveSessionIdFromJsonNode(jsonArray[i]); - } - - return jsonArray; - } - - // JsonElement تغییرپذیر نیست؛ پس نسخه پاک‌سازی‌شده می‌سازیم. - case JsonElement jsonElement: - { - var node = JsonNode.Parse(jsonElement.GetRawText()); - - if (node == null) - return jsonElement; - - var cleanedNode = RemoveSessionIdFromJsonNode(node); - - return cleanedNode == null - ? jsonElement - : JsonSerializer.SerializeToElement(cleanedNode); - } - - // Newtonsoft.Json - case JObject jObject: - { - RemoveSessionIdKeys(jObject); - - foreach (var property in jObject.Properties().ToList()) - property.Value = RemoveSessionIdFromJToken(property.Value); - - return jObject; - } - - case JArray jArray: - { - for (var i = 0; i < jArray.Count; i++) - jArray[i] = RemoveSessionIdFromJToken(jArray[i]); - - return jArray; - } - - // سایر لیست‌ها و آرایه‌ها - case IList list: - { - for (var i = 0; i < list.Count; i++) - list[i] = RemoveSessionIdRecursive(list[i]); - - return list; - } - - case IEnumerable enumerable when value is not string: - { - foreach (var child in enumerable) - RemoveSessionIdRecursive(child); - - return value; - } - - default: - return value; - } - } - - private static JsonNode? RemoveSessionIdFromJsonNode(JsonNode? node) - { - if (node == null) - return null; - - switch (node) - { - case JsonObject jsonObject: - { - RemoveSessionIdKeys(jsonObject); - - foreach (var property in jsonObject.ToList()) - { - jsonObject[property.Key] = - RemoveSessionIdFromJsonNode(property.Value); - } - - break; - } - - case JsonArray jsonArray: - { - for (var i = 0; i < jsonArray.Count; i++) - { - jsonArray[i] = - RemoveSessionIdFromJsonNode(jsonArray[i]); - } - - break; - } - } - - return node; - } - - private static JToken RemoveSessionIdFromJToken(JToken token) - { - switch (token) - { - case JObject jObject: - { - RemoveSessionIdKeys(jObject); - - foreach (var property in jObject.Properties().ToList()) - property.Value = RemoveSessionIdFromJToken(property.Value); - - break; - } - - case JArray jArray: - { - for (var i = 0; i < jArray.Count; i++) - jArray[i] = RemoveSessionIdFromJToken(jArray[i]); - - break; - } - } - - return token; - } - - private static void RemoveSessionIdKeys( - IDictionary dictionary) - { - var keys = dictionary.Keys - .Where(IsSessionId) - .ToList(); - - foreach (var key in keys) - dictionary.Remove(key); - } - - private static void RemoveSessionIdKeys(JsonObject jsonObject) - { - var keys = jsonObject - .Select(x => x.Key) - .Where(IsSessionId) - .ToList(); - - foreach (var key in keys) - jsonObject.Remove(key); - } - - private static void RemoveSessionIdKeys(JObject jObject) - { - var properties = jObject.Properties() - .Where(x => IsSessionId(x.Name)) - .ToList(); - - foreach (var property in properties) - property.Remove(); - } - - private static bool IsSessionId(string key) - { - return string.Equals( - key, - SessionIdKey, - StringComparison.OrdinalIgnoreCase); - } } \ No newline at end of file