From e5ea61ae1a2c006bf75ed9c047bf83d378a9efca Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Thu, 26 May 2022 23:34:05 -0300 Subject: [PATCH 01/14] Implementation API Queue. Issue 96198 --- dotnet/DotNetStandardClasses.sln | 20 + .../GxClasses/Properties/AssemblyInfo.cs | 3 +- .../Messaging/GXAzureQueue/AzureQueue.cs | 439 ++++++++++++++++++ .../GXAzureQueue/GXAzureQueue.csproj | 16 + .../Messaging/GXQueue/GXQueue.csproj | 12 + .../Messaging/GXQueue/MessageQueueProvider.cs | 111 +++++ .../Providers/Messaging/GXQueue/Queue.cs | 125 +++++ .../Providers/Messaging/GXQueue/QueueBase.cs | 37 ++ .../Messaging/GXQueue/ServiceSettings.cs | 101 ++++ .../Messaging/GXQueue/SimpleMessageQueue.cs | 253 ++++++++++ .../GxClasses/Services/Storage/GXServices.cs | 1 + .../DotNetCoreUnitTest.csproj | 3 +- 12 files changed, 1119 insertions(+), 2 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index eeaf8caad..cc6023025 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -188,6 +188,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GxXsl", "src\dotnetcore\GxXsl\GxXsl.csproj", "{30E7E437-F9B0-42B8-9144-A8E8F972B462}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXAzureQueue", "src\dotnetcore\Providers\Messaging\GXAzureQueue\GXAzureQueue.csproj", "{0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "messaging", "messaging", "{30159B0F-BE61-4DB7-AC02-02851426BE4B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{4C43F2DA-59E5-46F5-B691-195449498555}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXQueue", "src\dotnetcore\Providers\Messaging\GXQueue\GXQueue.csproj", "{C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -462,6 +470,14 @@ Global {30E7E437-F9B0-42B8-9144-A8E8F972B462}.Debug|Any CPU.Build.0 = Debug|Any CPU {30E7E437-F9B0-42B8-9144-A8E8F972B462}.Release|Any CPU.ActiveCfg = Release|Any CPU {30E7E437-F9B0-42B8-9144-A8E8F972B462}.Release|Any CPU.Build.0 = Release|Any CPU + {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Release|Any CPU.Build.0 = Release|Any CPU + {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -552,6 +568,10 @@ Global {B59F76D8-FDB2-4F51-89DB-F15E9BDFF1DC} = {420E8A4A-11D9-42E9-BFB7-4325EA7330B8} {D97E17A4-C945-4BF3-957E-F73142C4C6D0} = {947E032A-C385-4586-96E3-FC7D2767F082} {30E7E437-F9B0-42B8-9144-A8E8F972B462} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3} + {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} + {30159B0F-BE61-4DB7-AC02-02851426BE4B} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3} + {4C43F2DA-59E5-46F5-B691-195449498555} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} + {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82} = {4C43F2DA-59E5-46F5-B691-195449498555} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs index ac4308186..5c9ad0030 100644 --- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs @@ -3,4 +3,5 @@ [assembly: InternalsVisibleTo("GxClasses.Web")] [assembly: InternalsVisibleTo("GxSearch")] -[assembly: InternalsVisibleTo("GxNetCoreStartup")] \ No newline at end of file +[assembly: InternalsVisibleTo("GxNetCoreStartup")] +[assembly: InternalsVisibleTo("GXQueue")] \ No newline at end of file diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs new file mode 100644 index 000000000..a23ff4f78 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -0,0 +1,439 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading.Tasks; +using Azure.Storage.Queues; +using Azure.Storage.Queues.Models; +using GeneXus.Messaging.Common; +using GeneXus.Services; +using GeneXus.Utils; + +namespace GeneXus.Messaging.Queue +{ + public class AzureQueue : QueueBase, IQueue + { + + public static String Name = "AZUREQUEUE"; + const string QUEUE_NAME = "QUEUENAME"; + const string QUEUE_CONNECTION_STRING = "CONNECTIONSTRING"; + + QueueClient _queueClient { get; set; } + private string _queueName { get; set; } + private string _connectionString { get; set; } + + public AzureQueue() : this(null) + { + } + + public AzureQueue(GXService providerService) : base(providerService) + { + Initialize(providerService); + } + + private void Initialize(GXService providerService) + { + ServiceSettings serviceSettings = new("QUEUE", Name, providerService); + _queueName = serviceSettings.GetEncryptedPropertyValue(QUEUE_NAME); + _connectionString = serviceSettings.GetEncryptedPropertyValue(QUEUE_CONNECTION_STRING); + + if (_queueClient == null) + _queueClient = new QueueClient(_connectionString, _queueName); + } + + QueueClient QueueClient + { + get + { + if (_queueClient == null) + _queueClient = new QueueClient(_connectionString, _queueName); + return _queueClient; + } + } + + public AzureQueue(string connectionString, string queueName) + { + _queueName = queueName; + _connectionString = connectionString; + } + + //public AzureQueue(Uri uri, TokenCredential tokenCredential) + //{ + //_queueClient = new QueueClient(uri, tokenCredential); + //} + + public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) + { + try + { + msg.gxTpr_Description = ex.Message; + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Get the approximate number of messages in the queue + /// + /// + /// + public int GetQueueLength(out bool success) + { + int cachedMessagesCount = 0; + success = false; + if (_queueClient is QueueClient && _queueClient.Exists()) + { + QueueProperties properties = _queueClient.GetProperties(); + + // Retrieve the cached approximate message count. + cachedMessagesCount = properties.ApproximateMessagesCount; + success = true; + } + return cachedMessagesCount; + } + + /// + /// Deletes all messages from a queue. + /// + public void Clear(out bool success) + { + success = false; + if (_queueClient is QueueClient && _queueClient.Exists()) + { + Azure.Response result = _queueClient.ClearMessages(); + success = !result.IsError; + } + } + + public Task ClearAsync(out bool success) + { + success = false; + if (_queueClient is QueueClient && _queueClient.Exists()) + { + Task result = _queueClient.ClearMessagesAsync(); + success = !result.Result.IsError; + return (result); + } + return null; + } + + /// + /// Permanently removes the first message dequeued. + /// + + public MessageQueueResult DeleteMessage(out bool success) + { + success=false; + MessageQueueResult messageQueueResult = new MessageQueueResult(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + Azure.Response receivedMessage = _queueClient.ReceiveMessage(); + + if ((receivedMessage != null) && (!receivedMessage.GetRawResponse().IsError) && (receivedMessage.Value != null)) + { + Azure.Response deleteResult = _queueClient.DeleteMessage(receivedMessage.Value.MessageId, receivedMessage.Value.PopReceipt); + + success = !deleteResult.IsError; + if (success) + { + return (AzQueueMessageToMessageQueueResult(receivedMessage.Value, MessageQueueResultStatus.Deleted)); + } + } + } + return messageQueueResult; + } + + /// + /// Deletes permanently the messages given on the list. + /// + + public IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions,out bool success) + { + success = false; + IList messageQueueResults = new List(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + QueueProperties properties = _queueClient.GetProperties(); + int count = properties.ApproximateMessagesCount; + //If maxMessages is 0, receive using blocks until count = 0 + + QueueMessage[] receivedMessages = _queueClient.ReceiveMessages(messageQueueOptions.MaxNumberOfMessages); + Azure.Response deleteResult; + foreach (QueueMessage message in receivedMessages) + { + if (messageHandleId.Contains(message.MessageId) ) + { + deleteResult = _queueClient.DeleteMessage(message?.MessageId, message?.PopReceipt); + if ((deleteResult != null) && (!deleteResult.IsError) && message is QueueMessage) + messageQueueResults.Add(AzQueueMessageToMessageQueueResult(queueMessage: message, status: MessageQueueResultStatus.Deleted)); + } + } + success = true; + } + return messageQueueResults; + } + + /// + /// Retrieves all the messages from the queue. + /// + public IList GetMessages(out bool success) + { + success = false; + IList simpleQueueMessages = new List(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + Azure.Response messageResponse; + + messageResponse = _queueClient.ReceiveMessages(); + + if (messageResponse.Value != null) + { + foreach (QueueMessage message in messageResponse.Value) + { + simpleQueueMessages.Add(AzQueueMessageToSimpleQueueMessage(message)); + + } + } + success = true; + } + return simpleQueueMessages; + } + + /// + /// Retrieves mesages from the queue, given some options. + /// + public IList GetMessages(MessageQueueOptions messageQueueOptions, out bool success) + { + success = false; + bool deleteSuccess = true; + IList simpleQueueMessages = new List(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + Azure.Response messageResponse; + if (messageQueueOptions.MaxNumberOfMessages != 0) + + messageResponse = _queueClient.ReceiveMessages(messageQueueOptions.MaxNumberOfMessages, TimeSpan.FromSeconds(messageQueueOptions.VisibilityTimeout)); + else + messageResponse = _queueClient.ReceiveMessages(visibilityTimeout: TimeSpan.FromSeconds(messageQueueOptions.VisibilityTimeout)); + + if (messageResponse.Value != null) + { + foreach (QueueMessage message in messageResponse.Value) + { + simpleQueueMessages.Add(AzQueueMessageToSimpleQueueMessage(message)); + if (messageQueueOptions.DeleteConsumedMessages) + { + Azure.Response deleteResponse = _queueClient.DeleteMessage(message.MessageId, message.PopReceipt); + if (deleteResponse != null && deleteResponse.IsError) + deleteSuccess = false; + } + } + } + success = deleteSuccess; + } + return simpleQueueMessages; + } + + public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success) + { + success = false; + Azure.Response sendReceipt; + MessageQueueResult queueMessageResult = new MessageQueueResult(); + + if (_queueClient is QueueClient && _queueClient.Exists()) + { + sendReceipt = _queueClient.SendMessage(simpleQueueMessage.MessageBody, TimeSpan.FromSeconds(messageQueueOptions.VisibilityTimeout), TimeSpan.FromSeconds(messageQueueOptions.TimetoLive)); + if ((sendReceipt != null) && (sendReceipt.Value != null)) + { + MessageQueueResult result = new MessageQueueResult() + { + MessageId = simpleQueueMessage.MessageId, + ServerMessageId = sendReceipt.Value.MessageId, + MessageStatus = MessageQueueResultStatus.Sent, + MessageAttributes = new GXProperties() + + }; + Type t = sendReceipt.GetType(); + PropertyInfo[] props = t.GetProperties(); + foreach (PropertyInfo prop in props) + { + object value; + if (prop.GetIndexParameters().Length == 0 && sendReceipt != null) + { +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + value = prop.GetValue(sendReceipt); +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. + if (value != null) + result.MessageAttributes.Add(prop.Name, value.ToString()); + } + } + + success = true; + return result; + } + } + return queueMessageResult; + + } + public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out bool success) + { + success = false; + Azure.Response sendReceipt; + MessageQueueResult queueMessageResult = new MessageQueueResult(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + sendReceipt = _queueClient.SendMessage(simpleQueueMessage.MessageBody); + if ((sendReceipt != null) && (sendReceipt.Value != null)) + { + MessageQueueResult result = new MessageQueueResult() + { + MessageId = simpleQueueMessage.MessageId, + ServerMessageId = sendReceipt.Value.MessageId, + MessageStatus = MessageQueueResultStatus.Sent, + MessageAttributes = new GXProperties() + + }; + Type t = sendReceipt.Value.GetType(); + PropertyInfo[] props = t.GetProperties(); + foreach (PropertyInfo prop in props) + { + object value; + if (prop.GetIndexParameters().Length == 0 && sendReceipt.Value != null) + { +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + value = prop.GetValue(sendReceipt.Value); +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. + if (value != null) + result.MessageAttributes.Add(prop.Name, value.ToString()); + } + } + + success = true; + return result; + } + } + return queueMessageResult; + + } + + /// + /// + /// + /// + /// + /// + /// + /// + public IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + IList messageQueueResults = new List(); + + bool sendError = false; + bool successSend = false; + foreach (SimpleQueueMessage simpleQueueMessage in simpleQueueMessages) + { + messageQueueResult = SendMessage(simpleQueueMessage, messageQueueOptions, out successSend); + if (successSend) + messageQueueResults.Add(messageQueueResult); + else + { + sendError = true; + } + + } + success = !sendError; + return messageQueueResults; + } + + private MessageQueueResult AzQueueMessageToMessageQueueResult(QueueMessage queueMessage, string status) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + if (queueMessage != null) + { + messageQueueResult.MessageId = queueMessage.MessageId; + messageQueueResult.ServerMessageId = queueMessage.MessageId; + messageQueueResult.MessageStatus = status; + messageQueueResult.MessageAttributes = new GXProperties(); + + + Type t = queueMessage.GetType(); + PropertyInfo[] props = t.GetProperties(); + foreach (PropertyInfo prop in props) + { + object value; + if (prop.GetIndexParameters().Length == 0 && queueMessage != null) + { +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + value = prop.GetValue(queueMessage); +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. + if (value != null) + messageQueueResult.MessageAttributes.Add(prop.Name, value.ToString()); + } + } + } + return messageQueueResult; + } + + private SimpleQueueMessage AzPeekedMessageToSimpleQueueMessage(PeekedMessage peekedMessage) + { + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + if (peekedMessage != null) + { + simpleQueueMessage.MessageId = peekedMessage.MessageId; + simpleQueueMessage.MessageBody = peekedMessage.Body.ToString(); + simpleQueueMessage.MessageAttributes = new GXProperties(); + + Type t = peekedMessage.GetType(); + PropertyInfo[] props = t.GetProperties(); + foreach (PropertyInfo prop in props) + { + object value; + if (prop.GetIndexParameters().Length == 0 && peekedMessage != null) + { +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + value = prop.GetValue(peekedMessage); +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. + if (value != null) + simpleQueueMessage.MessageAttributes.Add(prop.Name, value.ToString()); + } + } + } + return simpleQueueMessage; + } + + private SimpleQueueMessage AzQueueMessageToSimpleQueueMessage(QueueMessage queueMessage) + { + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + if (queueMessage != null) + { + simpleQueueMessage.MessageId = queueMessage.MessageId; + simpleQueueMessage.MessageBody = queueMessage.Body.ToString(); + simpleQueueMessage.MessageAttributes = new GXProperties(); + + Type t = queueMessage.GetType(); + PropertyInfo[] props = t.GetProperties(); + foreach (PropertyInfo prop in props) + { + object value; + if (prop.GetIndexParameters().Length == 0 && queueMessage != null) + { +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + value = prop.GetValue(queueMessage); +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. + if (value != null) + simpleQueueMessage.MessageAttributes.Add(prop.Name, value.ToString()); + } + } + } + return simpleQueueMessage; + } + public override string GetName() + { + return Name; + } + } + +} \ No newline at end of file diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj new file mode 100644 index 000000000..30e505229 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + + + + + + + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj new file mode 100644 index 000000000..4e7afff8d --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj @@ -0,0 +1,12 @@ + + + + net6.0 + TRACE;DEBUG;NETCORE + + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs new file mode 100644 index 000000000..c10a97223 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Attributes; +using GeneXus.Encryption; +using GeneXus.Services; +using GeneXus.Utils; +using GxClasses.Helpers; +using log4net; + +namespace GeneXus.Messaging.Common +{ + [GXApi] + public class MessageQueueProvider : SimpleMessageQueue + { + static readonly ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static GXService providerService; + public MessageQueueProvider() + { + /*if (providerService == null) + { + providerService = ServiceFactory.GetGXServices().Get(GXServices.QUEUE_SERVICE); + }*/ + + } + + public SimpleMessageQueue Connect(string providerTypeName, GXProperties properties, out GXBaseCollection errorMessages, out bool success) + { + + errorMessages = new GXBaseCollection(); + SimpleMessageQueue simpleMessageQueue = new SimpleMessageQueue(); + if (string.IsNullOrEmpty(providerTypeName)) + { + GXUtil.ErrorToMessages("Unsupported", "Queue provider cannot be empty", errorMessages); + success = false; + return simpleMessageQueue; + } + try + { + if (providerService == null || !string.Equals(providerService.Name, providerTypeName, StringComparison.OrdinalIgnoreCase)) + { + providerService = new GXService(); + providerService.Type = GXServices.QUEUE_SERVICE; + providerService.Name = providerTypeName; + providerService.AllowMultiple = false; + providerService.Properties = new GXProperties(); + } + preprocess(providerTypeName, properties); + + GxKeyValuePair prop = properties.GetFirst(); + while (!properties.Eof()) + { + providerService.Properties.Set(prop.Key, prop.Value); + prop = properties.GetNext(); + } + + string typeFullName = providerService.ClassName; + logger.Debug("Loading Queue provider: " + typeFullName); +#if !NETCORE + Type type = Type.GetType(typeFullName, true, true); +#else + Type type = AssemblyLoader.GetType(typeFullName); +#endif + simpleMessageQueue.queue = (IQueue)Activator.CreateInstance(type, new object[] { providerService }); + + } + catch (Exception ex) + { + logger.Error("Couldn't connect to Queue provider. ", ex); + GXUtil.ErrorToMessages("Queue Error", ex, errorMessages); + success = false; + return simpleMessageQueue; + } + success = true; + return (simpleMessageQueue); + } + + private static void preprocess(String name, GXProperties properties) + { + string className; + + switch (name) + { + case "AZUREQUEUE": + className = "GeneXus.Messaging.Queue.AzureQueue"; + SetEncryptedProperty(properties, "QUEUE_AZUREQUEUE_QUEUENAME"); + SetEncryptedProperty(properties, "QUEUE_AZUREQUEUE_CONNECTIONSTRING"); + if (string.IsNullOrEmpty(providerService.ClassName) || !providerService.ClassName.Contains(className)) + { + providerService.ClassName = "GeneXus.Messaging.Queue.AzureQueue, GXAzureQueue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + } + break; + + default: + throw new SystemException(string.Format("Provider {0} is not supported", name)); + + } + } + private static void SetEncryptedProperty(GXProperties properties, String prop) + { + String value = properties.Get(prop); + if (string.IsNullOrEmpty(value)) + value = ""; + value = CryptoImpl.Encrypt(value); + properties.Set(prop, value); + } + + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs new file mode 100644 index 000000000..a500ea206 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using GeneXus.Utils; + +namespace GeneXus.Messaging.Common +{ + public interface IQueue + { + public const int MAX_NUMBER_MESSAGES = 10; + public const bool DELETE_CONSUMED_MESSAGES = false; + public const int WAIT_TIMEOUT = 10; + public const int VISIBILITY_TIMEOUT = 60; + + int GetQueueLength(out bool success); + MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out bool success); + MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success); + IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success); + IList GetMessages(out bool success); + IList GetMessages(MessageQueueOptions messageQueueOptions, out bool success); + MessageQueueResult DeleteMessage(out bool success); + + IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions, out bool success); + void Clear(out bool success); + bool GetMessageFromException(Exception ex, SdtMessages_Message msg); + } + public class SimpleQueueMessage : GxUserType + { + public string MessageId { get; set; } + public string MessageBody { get; set; } + public GXProperties MessageAttributes { get; set; } + public string MessageHandleId { get; set; } + + #region Json + private static Hashtable mapper; + public override String JsonMap(String value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (String)mapper[value]; ; + } + + public override void ToJSON() + { + ToJSON(true); + return; + } + + public override void ToJSON(bool includeState) + { + AddObjectProperty("MessageId", MessageId, false); + AddObjectProperty("MessageBody", MessageBody, false); + AddObjectProperty("MessageHandleId", MessageHandleId, false); + //Properties? + return; + } + + #endregion + + } + + public class MessageQueueResult : GxUserType + { + public string MessageId { get; set; } + public string ServerMessageId { get; set; } + public GXProperties MessageAttributes { get; set; } + public string MessageHandleId { get; set; } + public string MessageStatus { get; set; } + + #region Json + private static Hashtable mapper; + public override String JsonMap(String value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (String)mapper[value]; ; + } + + public override void ToJSON() + { + ToJSON(true); + return; + } + + public override void ToJSON(bool includeState) + { + AddObjectProperty("MessageId", MessageId, false); + AddObjectProperty("ServerMessageId", ServerMessageId, false); + AddObjectProperty("MessageHandleId", MessageHandleId, false); + AddObjectProperty("MessageStatus", MessageStatus, false); + //GxKeyValuePair prop = MessageAttributes.GetFirst(); + //while (!MessageAttributes.Eof()) + //{ + //AddObjectProperty("MessageStatus", MessageStatus, false); + + //prop = MessageAttributes.GetNext(); + // } + return; + } + + #endregion + } + + public class MessageQueueOptions : GxUserType + { + public short MaxNumberOfMessages { get; set; } + public bool DeleteConsumedMessages { get; set; } + public int WaitTimeout { get; set; } + public int VisibilityTimeout { get; set; } + public int TimetoLive { get; set; } + + } + + public static class MessageQueueResultStatus + { + public const string Unknown = "Unknown"; + public const string Sent = "Sent"; + public const string Deleted = "Deleted"; + public const string Failed = "Failed"; + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs new file mode 100644 index 000000000..309f2d8b4 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Services; +using log4net; + +namespace GeneXus.Messaging.Common +{ + public abstract class QueueBase + { + static readonly ILog logger = log4net.LogManager.GetLogger(typeof(QueueBase)); + internal GXService service; + public QueueBase() + { + } + + public QueueBase(GXService s) + { + if (s == null) + { + try + { + s = ServiceFactory.GetGXServices().Get(GXServices.QUEUE_SERVICE); + } + catch (Exception) + { + logger.Warn("QUEUE_SERVICE is not activated"); + } + } + + service = s; + } + public abstract String GetName(); + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs new file mode 100644 index 000000000..6e315e6bb --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Encryption; +using GeneXus.Messaging.Common; +using GeneXus.Services; +using log4net; + +namespace GeneXus.Messaging.Queue +{ + public class ServiceSettings + { + static readonly ILog logger = log4net.LogManager.GetLogger(typeof(ServiceSettings)); + + internal GXService service; + public string serviceNameResolver { get; } + public string name { get; } + + public ServiceSettings(string serviceNameResolver, string name, GXService gXService) + { + this.serviceNameResolver = serviceNameResolver; + this.name = name; + this.service = gXService; + } + + public string GetEncryptedPropertyValue(string propertyName, string alternativePropertyName = null) + { + String value = GetEncryptedPropertyValue(propertyName, alternativePropertyName, null); + if (value == null) + { + String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); + logger.Fatal(errorMessage); + throw new Exception(errorMessage); + } + return value; + } + public string GetEncryptedPropertyValue(string propertyName, string alternativePropertyName, string defaultValue) + { + String value = GetPropertyValue(propertyName, alternativePropertyName, defaultValue); + if (!String.IsNullOrEmpty(value)) + { + try + { + string ret = ""; + if (CryptoImpl.Decrypt(ref ret, value)) + { + value = ret; + } + } + catch (Exception) + { + logger.Warn($"Could not decrypt property name: {ResolvePropertyName(propertyName)}"); + } + } + return value; + } + + internal string GetPropertyValue(string propertyName, string alternativePropertyName = null) + { + String value = GetPropertyValue(propertyName, alternativePropertyName, null); + if (value == null) + { + String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); + logger.Fatal(errorMessage); + throw new Exception(errorMessage); + } + return value; + } + + internal string GetPropertyValue(string propertyName, string alternativePropertyName, string defaultValue) + { + String value = null; + value = string.IsNullOrEmpty(value) ? GetPropertyValueImpl(ResolvePropertyName(propertyName)) : value; + value = string.IsNullOrEmpty(value) ? GetPropertyValueImpl(propertyName) : value; + value = string.IsNullOrEmpty(value) ? GetPropertyValueImpl(alternativePropertyName) : value; + value = string.IsNullOrEmpty(value) ? defaultValue : value; + return value; + } + + internal string GetPropertyValueImpl(string propertyName) + { + String value = null; + if (!string.IsNullOrEmpty(propertyName)) + { + value = Environment.GetEnvironmentVariable(propertyName); + if (service != null) + { + value = service.Properties.Get(propertyName); + } + } + return value; + } + + internal string ResolvePropertyName(string propertyName) + { + return $"{serviceNameResolver}_{name}_{propertyName}"; + } + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs new file mode 100644 index 000000000..e11b04f9c --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus; +using GeneXus.Messaging.Common; +using GeneXus.Services; +using GeneXus.Utils; +using GxClasses.Helpers; +using log4net; + +namespace GeneXus.Messaging.Common +{ + public class SimpleMessageQueue + { + internal IQueue queue = null; + + + public SimpleMessageQueue() + { + //queue = ServiceFactory.GetQueue(); + } + public SimpleMessageQueue(SimpleMessageQueue other) + { + queue = other.queue; + } + void ValidQueue() + { + if (queue == null) + throw new Exception("Queue not found"); + } + public void Clear(out GXBaseCollection errorMessages, out bool success) + { + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + queue.Clear(out success); + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + } + + public int GetQueueLength(out GXBaseCollection errorMessages, out bool success) + { + errorMessages = new GXBaseCollection(); + int queueLength = 0; + try + { + ValidQueue(); + queueLength = queue.GetQueueLength(out success); + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + + return queueLength; + } + public MessageQueueResult DeleteMessage(out GXBaseCollection errorMessages, out bool success) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + messageQueueResult = queue.DeleteMessage(out success); + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + return messageQueueResult; + } + + public IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + { + IList messageQueueResults = new List(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + messageQueueResults = queue.DeleteMessages(messageHandleId, messageQueueOptions, out success); + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + return messageQueueResults; + } + + public IList GetMessages(out GXBaseCollection errorMessages, out bool success) + { + IList simpleQueueMessages = new List(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + simpleQueueMessages = queue.GetMessages(out success); + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + return simpleQueueMessages = queue.GetMessages(out success); + } + + public IList GetMessages(MessageQueueOptions messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + { + IList simpleQueueMessages = new List(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + simpleQueueMessages = queue.GetMessages(messageQueueOptions, out success); + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + return simpleQueueMessages = queue.GetMessages(out success); + } + + public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out GXBaseCollection errorMessages, out bool success) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + messageQueueResult = queue.SendMessage(simpleQueueMessage, out success); + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + return messageQueueResult; + + } + + public IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + { + IList messageQueueResults = new List(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + messageQueueResults = queue.SendMessages(simpleQueueMessages, messageQueueOptions, out success); + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + return messageQueueResults; + } + + protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection errorMessages) + { + errorMessages = new GXBaseCollection(); + if (errorMessages != null && ex != null) + { + SdtMessages_Message msg = new SdtMessages_Message(); + if (queue != null && queue.GetMessageFromException(ex, msg)) + { + msg.gxTpr_Type = 1; + StringBuilder str = new StringBuilder(); + str.Append(ex.Message); + while (ex.InnerException != null) + { + str.Append(ex.InnerException.Message); + ex = ex.InnerException; + } + msg.gxTpr_Description = str.ToString(); + errorMessages.Add(msg); + } + else + { + GXUtil.ErrorToMessages("Queue Error", ex, errorMessages); + } + } + } + } + public class ServiceFactory + { + private static IQueue queue; + private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Services.ServiceFactory)); + + public static GXServices GetGXServices() + { + return GXServices.Instance; + } + + public static IQueue GetQueue() + { + if (queue == null) + { + queue = GetQueueImpl(GXServices.QUEUE_SERVICE); + } + return queue; + } + + public static IQueue GetQueueImpl(string service) + { + IQueue queueImpl = null; + if (GetGXServices() != null) + { + GXService providerService = GetGXServices().Get(service); + if (providerService != null) + { + try + { + string typeFullName = providerService.ClassName; + GXLogging.Debug(log, "Loading Queue settings:", typeFullName); +#if !NETCORE + if (!string.IsNullOrEmpty(typeFullName)) + Type type = Type.GetType(typeFullName, true, true); +#else + Type type = AssemblyLoader.GetType(typeFullName); +#endif + queueImpl = (IQueue)Activator.CreateInstance(type); + } + catch (Exception e) + { + GXLogging.Error(log, "Couldn't connect to the Queue.", e.Message, e); + throw e; + } + } + } + return queueImpl; + } + } +} + + + diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs index 28432439e..9d45d6f27 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs @@ -21,6 +21,7 @@ public class GXServices public static string CACHE_SERVICE = "Cache"; public static string SESSION_SERVICE = "Session"; public static string WEBNOTIFICATIONS_SERVICE = "WebNotifications"; + public static string QUEUE_SERVICE = "QueueService"; private static string[] SERVICES_FILE = new string[] { "CloudServices.dev.config", "CloudServices.config" }; [System.Diagnostics.CodeAnalysis.SuppressMessage("GxFxCopRules", "CR1000:EnforceThreadSafeType")] private Dictionary services = new Dictionary(); diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 62bee4934..4a9ea752e 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -1,4 +1,4 @@ - + net6.0 CS8032;1701;1702;NU1701 @@ -72,6 +72,7 @@ + From 04d1ba4205af7ceaa73683e19c985cb5c3bbd586 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 1 Jun 2022 20:56:48 -0300 Subject: [PATCH 02/14] Changes in implementation in order to use SDTs instead of EOs for the in and out parameters of the methods in GX. --- .../Messaging/GXAzureQueue/AzureQueue.cs | 8 +- .../Messaging/GXQueue/MessageQueueProvider.cs | 1 - .../Messaging/GXQueue/SimpleMessageQueue.cs | 312 +++++++++++++++--- .../GxClasses/Domain/GxCollections.cs | 9 + 4 files changed, 285 insertions(+), 45 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index a23ff4f78..34f31d2f1 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -319,13 +319,9 @@ public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out } /// - /// + /// Send messages using Queue options /// - /// - /// - /// - /// - /// + public IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success) { MessageQueueResult messageQueueResult = new MessageQueueResult(); diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index c10a97223..8749384d2 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -28,7 +28,6 @@ public MessageQueueProvider() public SimpleMessageQueue Connect(string providerTypeName, GXProperties properties, out GXBaseCollection errorMessages, out bool success) { - errorMessages = new GXBaseCollection(); SimpleMessageQueue simpleMessageQueue = new SimpleMessageQueue(); if (string.IsNullOrEmpty(providerTypeName)) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index e11b04f9c..6000be9c2 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -1,11 +1,10 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; +using System.IO; +using System.Reflection; using System.Text; -using System.Threading.Tasks; -using GeneXus; -using GeneXus.Messaging.Common; +using GeneXus.Application; using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; @@ -16,8 +15,14 @@ namespace GeneXus.Messaging.Common public class SimpleMessageQueue { internal IQueue queue = null; - - + public static Assembly assembly; + static readonly ILog logger = log4net.LogManager.GetLogger(typeof(SimpleMessageQueue)); + private const string SDT_MESSAGE_CLASS_NAME = @"SdtMessage"; + private const string SDT_MESSAGEPROPERTY_CLASS_NAME = @"SdtMessageProperty"; + private const string SDT_MESSAGERESULT_CLASS_NAME = @"SdtMessageResult"; + private const string NAMESPACE = @"GeneXus.Programs.genexusmessagingqueue.simplequeue"; + private const string GENEXUS_COMMON_DLL = @"GeneXus.Programs.Common.dll"; + public SimpleMessageQueue() { //queue = ServiceFactory.GetQueue(); @@ -29,8 +34,12 @@ public SimpleMessageQueue(SimpleMessageQueue other) void ValidQueue() { if (queue == null) + { + GXLogging.Error(logger, "Queue not found"); throw new Exception("Queue not found"); + } } + public void Clear(out GXBaseCollection errorMessages, out bool success) { errorMessages = new GXBaseCollection(); @@ -63,113 +72,339 @@ public int GetQueueLength(out GXBaseCollection errorMessage return queueLength; } - public MessageQueueResult DeleteMessage(out GXBaseCollection errorMessages, out bool success) + public GxUserType DeleteMessage(out GXBaseCollection errorMessages, out bool success) { MessageQueueResult messageQueueResult = new MessageQueueResult(); + GxUserType messageResult = new GxUserType(); errorMessages = new GXBaseCollection(); try { ValidQueue(); messageQueueResult = queue.DeleteMessage(out success); + try + { + LoadAssemblyIfRequired(); + if (messageQueueResult != null && TransformMessageQueueResult(messageQueueResult) is GxUserType result) + return result; + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + success = false; + throw ex; + } } catch (Exception ex) { QueueErrorMessagesSetup(ex, out errorMessages); + GXLogging.Error(logger, ex); success = false; } - return messageQueueResult; + return messageResult; } - public IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + public IList DeleteMessages(List messageHandleId, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) { IList messageQueueResults = new List(); errorMessages = new GXBaseCollection(); + IList messageResults = new List(); + success = false; try { - ValidQueue(); - messageQueueResults = queue.DeleteMessages(messageHandleId, messageQueueOptions, out success); - + MessageQueueOptions options = TransformOptions(messageQueueOptions); + try + { + ValidQueue(); + messageQueueResults = queue.DeleteMessages(messageHandleId, options, out success); + LoadAssemblyIfRequired(); + foreach (MessageQueueResult messageResult in messageQueueResults) + { + if (TransformMessageQueueResult(messageResult) is GxUserType result) + messageResults.Add(result); + } + success = true; + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } } catch (Exception ex) { - QueueErrorMessagesSetup(ex, out errorMessages); + GXLogging.Error(logger, ex); success = false; + throw ex; } - return messageQueueResults; + + return messageResults; } - public IList GetMessages(out GXBaseCollection errorMessages, out bool success) + public IList GetMessages(out GXBaseCollection errorMessages, out bool success) { - IList simpleQueueMessages = new List(); + errorMessages = new GXBaseCollection(); + IList resultMessages = new List(); + success = false; try { ValidQueue(); - simpleQueueMessages = queue.GetMessages(out success); + IList simpleQueueMessages = queue.GetMessages(out success); + try + { + LoadAssemblyIfRequired(); + + foreach (SimpleQueueMessage simpleQueueMessage in simpleQueueMessages) + { + if (TransformSimpleQueueMessage(simpleQueueMessage) is GxUserType result) + resultMessages.Add(result); + } + success = true; + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + success = false; + } } catch (Exception ex) { + GXLogging.Error(logger, ex); QueueErrorMessagesSetup(ex, out errorMessages); success = false; } - return simpleQueueMessages = queue.GetMessages(out success); + return resultMessages; } - public IList GetMessages(MessageQueueOptions messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + public IList GetMessages(GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) { - IList simpleQueueMessages = new List(); + errorMessages = new GXBaseCollection(); + IList resultMessages = new List(); + success = false; try { - ValidQueue(); - simpleQueueMessages = queue.GetMessages(messageQueueOptions, out success); + MessageQueueOptions options = TransformOptions(messageQueueOptions); + + try + { + ValidQueue(); + IList simpleQueueMessages = queue.GetMessages(options, out success); + LoadAssemblyIfRequired(); + foreach (SimpleQueueMessage simpleQueueMessage in simpleQueueMessages) + { + if (TransformSimpleQueueMessage(simpleQueueMessage) is GxUserType result) + resultMessages.Add(result); + } + success = true; + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + GXLogging.Error(logger, ex); + success = false; + } } catch (Exception ex) { - QueueErrorMessagesSetup(ex, out errorMessages); + GXLogging.Error(logger, ex); success = false; + throw ex; + } + + return resultMessages; + } + + private static void LoadAssemblyIfRequired() + { + if (assembly == null) + { + assembly = LoadAssembly(Path.Combine(GxContext.StaticPhysicalPath(), GENEXUS_COMMON_DLL)); + if (assembly == null) + assembly = LoadAssembly(Path.Combine(GxContext.StaticPhysicalPath(), "bin", GENEXUS_COMMON_DLL)); + } + } + + private MessageQueueOptions TransformOptions(GxUserType messageQueueOptions) + { + MessageQueueOptions options = new MessageQueueOptions(); + options.MaxNumberOfMessages = messageQueueOptions.GetPropertyValue("Maxnumberofmessages"); + options.DeleteConsumedMessages = messageQueueOptions.GetPropertyValue("Deleteconsumedmessages"); + options.WaitTimeout = messageQueueOptions.GetPropertyValue("Waittimeout"); + options.VisibilityTimeout = messageQueueOptions.GetPropertyValue("Visibilitytimeout"); + options.TimetoLive = messageQueueOptions.GetPropertyValue("Timetolive"); + return options; + } + + private SimpleQueueMessage TransformGXUserTypeToSimpleQueueMessage(GxUserType simpleQueueMessage) + { + SimpleQueueMessage queueMessage = new SimpleQueueMessage(); + queueMessage.MessageId = simpleQueueMessage.GetPropertyValue("Messageid"); + queueMessage.MessageBody = simpleQueueMessage.GetPropertyValue("Messagebody"); + queueMessage.MessageHandleId = simpleQueueMessage.GetPropertyValue("Messagehandleid"); + IList messageAttributes = simpleQueueMessage.GetPropertyValue("Messageattributes_GXBaseCollection"); + queueMessage.MessageAttributes = new GXProperties(); + foreach (GxUserType messageAttribute in messageAttributes) + { + string messagePropKey = messageAttribute.GetPropertyValue("Propertykey"); + string messagePropValue = messageAttribute.GetPropertyValue("Propertyvalue"); + queueMessage.MessageAttributes.Add(messagePropKey, messagePropValue); + } + return queueMessage; + } + private GxUserType TransformSimpleQueueMessage(SimpleQueueMessage simpleQueueMessage) + { + Type classType = assembly.GetType(NAMESPACE + "." + SDT_MESSAGE_CLASS_NAME, false, ignoreCase: true); + Type propertyClassType = assembly.GetType(NAMESPACE + "." + SDT_MESSAGEPROPERTY_CLASS_NAME, false, ignoreCase: true); + + if (classType != null && Activator.CreateInstance(classType) is GxUserType simpleMessageSDT) + { + simpleMessageSDT.SetPropertyValue("Messageid", simpleQueueMessage.MessageId); + simpleMessageSDT.SetPropertyValue("Messagebody", simpleQueueMessage.MessageBody); + simpleMessageSDT.SetPropertyValue("Messagehandleid", simpleQueueMessage.MessageHandleId); + + IList messageResultSDTAttributes = (IList)Activator.CreateInstance(classType.GetProperty("gxTpr_Messageattributes").PropertyType, new object[] { simpleMessageSDT.context, "MessageProperty", string.Empty }); + GxKeyValuePair prop = simpleQueueMessage.MessageAttributes.GetFirst(); + while (!simpleQueueMessage.MessageAttributes.Eof()) + { + if (propertyClassType != null && Activator.CreateInstance(propertyClassType) is GxUserType propertyClassTypeSDT) + { + propertyClassTypeSDT.SetPropertyValue("Propertykey", prop.Key); + propertyClassTypeSDT.SetPropertyValue("Propertyvalue", prop.Value); + messageResultSDTAttributes.Add(propertyClassTypeSDT); + prop = simpleQueueMessage.MessageAttributes.GetNext(); + } + } + simpleMessageSDT.SetPropertyValue("Messageattributes", messageResultSDTAttributes); + + return simpleMessageSDT; } - return simpleQueueMessages = queue.GetMessages(out success); + return null; } + private GxUserType TransformMessageQueueResult(MessageQueueResult messageQueueResult) + { + Type classType = assembly.GetType(NAMESPACE + "." + SDT_MESSAGERESULT_CLASS_NAME, false, ignoreCase: true); + Type propertyClassType = assembly.GetType(NAMESPACE + "." + SDT_MESSAGEPROPERTY_CLASS_NAME, false, ignoreCase: true); - public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out GXBaseCollection errorMessages, out bool success) + if (classType != null && Activator.CreateInstance(classType) is GxUserType messageResultSDT) + { + messageResultSDT.SetPropertyValue("Messageid", messageQueueResult.MessageId); + messageResultSDT.SetPropertyValue("Servermessageid", messageQueueResult.ServerMessageId); + messageResultSDT.SetPropertyValue("Messagehandleid", messageQueueResult.MessageHandleId); + messageResultSDT.SetPropertyValue("Messagestatus", messageQueueResult.MessageStatus); + + IList messageResultSDTAttributes = (IList)Activator.CreateInstance(classType.GetProperty("gxTpr_Messageattributes").PropertyType, new object[] { messageResultSDT.context, "MessageProperty", string.Empty }); + GxKeyValuePair prop = messageQueueResult.MessageAttributes.GetFirst(); + while (!messageQueueResult.MessageAttributes.Eof()) + { + if (propertyClassType != null && Activator.CreateInstance(propertyClassType) is GxUserType propertyClassTypeSDT) + { + propertyClassTypeSDT.SetPropertyValue("Propertykey", prop.Key); + propertyClassTypeSDT.SetPropertyValue("Propertyvalue", prop.Value); + + messageResultSDTAttributes.Add(propertyClassTypeSDT); + prop = messageQueueResult.MessageAttributes.GetNext(); + } + } + messageResultSDT.SetPropertyValue("Messageattributes", messageResultSDTAttributes); + return messageResultSDT; + } + return null; + } + private static Assembly LoadAssembly(string fileName) + { + if (File.Exists(fileName)) + { + Assembly assemblyLoaded = Assembly.LoadFrom(fileName); + return assemblyLoaded; + } + else + return null; + } + public GxUserType SendMessage(GxUserType simpleQueueMessage, out GXBaseCollection errorMessages, out bool success) { + success = false; MessageQueueResult messageQueueResult = new MessageQueueResult(); errorMessages = new GXBaseCollection(); + GxUserType result = new GxUserType(); try { - ValidQueue(); - messageQueueResult = queue.SendMessage(simpleQueueMessage, out success); + SimpleQueueMessage queueMessage = TransformGXUserTypeToSimpleQueueMessage(simpleQueueMessage); + + try + { + ValidQueue(); + messageQueueResult = queue.SendMessage(queueMessage, out success); + LoadAssemblyIfRequired(); + + if (TransformMessageQueueResult(messageQueueResult) is GxUserType messageResult) + return messageResult; + success = true; + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + GXLogging.Error(logger, ex); + } } catch (Exception ex) { - QueueErrorMessagesSetup(ex, out errorMessages); success = false; + GXLogging.Error(logger,ex); + throw ex; } - return messageQueueResult; - + return result; } - public IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out GXBaseCollection errorMessages, out bool success) - { - IList messageQueueResults = new List(); + public IList SendMessages(GXBaseCollection simpleQueueMessages, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + { errorMessages = new GXBaseCollection(); + List messageResults = new List(); try { - ValidQueue(); - messageQueueResults = queue.SendMessages(simpleQueueMessages, messageQueueOptions, out success); + // Load Message Queue Options// + MessageQueueOptions options = TransformOptions(messageQueueOptions); + IList simpleQueueMessagesList = new List(); + foreach (GxUserType simpleQueueMessage in simpleQueueMessages) + { + if (TransformGXUserTypeToSimpleQueueMessage(simpleQueueMessage) is SimpleQueueMessage queueMessage) + + simpleQueueMessagesList.Add(queueMessage); + } + try + { + ValidQueue(); + IList messageQueueResults = queue.SendMessages(simpleQueueMessagesList, options, out success); + + LoadAssemblyIfRequired(); + foreach (MessageQueueResult messageResult in messageQueueResults) + { + if (TransformMessageQueueResult(messageResult) is GxUserType result) + messageResults.Add(result); + } + success = true; + + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + GXLogging.Error(logger, ex); + } } catch (Exception ex) { - QueueErrorMessagesSetup(ex, out errorMessages); - success = false; + GXLogging.Error(logger, ex); + throw ex; } - return messageQueueResults; + return messageResults; } protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection errorMessages) @@ -193,6 +428,7 @@ protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection Messa return false; } + internal T GetPropertyValue(string propertyName) + { + return (T)GetType().GetProperty($"gxTpr_{propertyName}").GetValue(this); + } + + internal void SetPropertyValue(string propertyName, object propertyValue) + { + GetType().GetProperty($"gxTpr_{propertyName}").SetValue(this, propertyValue); + } } public interface IGxJSONAble From 246320fb332aefba79bcbf89d6d7572278fc7d49 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 1 Jun 2022 21:00:38 -0300 Subject: [PATCH 03/14] Changes to support SDTs as parameters of the methods instead of EOs --- .../dotnetcore/GxNetCoreStartup/Startup.cs | 1 + .../Queue/AzureQueueTest.cs | 13 ++ .../DotNetCoreUnitTest/Queue/QueueTest.cs | 197 ++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 dotnet/test/DotNetCoreUnitTest/Queue/AzureQueueTest.cs create mode 100644 dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 248addec5..699a8b66e 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -36,6 +36,7 @@ public class Program const string DEFAULT_PORT = "80"; public static void Main(string[] args) { + System.Diagnostics.Debugger.Launch(); try { string port = DEFAULT_PORT; diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/AzureQueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/AzureQueueTest.cs new file mode 100644 index 000000000..dd72a8261 --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/Queue/AzureQueueTest.cs @@ -0,0 +1,13 @@ +using GeneXus.Messaging.Queue; +using UnitTesting; + +namespace DotNetUnitTest +{ + public class AzureQueueTest : QueueTest + { + public AzureQueueTest() : base(AzureQueue.Name, typeof(AzureQueue)) + { + } + + } +} \ No newline at end of file diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs new file mode 100644 index 000000000..5d2195193 --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using DotNetUnitTest; +using GeneXus.Messaging.Common; +using GeneXus.Services; +using GeneXus.Storage; +using Xunit; + + +#pragma warning disable CA1031 // Do not catch general exception types +namespace UnitTesting +{ + [Collection("Sequential")] + public abstract class QueueTest + { + + private IQueue queue; + // private String testFileName = "testresult.txt"; + // private String testFilePath; + + public QueueTest(string queueName, Type queueType) + { + //bool testEnabled = Environment.GetEnvironmentVariable(providerName + "_TEST_ENABLED") == "true"; + + + //Skip.IfNot(testEnabled, "Environment variables not set"); + + //bool testEnabled; + if (queueName == GeneXus.Messaging.Queue.AzureQueue.Name) + { + //testEnabled = true; + Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_QUEUENAME", "gxqueue"); + Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_CONNECTIONSTRING", "DefaultEndpointsProtocol=https;AccountName=storagegx;AccountKey=Wm5glFw1YRqjRyjH5awmTEoEmp41y585QBQCvfDEXxwPdeDWKw7dXY/0b1xR8oWE/mTbQFSXNE89p1l808ZJHA==;EndpointSuffix=core.windows.net"); + } + + queue = (IQueue)Activator.CreateInstance(queueType); + + Assert.NotNull(queue); + + //testFilePath = Path.Combine("resources", testFileName).ToString(CultureInfo.InvariantCulture); + //File.WriteAllText(testFilePath, "Unit test sample for API Queue"); + } + + [Fact] + //Clear the Queue + public void TestClearQueue() + { + bool success = false; + queue.Clear(out success); + Assert.True(success); + + } + + [Fact] + public void TestSimpleSendOneMessageMethod() + { + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + simpleQueueMessage.MessageId = "TestMsgId"; + simpleQueueMessage.MessageBody = "This is the message body"; + + bool success= false; + MessageQueueResult messageQueueResult = queue.SendMessage(simpleQueueMessage, out success); + + Assert.True(success); + + Assert.Equal(simpleQueueMessage.MessageId, messageQueueResult.MessageId); + Assert.Equal(messageQueueResult.MessageStatus,MessageQueueResultStatus.Sent); + + } + [Fact] + public void TestSimpleGetMessagesMethod() + { + bool success = false; + IList simpleQueueMessages = queue.GetMessages(out success); + + Assert.True(success); + Assert.True(simpleQueueMessages.Count == 1); + Assert.Equal("This is the message body", simpleQueueMessages[0].MessageBody); + + } + + [Fact] + public void TestSendMessageOptionsMethod() + { + System.Diagnostics.Debugger.Launch(); + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + simpleQueueMessage.MessageId = "TestMsgId2"; + simpleQueueMessage.MessageBody = "This is the message body with options"; + + MessageQueueOptions options = new MessageQueueOptions(); + //options.VisibilityTimeout = TimeSpan.FromSeconds(1); + options.TimetoLive = 3600; + + bool success = false; + MessageQueueResult messageQueueResult = queue.SendMessage(simpleQueueMessage, options, out success); + + Assert.True(success); + Assert.Equal(simpleQueueMessage.MessageId, messageQueueResult.MessageId); + Assert.Equal(MessageQueueResultStatus.Sent,messageQueueResult.MessageStatus); + + } + [Fact] + public void TestGetMessageOptionsMethod() + { + + bool success = false; + MessageQueueOptions options = new MessageQueueOptions(); + options.MaxNumberOfMessages = 10; + options.DeleteConsumedMessages = true; + options.VisibilityTimeout = 1; + IList simpleQueueMessages = queue.GetMessages(options, out success); + + Assert.True(success); + Assert.True(simpleQueueMessages.Count == 2); + + Assert.Equal("TestMsgId1", simpleQueueMessages[0].MessageId); + Assert.Equal("TestMsgId2", simpleQueueMessages[1].MessageId); + + } + + [Fact] + public void TestSendMessagesOptionsMethod() + { + + IList simpleQueueMessages = new List(); + + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + simpleQueueMessage.MessageId = "TestMsgId3"; + simpleQueueMessage.MessageBody = "This is the message body 3"; + simpleQueueMessages.Add(simpleQueueMessage); + + SimpleQueueMessage simpleQueueMessage2 = new SimpleQueueMessage(); + simpleQueueMessage2.MessageId = "TestMsgId4"; + simpleQueueMessage2.MessageBody = "This is the message body 4"; + simpleQueueMessages.Add(simpleQueueMessage2); + + MessageQueueOptions options = new MessageQueueOptions(); + + //Azure VisibilityTimeout. If specified, the request must be made using an x-ms-version of 2011-08-18 or later. If not specified, the default value is 0. Specifies the new visibility timeout value, in seconds, relative to server time. The new value must be larger than or equal to 0, and cannot be larger than 7 days. The visibility timeout of a message cannot be set to a value later than the expiry time. visibilitytimeout should be set to a value smaller than the time-to-live value. + //options.VisibilityTimeout = TimeSpan.FromSeconds(1); + + //TimeToLive. Specifies the time-to-live interval for the message, in seconds + //Azure -1 means not expires + options.TimetoLive = 3600; + + bool success = false; + IList messageQueueResults = queue.SendMessages(simpleQueueMessages,options, out success); + + Assert.True(success); + Assert.True(simpleQueueMessages.Count == 2); + + System.Threading.Thread.Sleep(1000); + Assert.Equal("TestMsgId3", simpleQueueMessages[0].MessageId); + Assert.Equal("TestMsgId4", simpleQueueMessages[1].MessageId); + + } + + + public void TestDeleteMessagesOptionsMethod() + { + bool success = false; + IList messageQueueResults = new List(); + List messageHandleId = new List() { "TestMsgIdNotExists", "TestMsgId3" }; + MessageQueueOptions options = new MessageQueueOptions(); + options.MaxNumberOfMessages = 10; + messageQueueResults = queue.DeleteMessages(messageHandleId, options, out success); + + Assert.True(success); + Assert.True(messageQueueResults.Count == 1); + + } + + + public void TestDeleteMessageMethod() + { + bool success = false; + MessageQueueResult messageQueueResult = queue.DeleteMessage(out success); + Assert.True(success); + } + + [Fact] + public void TestGetQueueLength() + { + bool success = false; + int length = queue.GetQueueLength(out success); + + Assert.True(success); + Assert.Equal(0, length); + + } + + } +} +#pragma warning restore CA1031 // Do not catch general exception types \ No newline at end of file From 50501443fae33e9d3d33b54b6c2e1a1af10586ed Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 1 Jun 2022 21:17:12 -0300 Subject: [PATCH 04/14] Integration tests use env variables. --- .../dotnetcore/GxNetCoreStartup/Startup.cs | 1 - .../DotNetCoreUnitTest/Queue/QueueTest.cs | 37 ++++++++----------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 699a8b66e..248addec5 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -36,7 +36,6 @@ public class Program const string DEFAULT_PORT = "80"; public static void Main(string[] args) { - System.Diagnostics.Debugger.Launch(); try { string port = DEFAULT_PORT; diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs index 5d2195193..4d8e5f091 100644 --- a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs +++ b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs @@ -18,33 +18,26 @@ public abstract class QueueTest { private IQueue queue; - // private String testFileName = "testresult.txt"; - // private String testFilePath; public QueueTest(string queueName, Type queueType) { - //bool testEnabled = Environment.GetEnvironmentVariable(providerName + "_TEST_ENABLED") == "true"; + bool testEnabled = Environment.GetEnvironmentVariable("AZUREQUEUE_TEST_ENABLED") == "true"; + Skip.IfNot(testEnabled, "Environment variables not set"); - - //Skip.IfNot(testEnabled, "Environment variables not set"); - - //bool testEnabled; if (queueName == GeneXus.Messaging.Queue.AzureQueue.Name) { //testEnabled = true; - Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_QUEUENAME", "gxqueue"); - Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_CONNECTIONSTRING", "DefaultEndpointsProtocol=https;AccountName=storagegx;AccountKey=Wm5glFw1YRqjRyjH5awmTEoEmp41y585QBQCvfDEXxwPdeDWKw7dXY/0b1xR8oWE/mTbQFSXNE89p1l808ZJHA==;EndpointSuffix=core.windows.net"); - } + //Environment variables needed here + Environment.SetEnvironmentVariable("Queue_AZUREQUEUE_QUEUENAME", ""); + Environment.SetEnvironmentVariable("Queue_AZUREQUEUE_CONNECTIONSTRING", ""); - queue = (IQueue)Activator.CreateInstance(queueType); + queue = (IQueue)Activator.CreateInstance(queueType); - Assert.NotNull(queue); - - //testFilePath = Path.Combine("resources", testFileName).ToString(CultureInfo.InvariantCulture); - //File.WriteAllText(testFilePath, "Unit test sample for API Queue"); + Assert.NotNull(queue); + } } - [Fact] + [SkippableFact] //Clear the Queue public void TestClearQueue() { @@ -54,7 +47,7 @@ public void TestClearQueue() } - [Fact] + [SkippableFact] public void TestSimpleSendOneMessageMethod() { SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); @@ -70,7 +63,7 @@ public void TestSimpleSendOneMessageMethod() Assert.Equal(messageQueueResult.MessageStatus,MessageQueueResultStatus.Sent); } - [Fact] + [SkippableFact] public void TestSimpleGetMessagesMethod() { bool success = false; @@ -82,7 +75,7 @@ public void TestSimpleGetMessagesMethod() } - [Fact] + [SkippableFact] public void TestSendMessageOptionsMethod() { System.Diagnostics.Debugger.Launch(); @@ -102,7 +95,7 @@ public void TestSendMessageOptionsMethod() Assert.Equal(MessageQueueResultStatus.Sent,messageQueueResult.MessageStatus); } - [Fact] + [SkippableFact] public void TestGetMessageOptionsMethod() { @@ -121,7 +114,7 @@ public void TestGetMessageOptionsMethod() } - [Fact] + [SkippableFact] public void TestSendMessagesOptionsMethod() { @@ -181,7 +174,7 @@ public void TestDeleteMessageMethod() Assert.True(success); } - [Fact] + [SkippableFact] public void TestGetQueueLength() { bool success = false; From 0915dbff18d8448e57f864e1b5611253d7401fe2 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 1 Jun 2022 21:20:17 -0300 Subject: [PATCH 05/14] Remove debug line from test --- dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs index 4d8e5f091..05f168844 100644 --- a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs +++ b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs @@ -78,7 +78,6 @@ public void TestSimpleGetMessagesMethod() [SkippableFact] public void TestSendMessageOptionsMethod() { - System.Diagnostics.Debugger.Launch(); SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); simpleQueueMessage.MessageId = "TestMsgId2"; simpleQueueMessage.MessageBody = "This is the message body with options"; From 1aea46841064355159310d8d3587e16d344cd74f Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Thu, 2 Jun 2022 20:29:59 -0300 Subject: [PATCH 06/14] Force messages to UTF8 encoding. --- .../Messaging/GXAzureQueue/AzureQueue.cs | 46 +++++-------------- .../Messaging/GXQueue/MessageQueueProvider.cs | 17 +++---- .../Providers/Messaging/GXQueue/QueueBase.cs | 2 +- .../Messaging/GXQueue/SimpleMessageQueue.cs | 2 +- .../DotNetCoreUnitTest/Queue/QueueTest.cs | 4 +- 5 files changed, 23 insertions(+), 48 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index 34f31d2f1..1b81ce080 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Reflection; -using System.Threading.Tasks; using Azure.Storage.Queues; using Azure.Storage.Queues.Models; using GeneXus.Messaging.Common; @@ -36,8 +35,12 @@ private void Initialize(GXService providerService) _queueName = serviceSettings.GetEncryptedPropertyValue(QUEUE_NAME); _connectionString = serviceSettings.GetEncryptedPropertyValue(QUEUE_CONNECTION_STRING); - if (_queueClient == null) - _queueClient = new QueueClient(_connectionString, _queueName); + QueueClientOptions queueClientOptions = new QueueClientOptions() + { + MessageEncoding = QueueMessageEncoding.Base64 + }; + + _queueClient = new QueueClient(_connectionString, _queueName, queueClientOptions); } QueueClient QueueClient @@ -65,7 +68,9 @@ public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) { try { - msg.gxTpr_Description = ex.Message; + Azure.RequestFailedException az_ex = (Azure.RequestFailedException)ex; + msg.gxTpr_Id = az_ex.ErrorCode; + msg.gxTpr_Description = az_ex.Message; return true; } catch (Exception) @@ -107,18 +112,6 @@ public void Clear(out bool success) } } - public Task ClearAsync(out bool success) - { - success = false; - if (_queueClient is QueueClient && _queueClient.Exists()) - { - Task result = _queueClient.ClearMessagesAsync(); - success = !result.Result.IsError; - return (result); - } - return null; - } - /// /// Permanently removes the first message dequeued. /// @@ -156,8 +149,6 @@ public IList DeleteMessages(List messageHandleId, Me if (_queueClient is QueueClient && _queueClient.Exists()) { QueueProperties properties = _queueClient.GetProperties(); - int count = properties.ApproximateMessagesCount; - //If maxMessages is 0, receive using blocks until count = 0 QueueMessage[] receivedMessages = _queueClient.ReceiveMessages(messageQueueOptions.MaxNumberOfMessages); Azure.Response deleteResult; @@ -262,14 +253,11 @@ public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, Mes object value; if (prop.GetIndexParameters().Length == 0 && sendReceipt != null) { -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. value = prop.GetValue(sendReceipt); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. if (value != null) result.MessageAttributes.Add(prop.Name, value.ToString()); } } - success = true; return result; } @@ -283,7 +271,7 @@ public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out Azure.Response sendReceipt; MessageQueueResult queueMessageResult = new MessageQueueResult(); if (_queueClient is QueueClient && _queueClient.Exists()) - { + { sendReceipt = _queueClient.SendMessage(simpleQueueMessage.MessageBody); if ((sendReceipt != null) && (sendReceipt.Value != null)) { @@ -301,15 +289,12 @@ public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out { object value; if (prop.GetIndexParameters().Length == 0 && sendReceipt.Value != null) - { -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + { value = prop.GetValue(sendReceipt.Value); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. if (value != null) result.MessageAttributes.Add(prop.Name, value.ToString()); - } + } } - success = true; return result; } @@ -338,7 +323,6 @@ public IList SendMessages(IList simpleQu { sendError = true; } - } success = !sendError; return messageQueueResults; @@ -362,9 +346,7 @@ private MessageQueueResult AzQueueMessageToMessageQueueResult(QueueMessage queue object value; if (prop.GetIndexParameters().Length == 0 && queueMessage != null) { -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. value = prop.GetValue(queueMessage); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. if (value != null) messageQueueResult.MessageAttributes.Add(prop.Name, value.ToString()); } @@ -389,9 +371,7 @@ private SimpleQueueMessage AzPeekedMessageToSimpleQueueMessage(PeekedMessage pee object value; if (prop.GetIndexParameters().Length == 0 && peekedMessage != null) { -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. value = prop.GetValue(peekedMessage); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. if (value != null) simpleQueueMessage.MessageAttributes.Add(prop.Name, value.ToString()); } @@ -416,9 +396,7 @@ private SimpleQueueMessage AzQueueMessageToSimpleQueueMessage(QueueMessage queue object value; if (prop.GetIndexParameters().Length == 0 && queueMessage != null) { -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. value = prop.GetValue(queueMessage); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. if (value != null) simpleQueueMessage.MessageAttributes.Add(prop.Name, value.ToString()); } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index 8749384d2..17954ccca 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using GeneXus.Attributes; using GeneXus.Encryption; using GeneXus.Services; @@ -33,6 +29,7 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti if (string.IsNullOrEmpty(providerTypeName)) { GXUtil.ErrorToMessages("Unsupported", "Queue provider cannot be empty", errorMessages); + GXLogging.Error(logger, "Queue provider cannot be empty"); success = false; return simpleMessageQueue; } @@ -46,7 +43,7 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti providerService.AllowMultiple = false; providerService.Properties = new GXProperties(); } - preprocess(providerTypeName, properties); + Preprocess(providerTypeName, properties); GxKeyValuePair prop = properties.GetFirst(); while (!properties.Eof()) @@ -56,7 +53,7 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti } string typeFullName = providerService.ClassName; - logger.Debug("Loading Queue provider: " + typeFullName); + GXLogging.Debug(logger, "Loading Queue provider: " + typeFullName); #if !NETCORE Type type = Type.GetType(typeFullName, true, true); #else @@ -67,8 +64,8 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti } catch (Exception ex) { - logger.Error("Couldn't connect to Queue provider. ", ex); - GXUtil.ErrorToMessages("Queue Error", ex, errorMessages); + GXLogging.Error(logger, "Couldn't connect to Queue provider. " + ex.Message); + GXUtil.ErrorToMessages("Queue Connection Error", ex, errorMessages); success = false; return simpleMessageQueue; } @@ -76,7 +73,7 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti return (simpleMessageQueue); } - private static void preprocess(String name, GXProperties properties) + private static void Preprocess(String name, GXProperties properties) { string className; @@ -101,7 +98,7 @@ private static void SetEncryptedProperty(GXProperties properties, String prop) { String value = properties.Get(prop); if (string.IsNullOrEmpty(value)) - value = ""; + value = String.Empty; value = CryptoImpl.Encrypt(value); properties.Set(prop, value); } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs index 309f2d8b4..14f523305 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs @@ -26,7 +26,7 @@ public QueueBase(GXService s) } catch (Exception) { - logger.Warn("QUEUE_SERVICE is not activated"); + GXLogging.Warn(logger, "QUEUE_SERVICE is not activated"); } } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index 6000be9c2..dfdd214da 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -362,7 +362,7 @@ public GxUserType SendMessage(GxUserType simpleQueueMessage, out GXBaseCollectio return result; } - public IList SendMessages(GXBaseCollection simpleQueueMessages, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + public IList SendMessages(IList simpleQueueMessages, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) { errorMessages = new GXBaseCollection(); List messageResults = new List(); diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs index 05f168844..7099c4c4c 100644 --- a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs +++ b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs @@ -28,8 +28,8 @@ public QueueTest(string queueName, Type queueType) { //testEnabled = true; //Environment variables needed here - Environment.SetEnvironmentVariable("Queue_AZUREQUEUE_QUEUENAME", ""); - Environment.SetEnvironmentVariable("Queue_AZUREQUEUE_CONNECTIONSTRING", ""); + Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_QUEUENAME", ""); + Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_CONNECTIONSTRING", ""); queue = (IQueue)Activator.CreateInstance(queueType); From db66a285bfb7cacb037828d4edc705d91e48df92 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Sat, 4 Jun 2022 22:26:07 -0300 Subject: [PATCH 07/14] Improve messages in error handling. --- .../Messaging/GXQueue/MessageQueueProvider.cs | 26 +++++-- .../Messaging/GXQueue/SimpleMessageQueue.cs | 73 ++++++++++--------- 2 files changed, 59 insertions(+), 40 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index 17954ccca..f9d1b57cb 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -28,8 +28,8 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti SimpleMessageQueue simpleMessageQueue = new SimpleMessageQueue(); if (string.IsNullOrEmpty(providerTypeName)) { - GXUtil.ErrorToMessages("Unsupported", "Queue provider cannot be empty", errorMessages); - GXLogging.Error(logger, "Queue provider cannot be empty"); + GXUtil.ErrorToMessages("GXQueue1000", "Queue provider cannot be empty", errorMessages); + GXLogging.Error(logger, "(GXQueue1000)Failed to Connect to a queue : Queue provider cannot be empty."); success = false; return simpleMessageQueue; } @@ -64,8 +64,8 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti } catch (Exception ex) { - GXLogging.Error(logger, "Couldn't connect to Queue provider. " + ex.Message); - GXUtil.ErrorToMessages("Queue Connection Error", ex, errorMessages); + GXLogging.Error(logger, "(GXQueue1001)Couldn't connect to Queue provider: " + ExceptionExtensions.GetInnermostException(ex)); + GXUtil.ErrorToMessages("GXQueue1001", ex, errorMessages); success = false; return simpleMessageQueue; } @@ -90,7 +90,7 @@ private static void Preprocess(String name, GXProperties properties) break; default: - throw new SystemException(string.Format("Provider {0} is not supported", name)); + throw new SystemException(string.Format("Provider {0} is not supported.", name)); } } @@ -104,4 +104,20 @@ private static void SetEncryptedProperty(GXProperties properties, String prop) } } + public static class ExceptionExtensions + { + public static string GetInnermostException(Exception e) + { + Exception ex = e; + if (ex != null) + { + while (ex.InnerException != null) + { + ex = ex.InnerException; + } + + } + return ex.Message; + } + } } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index dfdd214da..526eb86f8 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -35,8 +35,8 @@ void ValidQueue() { if (queue == null) { - GXLogging.Error(logger, "Queue not found"); - throw new Exception("Queue not found"); + GXLogging.Error(logger, "Queue was not instantiated."); + throw new Exception("Queue was not instantiated."); } } @@ -81,10 +81,9 @@ public GxUserType DeleteMessage(out GXBaseCollection errorM { ValidQueue(); messageQueueResult = queue.DeleteMessage(out success); - + LoadAssemblyIfRequired(); try { - LoadAssemblyIfRequired(); if (messageQueueResult != null && TransformMessageQueueResult(messageQueueResult) is GxUserType result) return result; } @@ -101,7 +100,7 @@ public GxUserType DeleteMessage(out GXBaseCollection errorM GXLogging.Error(logger, ex); success = false; } - return messageResult; + return TransformMessageQueueResult(messageQueueResult); } public IList DeleteMessages(List messageHandleId, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) @@ -267,20 +266,23 @@ private GxUserType TransformSimpleQueueMessage(SimpleQueueMessage simpleQueueMes simpleMessageSDT.SetPropertyValue("Messagebody", simpleQueueMessage.MessageBody); simpleMessageSDT.SetPropertyValue("Messagehandleid", simpleQueueMessage.MessageHandleId); - IList messageResultSDTAttributes = (IList)Activator.CreateInstance(classType.GetProperty("gxTpr_Messageattributes").PropertyType, new object[] { simpleMessageSDT.context, "MessageProperty", string.Empty }); - GxKeyValuePair prop = simpleQueueMessage.MessageAttributes.GetFirst(); - while (!simpleQueueMessage.MessageAttributes.Eof()) - { - if (propertyClassType != null && Activator.CreateInstance(propertyClassType) is GxUserType propertyClassTypeSDT) + IList messageResultSDTAttributes = (IList)Activator.CreateInstance(classType.GetProperty("gxTpr_Messageattributes").PropertyType, new object[] { simpleMessageSDT.context, "MessageProperty", string.Empty }); + + if ((simpleQueueMessage != null) && (simpleQueueMessage.MessageAttributes != null)) + { + GxKeyValuePair prop = simpleQueueMessage.MessageAttributes.GetFirst(); + while (!simpleQueueMessage.MessageAttributes.Eof()) { - propertyClassTypeSDT.SetPropertyValue("Propertykey", prop.Key); - propertyClassTypeSDT.SetPropertyValue("Propertyvalue", prop.Value); - messageResultSDTAttributes.Add(propertyClassTypeSDT); - prop = simpleQueueMessage.MessageAttributes.GetNext(); + if (propertyClassType != null && Activator.CreateInstance(propertyClassType) is GxUserType propertyClassTypeSDT) + { + propertyClassTypeSDT.SetPropertyValue("Propertykey", prop.Key); + propertyClassTypeSDT.SetPropertyValue("Propertyvalue", prop.Value); + messageResultSDTAttributes.Add(propertyClassTypeSDT); + prop = simpleQueueMessage.MessageAttributes.GetNext(); + } } + simpleMessageSDT.SetPropertyValue("Messageattributes", messageResultSDTAttributes); } - simpleMessageSDT.SetPropertyValue("Messageattributes", messageResultSDTAttributes); - return simpleMessageSDT; } return null; @@ -298,19 +300,23 @@ private GxUserType TransformMessageQueueResult(MessageQueueResult messageQueueRe messageResultSDT.SetPropertyValue("Messagestatus", messageQueueResult.MessageStatus); IList messageResultSDTAttributes = (IList)Activator.CreateInstance(classType.GetProperty("gxTpr_Messageattributes").PropertyType, new object[] { messageResultSDT.context, "MessageProperty", string.Empty }); - GxKeyValuePair prop = messageQueueResult.MessageAttributes.GetFirst(); - while (!messageQueueResult.MessageAttributes.Eof()) - { - if (propertyClassType != null && Activator.CreateInstance(propertyClassType) is GxUserType propertyClassTypeSDT) + GxKeyValuePair prop; + if ((messageQueueResult != null) && (messageQueueResult.MessageAttributes != null)) + { + prop = messageQueueResult.MessageAttributes.GetFirst(); + while (!messageQueueResult.MessageAttributes.Eof()) { - propertyClassTypeSDT.SetPropertyValue("Propertykey", prop.Key); - propertyClassTypeSDT.SetPropertyValue("Propertyvalue", prop.Value); + if (propertyClassType != null && Activator.CreateInstance(propertyClassType) is GxUserType propertyClassTypeSDT) + { + propertyClassTypeSDT.SetPropertyValue("Propertykey", prop.Key); + propertyClassTypeSDT.SetPropertyValue("Propertyvalue", prop.Value); - messageResultSDTAttributes.Add(propertyClassTypeSDT); - prop = messageQueueResult.MessageAttributes.GetNext(); + messageResultSDTAttributes.Add(propertyClassTypeSDT); + prop = messageQueueResult.MessageAttributes.GetNext(); + } } + messageResultSDT.SetPropertyValue("Messageattributes", messageResultSDTAttributes); } - messageResultSDT.SetPropertyValue("Messageattributes", messageResultSDTAttributes); return messageResultSDT; } return null; @@ -334,14 +340,12 @@ public GxUserType SendMessage(GxUserType simpleQueueMessage, out GXBaseCollectio try { SimpleQueueMessage queueMessage = TransformGXUserTypeToSimpleQueueMessage(simpleQueueMessage); - + LoadAssemblyIfRequired(); try { ValidQueue(); messageQueueResult = queue.SendMessage(queueMessage, out success); - LoadAssemblyIfRequired(); - if (TransformMessageQueueResult(messageQueueResult) is GxUserType messageResult) return messageResult; success = true; @@ -359,7 +363,8 @@ public GxUserType SendMessage(GxUserType simpleQueueMessage, out GXBaseCollectio GXLogging.Error(logger,ex); throw ex; } - return result; + + return TransformMessageQueueResult(messageQueueResult); } public IList SendMessages(IList simpleQueueMessages, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) @@ -370,19 +375,17 @@ public IList SendMessages(IList simpleQueueMessages, GxUserType mess { // Load Message Queue Options// MessageQueueOptions options = TransformOptions(messageQueueOptions); - + IList simpleQueueMessagesList = new List(); foreach (GxUserType simpleQueueMessage in simpleQueueMessages) { - if (TransformGXUserTypeToSimpleQueueMessage(simpleQueueMessage) is SimpleQueueMessage queueMessage) - + if (TransformGXUserTypeToSimpleQueueMessage(simpleQueueMessage) is SimpleQueueMessage queueMessage) simpleQueueMessagesList.Add(queueMessage); } try { ValidQueue(); IList messageQueueResults = queue.SendMessages(simpleQueueMessagesList, options, out success); - LoadAssemblyIfRequired(); foreach (MessageQueueResult messageResult in messageQueueResults) { @@ -428,8 +431,8 @@ protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection Date: Mon, 6 Jun 2022 09:50:35 -0300 Subject: [PATCH 08/14] Add implementation for AWS SQS --- dotnet/DotNetStandardClasses.sln | 23 +- .../Messaging/GXAmazonSQS/AWSQueue.cs | 585 ++++++++++++++++++ .../Messaging/GXAmazonSQS/GXAmazonSQS.csproj | 17 + .../Messaging/GXQueue/MessageQueueProvider.cs | 12 +- .../Providers/Messaging/GXQueue/Queue.cs | 3 + 5 files changed, 626 insertions(+), 14 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index 2f9ac280e..b535cf4ec 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -188,15 +188,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GxXsl", "src\dotnetcore\GxXsl\GxXsl.csproj", "{30E7E437-F9B0-42B8-9144-A8E8F972B462}" EndProject - -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXAzureQueue", "src\dotnetcore\Providers\Messaging\GXAzureQueue\GXAzureQueue.csproj", "{0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXAzureQueue", "src\dotnetcore\Providers\Messaging\GXAzureQueue\GXAzureQueue.csproj", "{0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "messaging", "messaging", "{30159B0F-BE61-4DB7-AC02-02851426BE4B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{4C43F2DA-59E5-46F5-B691-195449498555}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXQueue", "src\dotnetcore\Providers\Messaging\GXQueue\GXQueue.csproj", "{C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}" - +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXQueue", "src\dotnetcore\Providers\Messaging\GXQueue\GXQueue.csproj", "{C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mocking", "mocking", "{5045873B-E7CF-4317-94C1-0EF8623D23FA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8E5A25F9-2D64-4742-8227-2A3C5816AFEC}" @@ -206,10 +205,11 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C16BD5A9-4412-4B91-BB70-5C88B7AAE675}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestMockDBAccess", "src\extensions\mocking\test\TestMockDBAccess\TestMockDBAccess.csproj", "{B01A243D-C012-4BEB-BAA9-E1D9AC1468C8}" - EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneXus.Programs.Common", "src\extensions\Azure\test\GeneXus.Programs.Common\GeneXus.Programs.Common.csproj", "{DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXAmazonSQS", "src\dotnetcore\Providers\Messaging\GXAmazonSQS\GXAmazonSQS.csproj", "{F8BA0D65-267D-491F-BFAB-33F5E5B61AD7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -484,7 +484,6 @@ Global {30E7E437-F9B0-42B8-9144-A8E8F972B462}.Debug|Any CPU.Build.0 = Debug|Any CPU {30E7E437-F9B0-42B8-9144-A8E8F972B462}.Release|Any CPU.ActiveCfg = Release|Any CPU {30E7E437-F9B0-42B8-9144-A8E8F972B462}.Release|Any CPU.Build.0 = Release|Any CPU - {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Debug|Any CPU.Build.0 = Debug|Any CPU {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -493,7 +492,6 @@ Global {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Debug|Any CPU.Build.0 = Debug|Any CPU {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Release|Any CPU.ActiveCfg = Release|Any CPU {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82}.Release|Any CPU.Build.0 = Release|Any CPU - {8D05D621-3DB3-459F-8665-BEA4574F4EFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D05D621-3DB3-459F-8665-BEA4574F4EFF}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D05D621-3DB3-459F-8665-BEA4574F4EFF}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -502,12 +500,14 @@ Global {B01A243D-C012-4BEB-BAA9-E1D9AC1468C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {B01A243D-C012-4BEB-BAA9-E1D9AC1468C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {B01A243D-C012-4BEB-BAA9-E1D9AC1468C8}.Release|Any CPU.Build.0 = Release|Any CPU - {DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Debug|Any CPU.Build.0 = Debug|Any CPU {DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Release|Any CPU.ActiveCfg = Release|Any CPU {DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Release|Any CPU.Build.0 = Release|Any CPU - + {F8BA0D65-267D-491F-BFAB-33F5E5B61AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8BA0D65-267D-491F-BFAB-33F5E5B61AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8BA0D65-267D-491F-BFAB-33F5E5B61AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8BA0D65-267D-491F-BFAB-33F5E5B61AD7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -598,20 +598,17 @@ Global {B59F76D8-FDB2-4F51-89DB-F15E9BDFF1DC} = {420E8A4A-11D9-42E9-BFB7-4325EA7330B8} {D97E17A4-C945-4BF3-957E-F73142C4C6D0} = {947E032A-C385-4586-96E3-FC7D2767F082} {30E7E437-F9B0-42B8-9144-A8E8F972B462} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3} - {0CED9D4D-EE7C-4E19-9FC6-D4BBCB04DA97} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} {30159B0F-BE61-4DB7-AC02-02851426BE4B} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3} {4C43F2DA-59E5-46F5-B691-195449498555} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} {C1AC62A2-0FAC-4762-9B1A-47BB9FE5BF82} = {4C43F2DA-59E5-46F5-B691-195449498555} - {5045873B-E7CF-4317-94C1-0EF8623D23FA} = {C6AFB6A3-FF0B-4970-B1F1-10BCD3D932B2} {8E5A25F9-2D64-4742-8227-2A3C5816AFEC} = {5045873B-E7CF-4317-94C1-0EF8623D23FA} {8D05D621-3DB3-459F-8665-BEA4574F4EFF} = {8E5A25F9-2D64-4742-8227-2A3C5816AFEC} {C16BD5A9-4412-4B91-BB70-5C88B7AAE675} = {5045873B-E7CF-4317-94C1-0EF8623D23FA} {B01A243D-C012-4BEB-BAA9-E1D9AC1468C8} = {C16BD5A9-4412-4B91-BB70-5C88B7AAE675} - {DCEC0B38-93B6-4003-81E6-9FBC2BB4F163} = {7BA5A2CE-7992-4F87-9D84-91AE4D046F5A} - + {F8BA0D65-267D-491F-BFAB-33F5E5B61AD7} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs new file mode 100644 index 000000000..3c524d37b --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -0,0 +1,585 @@ +using System; +using System.Collections.Generic; +using Amazon; +using Amazon.Runtime; +using Amazon.SQS; +using Amazon.SQS.Model; +using GeneXus.Messaging.Common; +using GeneXus.Services; +using GeneXus.Utils; +using log4net; +using System.Threading.Tasks; +using System.Reflection; + +namespace GeneXus.Messaging.Queue +{ + public class AWSQueue : QueueBase, IQueue + { + + public static String Name = "AWSSQS"; + const string ACCESS_KEY = "ACCESS_KEY"; + const string SECRET_ACCESS_KEY = "SECRET_KEY"; + const string REGION = "REGION"; + const string QUEUE_URL = "QUEUE_URL"; + + AmazonSQSClient _sqsClient; + private string _accessKey; + private string _secret; + private string _awsregion; + private string _queueURL; + private bool _isFIFO; + public const string MESSSAGE_GROUP_ID = "MessageGroupId"; + public const string MESSSAGE_DEDUPLICATION_ID = "MessageDeduplicationId"; + + static readonly ILog logger = log4net.LogManager.GetLogger(typeof(AWSQueue)); + + public AWSQueue() : this(null) + { + } + + public AWSQueue(GXService providerService) : base(providerService) + { + Initialize(providerService); + + BasicAWSCredentials basicCredentials = new BasicAWSCredentials(_accessKey, _secret); + RegionEndpoint region = RegionEndpoint.GetBySystemName(_awsregion); + + _sqsClient = new AmazonSQSClient(basicCredentials, region); + } + + private void Initialize(GXService providerService) + { + ServiceSettings serviceSettings = new("QUEUE", Name, providerService); + + _queueURL = serviceSettings.GetEncryptedPropertyValue(QUEUE_URL); + _accessKey = serviceSettings.GetEncryptedPropertyValue(ACCESS_KEY); + _secret = serviceSettings.GetEncryptedPropertyValue(SECRET_ACCESS_KEY); + _awsregion = serviceSettings.GetEncryptedPropertyValue(REGION); + + _isFIFO = _queueURL.EndsWith(".fifo"); + + } + public void Clear(out bool success) + { + try + { + Task task = Task.Run(async () => await PurgeQueueAsync()); + PurgeQueueResponse response = task.Result; + success = response != null; + + } + catch (AggregateException ae) + { + throw ae; + } + } + + public MessageQueueResult DeleteMessage(out bool success) + { + success= false; + IList simpleQueueMessages = GetMessages(out bool isOK); + IList messageQueueResults = new List(); + MessageQueueResult messageQueueResult = new MessageQueueResult(); + List messageHandleId; + if ((simpleQueueMessages != null) && (isOK)) + { + messageHandleId = new List{ simpleQueueMessages[0].MessageHandleId }; + messageQueueResults = RemoveMessages(messageHandleId, out bool operationOK); + if ((operationOK) && (messageQueueResults != null)) + messageQueueResult = messageQueueResults[0]; + success= true; + } + return messageQueueResult; + } + + public IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions, out bool success) + { + return RemoveMessages(messageHandleId, out success, messageQueueOptions); + } + private IList RemoveMessages(List messageHandleId, out bool success, MessageQueueOptions messageQueueOptions= null) + { + IList messageQueueResults = new List(); + success = false; + try + { + Task task = Task.Run(async () => await DeleteQueueMessageBatchAsync(messageHandleId,messageQueueOptions)); + + DeleteMessageBatchResponse deleteMessageBatchResponse = task.Result; + if (deleteMessageBatchResponse != null) + success = (deleteMessageBatchResponse.Failed.Count == 0); + + foreach (BatchResultErrorEntry entry in deleteMessageBatchResponse.Failed) + { + MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); + messageQueueResults.Add(messageQueueResult); + } + + foreach (DeleteMessageBatchResultEntry entry in deleteMessageBatchResponse.Successful) + { + MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); + messageQueueResults.Add(messageQueueResult); + } + + } + catch (AggregateException ae) + { + throw ae; + } + return messageQueueResults; + } + + public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) + { + try + { + AmazonSQSException sqs_ex = (AmazonSQSException)ex; + msg.gxTpr_Id = sqs_ex.ErrorCode; + msg.gxTpr_Description = sqs_ex.Message; + return true; + } + catch (Exception) + { + return false; + } + } + + public IList GetMessages(out bool success) + { + return RetrieveMessages(success : out success); + } + + public IList GetMessages(MessageQueueOptions messageQueueOptions, out bool success) + { + return RetrieveMessages(out success, messageQueueOptions); + } + private IList RetrieveMessages(out bool success, MessageQueueOptions messageQueueOptions = null) + { + success = false; + IList simpleQueueMessages = new List(); + try + { + Task task = Task.Run(async () => await GetMessageAsync(messageQueueOptions)); + + ReceiveMessageResponse response = task.Result; + success = response != null; + if (success) + { + List messagesList = response.Messages; + + foreach (Message message in messagesList) + { + SimpleQueueMessage simpleQueueMessage = SetupSimpleQueueMessage(message); + simpleQueueMessages.Add(simpleQueueMessage); + } + } + } + catch (AggregateException ae) + { + throw ae; + } + return simpleQueueMessages; + } + + public override string GetName() + { + return Name; + } + + public int GetQueueLength(out bool success) + { + int approxNumberMessages = 0; + success = false; + try + { + List attributes = new List { "ApproximateNumberOfMessages" }; + Task task = Task.Run(async () => await GetQueueAttributeAsync(attributes).ConfigureAwait(false)); + GetQueueAttributesResponse response = task.Result; + success = response != null; + if (success) + { + return (response.ApproximateNumberOfMessages); + } + + } + catch (Exception ex) + { + throw ex; + } + return approxNumberMessages; + } + + public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out bool success) + { + success = false; + MessageQueueResult messageQueueResult = new MessageQueueResult(); + try + { + Task task = Task.Run(async () => await SendMessageAsync(simpleQueueMessage).ConfigureAwait(false)); + SendMessageResponse response = task.Result; + success = response != null; + + if (success) + { + messageQueueResult = SetupMessageQueueResult(response); + } + + } + catch (Exception ex) + { + throw ex; + } + return messageQueueResult; + } + + + public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success) + { + success = false; + MessageQueueResult messageQueueResult = new MessageQueueResult(); + try + { + Task task = Task.Run(async () => await SendMessageAsync(simpleQueueMessage, messageQueueOptions).ConfigureAwait(false)); + SendMessageResponse response = task.Result; + success = response != null; + + if (success) + { + messageQueueResult = SetupMessageQueueResult(response); + } + + } + catch (Exception ex) + { + throw ex; + } + return messageQueueResult; + } + + public IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success) + { + success = false; + IList messageQueueResults = new List(); + try + { + Task task = Task.Run(async () => await SendMessageBatchAsync(simpleQueueMessages, messageQueueOptions)); + SendMessageBatchResponse sendMessageBatchResponse = task.Result; + if (sendMessageBatchResponse != null) + success = (sendMessageBatchResponse.Failed.Count == 0); + + foreach (BatchResultErrorEntry entry in sendMessageBatchResponse.Failed) + { + MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); + messageQueueResults.Add(messageQueueResult); + } + + foreach (SendMessageBatchResultEntry entry in sendMessageBatchResponse.Successful) + { + MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); + messageQueueResults.Add(messageQueueResult); + } + + } + catch (AggregateException ae) + { + + throw ae; + //foreach (var ex in ae.InnerExceptions) + //{ + //Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message); + //mlogger.LogCritical(ex.Message); + + //} + } + return messageQueueResults; + } + private MessageQueueResult SetupMessageQueueResult(SendMessageResponse response) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + messageQueueResult.MessageId = response.MessageId; + messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent; + + messageQueueResult.MessageAttributes = new GXProperties(); + + messageQueueResult.MessageAttributes.Add("MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes); + messageQueueResult.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes); + messageQueueResult.MessageAttributes.Add("ContentLength", response.ContentLength.ToString()); + messageQueueResult.MessageAttributes.Add("MD5OfMessageBody", response.MD5OfMessageBody); + messageQueueResult.MessageAttributes.Add("SequenceNumber", response.SequenceNumber); + + Type t = response.ResponseMetadata.GetType(); + PropertyInfo[] props = t.GetProperties(); + + foreach (PropertyInfo prop in props) + { + object value; + if (prop.GetIndexParameters().Length == 0 && response.ResponseMetadata != null) + { + value = prop.GetValue(response.ResponseMetadata); + if (value != null) + messageQueueResult.MessageAttributes.Add(prop.Name, value.ToString()); + } + } + return messageQueueResult; + } + + private MessageQueueResult SetupMessageQueueResult(SendMessageBatchResultEntry response) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + messageQueueResult.MessageId = response.MessageId; + messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent; + + messageQueueResult.MessageAttributes = new GXProperties(); + + messageQueueResult.MessageAttributes.Add("MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes); + messageQueueResult.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes); + messageQueueResult.MessageAttributes.Add("MD5OfMessageBody", response.MD5OfMessageBody); + messageQueueResult.MessageAttributes.Add("SequenceNumber", response.SequenceNumber); + return messageQueueResult; + } + + private MessageQueueResult SetupMessageQueueResult(DeleteMessageBatchResultEntry response) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + messageQueueResult.MessageStatus = MessageQueueResultStatus.Deleted; + messageQueueResult.MessageId = response.Id; + return messageQueueResult; + } + + private MessageQueueResult SetupMessageQueueResult(BatchResultErrorEntry response) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + messageQueueResult.MessageStatus = MessageQueueResultStatus.Failed; + messageQueueResult.MessageId = response.Id; + + //Write error codes to log in debug mode + GXLogging.Debug(logger, $"Error processing SQS. Message: {response.Id}. Error: {response.Message}({response.Code})"); + + return messageQueueResult; + } + + private SimpleQueueMessage SetupSimpleQueueMessage(Message response) + { + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + simpleQueueMessage.MessageId = response.MessageId; + simpleQueueMessage.MessageBody = response.Body; + simpleQueueMessage.MessageHandleId = response.ReceiptHandle; + + simpleQueueMessage.MessageAttributes = new GXProperties(); + + simpleQueueMessage.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes); + simpleQueueMessage.MessageAttributes.Add("MD5OfBody", response.MD5OfBody); + + foreach (var messageAttribute in response.MessageAttributes) + { + MessageAttributeValue messageAttributeValue = messageAttribute.Value; + simpleQueueMessage.MessageAttributes.Add(messageAttribute.Key, messageAttribute.Value.StringValue); + } + + foreach (var attribute in response.Attributes) + { + simpleQueueMessage.MessageAttributes.Add(attribute.Key, attribute.Value); + } + + return simpleQueueMessage; + } + + private async Task SendMessageAsync(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions = null) + { + SendMessageResponse sendMessageResponse = new SendMessageResponse(); + + if (simpleQueueMessage != null) + { + GXProperties messageAttributes = simpleQueueMessage.MessageAttributes; + Dictionary properties = new Dictionary(); + + GxKeyValuePair messageAttribute = new GxKeyValuePair(); + if (messageAttributes != null) + messageAttribute = messageAttributes.GetFirst(); + while (!messageAttributes.Eof()) + { + properties.Add(messageAttribute.Key, new MessageAttributeValue() { DataType = "String", StringValue = messageAttribute.Value }); + messageAttribute = messageAttributes.GetNext(); + } + + SendMessageRequest sendMessageRequest = new SendMessageRequest + { + QueueUrl = _queueURL, + MessageBody = simpleQueueMessage.MessageBody, + MessageAttributes = properties + }; + + if (messageQueueOptions != null && messageQueueOptions.DelaySeconds != 0) + sendMessageRequest.DelaySeconds = messageQueueOptions.DelaySeconds; + + if ((messageAttributes != null) && (_isFIFO)) + { + string mesageGroupId = messageAttributes.Get(MESSSAGE_GROUP_ID); + string messageDeduplicationId = messageAttributes.Get(MESSSAGE_DEDUPLICATION_ID); + + if ((mesageGroupId != null) && (mesageGroupId != null)) + { + sendMessageRequest.MessageGroupId = mesageGroupId; + sendMessageRequest.MessageDeduplicationId = messageDeduplicationId; + + } + } + sendMessageResponse = await _sqsClient.SendMessageAsync(sendMessageRequest).ConfigureAwait(false); + } + return sendMessageResponse; + } + + private async Task SendMessageBatchAsync(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions) + { + + List messageBatchRequestEntries = new List(); + SendMessageBatchResponse responseSendBatch = new SendMessageBatchResponse(); + + foreach (SimpleQueueMessage simpleQueueMessage in simpleQueueMessages) + { + SendMessageBatchRequestEntry requestEntry = new SendMessageBatchRequestEntry(); + GXProperties messageAttributes = simpleQueueMessage.MessageAttributes; + Dictionary properties = new Dictionary(); + + GxKeyValuePair messageAttribute = new GxKeyValuePair(); + if (messageAttributes != null) + messageAttribute = messageAttributes.GetFirst(); + while (!messageAttributes.Eof()) + { + properties.Add(messageAttribute.Key, new MessageAttributeValue() { DataType = "String", StringValue = messageAttribute.Value }); + messageAttribute = messageAttributes.GetNext(); + } + + requestEntry.MessageBody = simpleQueueMessage.MessageBody; + requestEntry.Id = simpleQueueMessage.MessageId; + requestEntry.MessageAttributes = properties; + if (messageQueueOptions.DelaySeconds != 0) + requestEntry.DelaySeconds = messageQueueOptions.DelaySeconds; + + if ((messageAttributes != null) && (_isFIFO)) + { + string mesageGroupId = messageAttributes.Get(MESSSAGE_GROUP_ID); + string messageDeduplicationId = messageAttributes.Get(MESSSAGE_DEDUPLICATION_ID); + + if ((mesageGroupId != null) && (mesageGroupId != null)) + { + requestEntry.MessageGroupId = mesageGroupId; + requestEntry.MessageDeduplicationId = messageDeduplicationId; + } + } + + messageBatchRequestEntries.Add(requestEntry); + } + if (messageBatchRequestEntries.Count > 0) + responseSendBatch = await _sqsClient.SendMessageBatchAsync(_queueURL, messageBatchRequestEntries).ConfigureAwait(false); + + return (responseSendBatch); + + } + + private async Task GetMessageAsync(MessageQueueOptions messageQueueOptions = null) + { + ReceiveMessageResponse receiveMessageResponse = new ReceiveMessageResponse(); + try + { + + ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(); + receiveMessageRequest.QueueUrl = _queueURL; + if (messageQueueOptions != null) + { + if (messageQueueOptions.MaxNumberOfMessages != 0) + receiveMessageRequest.MaxNumberOfMessages = messageQueueOptions.MaxNumberOfMessages; + if (messageQueueOptions.VisibilityTimeout != 0) + receiveMessageRequest.VisibilityTimeout = messageQueueOptions.VisibilityTimeout; + if (messageQueueOptions.WaitTimeout != 0) + receiveMessageRequest.WaitTimeSeconds = messageQueueOptions.WaitTimeout; + if (! string.IsNullOrEmpty(messageQueueOptions.ReceiveRequestAttemptId)) + receiveMessageRequest.ReceiveRequestAttemptId = messageQueueOptions.ReceiveRequestAttemptId; + // TO DO : Check only for specific attrributes in the list + + if (messageQueueOptions.ReceiveMessageAttributes) + { + receiveMessageRequest.AttributeNames = new List { "All" }; + receiveMessageRequest.MessageAttributeNames = new List() { "All" }; + } + } + + return await _sqsClient.ReceiveMessageAsync(receiveMessageRequest).ConfigureAwait(false); + } + catch (TaskCanceledException) + { + GXLogging.Debug(logger, $"Get Message Operation cancelled for SQS {_queueURL}."); + } + catch (Exception ex) + { + throw (ex); + } + return receiveMessageResponse; + } + + private async Task DeleteQueueMessageBatchAsync(List messageHandleId, MessageQueueOptions messageQueueOptions) + { + DeleteMessageBatchResponse deleteMessageBatchResponse = new DeleteMessageBatchResponse(); + try + { + + List deleteMessageBatchRequestEntries = new List(); + + foreach (string handleId in messageHandleId) + { + DeleteMessageBatchRequestEntry deleteMessageBatchRequestEntry = new DeleteMessageBatchRequestEntry(); + deleteMessageBatchRequestEntry.ReceiptHandle = handleId; + deleteMessageBatchRequestEntry.Id = Guid.NewGuid().ToString(); + deleteMessageBatchRequestEntries.Add(deleteMessageBatchRequestEntry); + } + + deleteMessageBatchResponse = await _sqsClient.DeleteMessageBatchAsync(_queueURL, deleteMessageBatchRequestEntries).ConfigureAwait(false); + } + catch (Exception ex) + { + throw (ex); + } + return deleteMessageBatchResponse; + } + + private async Task PurgeQueueAsync() + { + PurgeQueueResponse purgeQueueResponse = new PurgeQueueResponse(); + try + { + PurgeQueueRequest purgeQueueRequest = new PurgeQueueRequest(); + purgeQueueRequest.QueueUrl = _queueURL; + + purgeQueueResponse= await _sqsClient.PurgeQueueAsync(purgeQueueRequest).ConfigureAwait(false); + } + catch (Exception ex) + { + throw (ex); + } + return purgeQueueResponse; + } + + private async Task GetQueueAttributeAsync(List attributesName) + { + GetQueueAttributesResponse getQueueAttributesResponse = new GetQueueAttributesResponse(); + GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest(); + try + { + getQueueAttributesRequest.QueueUrl= _queueURL; + if (attributesName == null) + getQueueAttributesRequest.AttributeNames.Add("All"); + foreach (string name in attributesName) + getQueueAttributesRequest.AttributeNames.Add(name); + getQueueAttributesResponse = await _sqsClient.GetQueueAttributesAsync(getQueueAttributesRequest).ConfigureAwait(false); + } + catch (Exception ex) + { + throw (ex); + } + return getQueueAttributesResponse; + + } + } + +} + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj new file mode 100644 index 000000000..b9f71c2aa --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + + + + + + + + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index f9d1b57cb..f751507f5 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -88,10 +88,20 @@ private static void Preprocess(String name, GXProperties properties) providerService.ClassName = "GeneXus.Messaging.Queue.AzureQueue, GXAzureQueue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; } break; + case "AWS_SQS": + className = "GeneXus.Messaging.Queue.AWSQueue"; + SetEncryptedProperty(properties, "QUEUE_AWSSQS_QUEUE_URL"); + SetEncryptedProperty(properties, "QUEUE_AWSSQS_ACCESS_KEY"); + SetEncryptedProperty(properties, "QUEUE_AWSSQS_SECRET_KEY"); + SetEncryptedProperty(properties, "QUEUE_AWSSQS_REGION"); + if (string.IsNullOrEmpty(providerService.ClassName) || !providerService.ClassName.Contains(className)) + { + providerService.ClassName = "GeneXus.Messaging.Queue.AWSQueue, GXAmazonSQS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + } + break; default: throw new SystemException(string.Format("Provider {0} is not supported.", name)); - } } private static void SetEncryptedProperty(GXProperties properties, String prop) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs index a500ea206..17244eb8a 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs @@ -112,6 +112,9 @@ public class MessageQueueOptions : GxUserType public int WaitTimeout { get; set; } public int VisibilityTimeout { get; set; } public int TimetoLive { get; set; } + public int DelaySeconds { get; set; } + public string ReceiveRequestAttemptId { get; set; } + public bool ReceiveMessageAttributes { get; set; } } From 9be042b3a89192fa91d1954b50d566ab3eb00800 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Mon, 6 Jun 2022 18:23:51 -0300 Subject: [PATCH 09/14] Fix error in condition. --- .../Providers/Messaging/GXAmazonSQS/AWSQueue.cs | 9 +-------- .../src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index 3c524d37b..6d599df0a 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -281,14 +281,7 @@ public IList SendMessages(IList simpleQu } catch (AggregateException ae) { - throw ae; - //foreach (var ex in ae.InnerExceptions) - //{ - //Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message); - //mlogger.LogCritical(ex.Message); - - //} } return messageQueueResults; } @@ -416,7 +409,7 @@ private async Task SendMessageAsync(SimpleQueueMessage simp string mesageGroupId = messageAttributes.Get(MESSSAGE_GROUP_ID); string messageDeduplicationId = messageAttributes.Get(MESSSAGE_DEDUPLICATION_ID); - if ((mesageGroupId != null) && (mesageGroupId != null)) + if ((mesageGroupId != null) && (messageDeduplicationId != null)) { sendMessageRequest.MessageGroupId = mesageGroupId; sendMessageRequest.MessageDeduplicationId = messageDeduplicationId; diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs index 17244eb8a..6112899eb 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs @@ -53,7 +53,6 @@ public override void ToJSON(bool includeState) AddObjectProperty("MessageId", MessageId, false); AddObjectProperty("MessageBody", MessageBody, false); AddObjectProperty("MessageHandleId", MessageHandleId, false); - //Properties? return; } @@ -92,13 +91,7 @@ public override void ToJSON(bool includeState) AddObjectProperty("ServerMessageId", ServerMessageId, false); AddObjectProperty("MessageHandleId", MessageHandleId, false); AddObjectProperty("MessageStatus", MessageStatus, false); - //GxKeyValuePair prop = MessageAttributes.GetFirst(); - //while (!MessageAttributes.Eof()) - //{ - //AddObjectProperty("MessageStatus", MessageStatus, false); - - //prop = MessageAttributes.GetNext(); - // } + return; } From df844cabf9a717611dca6da7c14cf358d959f33a Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Sat, 11 Jun 2022 20:14:44 -0300 Subject: [PATCH 10/14] Add specific connect implementation for each provider --- .../GXAmazonSQS/AWSMessageQueueProvider.cs | 31 +++++++++++++++++++ .../GXAzureQueue/AzureMessageQueueProvider.cs | 22 +++++++++++++ .../Messaging/GXQueue/ServiceSettings.cs | 2 +- .../GxClasses/Domain/GxCollections.cs | 4 +-- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs new file mode 100644 index 000000000..dfe82b20f --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs @@ -0,0 +1,31 @@ +using GeneXus.Messaging.Common; +using GeneXus.Utils; + +namespace GeneXus.Messaging.Queue +{ + public class AWSMessageQueueProvider + { + private const string AWS_SQS = "AWS_SQS"; + public SimpleMessageQueue Connect(GxUserType awsCredentials, string queueURL, out GXBaseCollection errorMessages, out bool success) + + { + MessageQueueProvider messageQueueProvider = new MessageQueueProvider(); + GXProperties properties = TransformAWSCredentials(awsCredentials); + properties.Add("QUEUE_AWSSQS_QUEUE_URL", queueURL); + SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(AWS_SQS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return simpleMessageQueue; + } + + public GXProperties TransformAWSCredentials(GxUserType awsCredentials) + { + GXProperties properties = new GXProperties(); + properties.Add("QUEUE_AWSSQS_ACCESS_KEY", awsCredentials.GetPropertyValue("Access_key")); + properties.Add("QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue("Secret_access_key")); + properties.Add("QUEUE_AWSSQS_REGION", awsCredentials.GetPropertyValue("Region")); + properties.Add("QUEUE_AWSSQ_IAM_Role", awsCredentials.GetPropertyValue("Iam_role")); + return properties; + } + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs new file mode 100644 index 000000000..9f6857498 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs @@ -0,0 +1,22 @@ +using GeneXus.Messaging.Common; +using GeneXus.Utils; + +namespace GeneXus.Messaging.Queue +{ + public class AzureMessageQueueProvider + { + private const string AZUREQUEUE = "AZUREQUEUE"; + public SimpleMessageQueue Connect(string queueName, string queueURL, out GXBaseCollection errorMessages, out bool success) + + { + MessageQueueProvider messageQueueProvider = new MessageQueueProvider(); + GXProperties properties = new GXProperties(); + properties.Add("QUEUE_AZUREQUEUE_QUEUENAME", queueName); + properties.Add("QUEUE_AZUREQUEUE_CONNECTIONSTRING", queueURL); + SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(AZUREQUEUE, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return simpleMessageQueue; + } + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs index 6e315e6bb..d022cee19 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs @@ -85,7 +85,7 @@ internal string GetPropertyValueImpl(string propertyName) if (!string.IsNullOrEmpty(propertyName)) { value = Environment.GetEnvironmentVariable(propertyName); - if (service != null) + if (service != null && value == null) { value = service.Properties.Get(propertyName); } diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 97a9c203d..16d3b909a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -1983,12 +1983,12 @@ public bool FromXmlFile(GxFile file, GXBaseCollection Messa return false; } - internal T GetPropertyValue(string propertyName) + public T GetPropertyValue(string propertyName) { return (T)GetType().GetProperty($"gxTpr_{propertyName}").GetValue(this); } - internal void SetPropertyValue(string propertyName, object propertyValue) + public void SetPropertyValue(string propertyName, object propertyValue) { GetType().GetProperty($"gxTpr_{propertyName}").SetValue(this, propertyValue); } From ae3fe4720967a6919b01cc4eda33e1c04478d1ad Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Sun, 19 Jun 2022 22:03:54 -0300 Subject: [PATCH 11/14] Changes in property names --- .../GXAmazonSQS/AWSMessageQueueProvider.cs | 16 ++- .../Messaging/GXAmazonSQS/AWSQueue.cs | 132 ++++++++++-------- .../Messaging/GXAzureQueue/AzureQueue.cs | 24 ++-- .../Messaging/GXQueue/MessageQueueProvider.cs | 4 - .../Providers/Messaging/GXQueue/Queue.cs | 8 +- .../Messaging/GXQueue/SimpleMessageQueue.cs | 12 +- .../GxClasses/Domain/GxCollections.cs | 2 - .../DotNetCoreUnitTest/Queue/QueueTest.cs | 12 +- 8 files changed, 115 insertions(+), 95 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs index dfe82b20f..ebf20e338 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs @@ -17,14 +17,24 @@ public SimpleMessageQueue Connect(GxUserType awsCredentials, string queueURL, ou success = successConnect; return simpleMessageQueue; } + public SimpleMessageQueue Connect(string queueURL, out GXBaseCollection errorMessages, out bool success) + + { + MessageQueueProvider messageQueueProvider = new MessageQueueProvider(); + GXProperties properties = new GXProperties(); + properties.Add("QUEUE_AWSSQS_QUEUE_URL", queueURL); + SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(AWS_SQS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return simpleMessageQueue; + } public GXProperties TransformAWSCredentials(GxUserType awsCredentials) { GXProperties properties = new GXProperties(); - properties.Add("QUEUE_AWSSQS_ACCESS_KEY", awsCredentials.GetPropertyValue("Access_key")); - properties.Add("QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue("Secret_access_key")); + properties.Add("QUEUE_AWSSQS_ACCESS_KEY", awsCredentials.GetPropertyValue("Accesskey")); + properties.Add("QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue("Secretkey")); properties.Add("QUEUE_AWSSQS_REGION", awsCredentials.GetPropertyValue("Region")); - properties.Add("QUEUE_AWSSQ_IAM_Role", awsCredentials.GetPropertyValue("Iam_role")); return properties; } } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index 6d599df0a..894250a97 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -40,11 +40,18 @@ public AWSQueue() : this(null) public AWSQueue(GXService providerService) : base(providerService) { Initialize(providerService); - - BasicAWSCredentials basicCredentials = new BasicAWSCredentials(_accessKey, _secret); + BasicAWSCredentials basicCredentials; RegionEndpoint region = RegionEndpoint.GetBySystemName(_awsregion); - _sqsClient = new AmazonSQSClient(basicCredentials, region); + if ((_accessKey != null) && (_secret != null)) + { + basicCredentials = new BasicAWSCredentials(_accessKey, _secret); + _sqsClient = new AmazonSQSClient(basicCredentials, region); + } + else //Use IAM Role + { + _sqsClient = new AmazonSQSClient(region); + } } private void Initialize(GXService providerService) @@ -74,35 +81,32 @@ public void Clear(out bool success) } } - public MessageQueueResult DeleteMessage(out bool success) + public MessageQueueResult DeleteMessage(string messageHandleId, out bool success) { success= false; - IList simpleQueueMessages = GetMessages(out bool isOK); - IList messageQueueResults = new List(); MessageQueueResult messageQueueResult = new MessageQueueResult(); - List messageHandleId; - if ((simpleQueueMessages != null) && (isOK)) + + List messageHandleIdToDelete = new List{ messageHandleId }; + IList messageQueueResults = RemoveMessages(messageHandleIdToDelete, out bool operationOK); + if ((operationOK) && (messageQueueResults != null)) { - messageHandleId = new List{ simpleQueueMessages[0].MessageHandleId }; - messageQueueResults = RemoveMessages(messageHandleId, out bool operationOK); - if ((operationOK) && (messageQueueResults != null)) - messageQueueResult = messageQueueResults[0]; + messageQueueResult = messageQueueResults[0]; success= true; } return messageQueueResult; } - public IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions, out bool success) + public IList DeleteMessages(List messageHandleId, out bool success) { - return RemoveMessages(messageHandleId, out success, messageQueueOptions); + return RemoveMessages(messageHandleId, out success); } - private IList RemoveMessages(List messageHandleId, out bool success, MessageQueueOptions messageQueueOptions= null) + private IList RemoveMessages(List messageHandleId, out bool success) { IList messageQueueResults = new List(); success = false; try { - Task task = Task.Run(async () => await DeleteQueueMessageBatchAsync(messageHandleId,messageQueueOptions)); + Task task = Task.Run(async () => await DeleteQueueMessageBatchAsync(messageHandleId)); DeleteMessageBatchResponse deleteMessageBatchResponse = task.Result; if (deleteMessageBatchResponse != null) @@ -128,21 +132,6 @@ private IList RemoveMessages(List messageHandleId, o return messageQueueResults; } - public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) - { - try - { - AmazonSQSException sqs_ex = (AmazonSQSException)ex; - msg.gxTpr_Id = sqs_ex.ErrorCode; - msg.gxTpr_Description = sqs_ex.Message; - return true; - } - catch (Exception) - { - return false; - } - } - public IList GetMessages(out bool success) { return RetrieveMessages(success : out success); @@ -180,11 +169,6 @@ private IList RetrieveMessages(out bool success, MessageQueu return simpleQueueMessages; } - public override string GetName() - { - return Name; - } - public int GetQueueLength(out bool success) { int approxNumberMessages = 0; @@ -212,45 +196,58 @@ public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out { success = false; MessageQueueResult messageQueueResult = new MessageQueueResult(); + List simpleQueueMessages = new List() { simpleQueueMessage }; try { - Task task = Task.Run(async () => await SendMessageAsync(simpleQueueMessage).ConfigureAwait(false)); - SendMessageResponse response = task.Result; - success = response != null; + Task task = Task.Run(async () => await SendMessageBatchAsync(simpleQueueMessages)); + SendMessageBatchResponse sendMessageBatchResponse = task.Result; + if (sendMessageBatchResponse != null) + success = (sendMessageBatchResponse.Failed.Count == 0); - if (success) + foreach (BatchResultErrorEntry entry in sendMessageBatchResponse.Failed) + { + messageQueueResult = SetupMessageQueueResult(entry); + } + + foreach (SendMessageBatchResultEntry entry in sendMessageBatchResponse.Successful) { - messageQueueResult = SetupMessageQueueResult(response); + messageQueueResult = SetupMessageQueueResult(entry); } } - catch (Exception ex) + catch (AggregateException ae) { - throw ex; + throw ae; } return messageQueueResult; } - - public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success) + protected MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success) { success = false; MessageQueueResult messageQueueResult = new MessageQueueResult(); + List simpleQueueMessages = new List() { simpleQueueMessage }; try { - Task task = Task.Run(async () => await SendMessageAsync(simpleQueueMessage, messageQueueOptions).ConfigureAwait(false)); - SendMessageResponse response = task.Result; - success = response != null; + Task task = Task.Run(async () => await SendMessageBatchAsync(simpleQueueMessages, messageQueueOptions)); + SendMessageBatchResponse sendMessageBatchResponse = task.Result; + if (sendMessageBatchResponse != null) + success = (sendMessageBatchResponse.Failed.Count == 0); - if (success) + foreach (BatchResultErrorEntry entry in sendMessageBatchResponse.Failed) { - messageQueueResult = SetupMessageQueueResult(response); + messageQueueResult = SetupMessageQueueResult(entry); + } + + foreach (SendMessageBatchResultEntry entry in sendMessageBatchResponse.Successful) + { + messageQueueResult = SetupMessageQueueResult(entry); } } - catch (Exception ex) + catch (AggregateException ae) { - throw ex; + throw ae; } return messageQueueResult; } @@ -285,6 +282,27 @@ public IList SendMessages(IList simpleQu } return messageQueueResults; } + + public override string GetName() + { + return Name; + } + + public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) + { + try + { + AmazonSQSException sqs_ex = (AmazonSQSException)ex; + msg.gxTpr_Id = sqs_ex.ErrorCode; + msg.gxTpr_Description = sqs_ex.Message; + return true; + } + catch (Exception) + { + return false; + } + } + private MessageQueueResult SetupMessageQueueResult(SendMessageResponse response) { MessageQueueResult messageQueueResult = new MessageQueueResult(); @@ -314,11 +332,10 @@ private MessageQueueResult SetupMessageQueueResult(SendMessageResponse response) } return messageQueueResult; } - private MessageQueueResult SetupMessageQueueResult(SendMessageBatchResultEntry response) { MessageQueueResult messageQueueResult = new MessageQueueResult(); - messageQueueResult.MessageId = response.MessageId; + messageQueueResult.MessageId = response.Id; messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent; messageQueueResult.MessageAttributes = new GXProperties(); @@ -421,9 +438,8 @@ private async Task SendMessageAsync(SimpleQueueMessage simp return sendMessageResponse; } - private async Task SendMessageBatchAsync(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions) + private async Task SendMessageBatchAsync(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions=null) { - List messageBatchRequestEntries = new List(); SendMessageBatchResponse responseSendBatch = new SendMessageBatchResponse(); @@ -445,7 +461,7 @@ private async Task SendMessageBatchAsync(IList GetMessageAsync(MessageQueueOptions m return receiveMessageResponse; } - private async Task DeleteQueueMessageBatchAsync(List messageHandleId, MessageQueueOptions messageQueueOptions) + private async Task DeleteQueueMessageBatchAsync(List messageHandleId) { DeleteMessageBatchResponse deleteMessageBatchResponse = new DeleteMessageBatchResponse(); try diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index 1b81ce080..d54d72924 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -116,15 +116,16 @@ public void Clear(out bool success) /// Permanently removes the first message dequeued. /// - public MessageQueueResult DeleteMessage(out bool success) + public MessageQueueResult DeleteMessage(string messageHandleId, out bool success) { + //This method should receive messageHandleId + popReceipt success=false; MessageQueueResult messageQueueResult = new MessageQueueResult(); if (_queueClient is QueueClient && _queueClient.Exists()) { Azure.Response receivedMessage = _queueClient.ReceiveMessage(); - if ((receivedMessage != null) && (!receivedMessage.GetRawResponse().IsError) && (receivedMessage.Value != null)) + if ((receivedMessage != null) && (!receivedMessage.GetRawResponse().IsError) && (receivedMessage.Value != null) && (receivedMessage.Value.MessageId == messageHandleId)) { Azure.Response deleteResult = _queueClient.DeleteMessage(receivedMessage.Value.MessageId, receivedMessage.Value.PopReceipt); @@ -142,15 +143,13 @@ public MessageQueueResult DeleteMessage(out bool success) /// Deletes permanently the messages given on the list. /// - public IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions,out bool success) + public IList DeleteMessages(List messageHandleId,out bool success) { success = false; IList messageQueueResults = new List(); if (_queueClient is QueueClient && _queueClient.Exists()) { - QueueProperties properties = _queueClient.GetProperties(); - - QueueMessage[] receivedMessages = _queueClient.ReceiveMessages(messageQueueOptions.MaxNumberOfMessages); + QueueMessage[] receivedMessages = _queueClient.ReceiveMessages(); Azure.Response deleteResult; foreach (QueueMessage message in receivedMessages) { @@ -226,8 +225,7 @@ public IList GetMessages(MessageQueueOptions messageQueueOpt } return simpleQueueMessages; } - - public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success) + private MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success) { success = false; Azure.Response sendReceipt; @@ -235,12 +233,17 @@ public MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, Mes if (_queueClient is QueueClient && _queueClient.Exists()) { - sendReceipt = _queueClient.SendMessage(simpleQueueMessage.MessageBody, TimeSpan.FromSeconds(messageQueueOptions.VisibilityTimeout), TimeSpan.FromSeconds(messageQueueOptions.TimetoLive)); + + if (messageQueueOptions.TimetoLive != 0) + sendReceipt = _queueClient.SendMessage(simpleQueueMessage.MessageBody, TimeSpan.FromSeconds(messageQueueOptions.VisibilityTimeout), TimeSpan.FromSeconds(messageQueueOptions.TimetoLive)); + else + sendReceipt = _queueClient.SendMessage(simpleQueueMessage.MessageBody, TimeSpan.FromSeconds(messageQueueOptions.VisibilityTimeout)); + if ((sendReceipt != null) && (sendReceipt.Value != null)) { MessageQueueResult result = new MessageQueueResult() { - MessageId = simpleQueueMessage.MessageId, + MessageId = sendReceipt.Value.MessageId, ServerMessageId = sendReceipt.Value.MessageId, MessageStatus = MessageQueueResultStatus.Sent, MessageAttributes = new GXProperties() @@ -386,6 +389,7 @@ private SimpleQueueMessage AzQueueMessageToSimpleQueueMessage(QueueMessage queue if (queueMessage != null) { simpleQueueMessage.MessageId = queueMessage.MessageId; + simpleQueueMessage.MessageHandleId = queueMessage.PopReceipt; simpleQueueMessage.MessageBody = queueMessage.Body.ToString(); simpleQueueMessage.MessageAttributes = new GXProperties(); diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index f751507f5..90d951738 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -15,10 +15,6 @@ public class MessageQueueProvider : SimpleMessageQueue private static GXService providerService; public MessageQueueProvider() { - /*if (providerService == null) - { - providerService = ServiceFactory.GetGXServices().Get(GXServices.QUEUE_SERVICE); - }*/ } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs index 6112899eb..06aced55b 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs @@ -14,13 +14,11 @@ public interface IQueue int GetQueueLength(out bool success); MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, out bool success); - MessageQueueResult SendMessage(SimpleQueueMessage simpleQueueMessage, MessageQueueOptions messageQueueOptions, out bool success); IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success); IList GetMessages(out bool success); IList GetMessages(MessageQueueOptions messageQueueOptions, out bool success); - MessageQueueResult DeleteMessage(out bool success); - - IList DeleteMessages(List messageHandleId, MessageQueueOptions messageQueueOptions, out bool success); + MessageQueueResult DeleteMessage(string messageHandleId, out bool success); + IList DeleteMessages(List messageHandleId, out bool success); void Clear(out bool success); bool GetMessageFromException(Exception ex, SdtMessages_Message msg); } @@ -66,7 +64,7 @@ public class MessageQueueResult : GxUserType public string ServerMessageId { get; set; } public GXProperties MessageAttributes { get; set; } public string MessageHandleId { get; set; } - public string MessageStatus { get; set; } + public string MessageStatus { get; set; } = "Unknown"; #region Json private static Hashtable mapper; diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index 526eb86f8..9edfd069f 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -25,7 +25,6 @@ public class SimpleMessageQueue public SimpleMessageQueue() { - //queue = ServiceFactory.GetQueue(); } public SimpleMessageQueue(SimpleMessageQueue other) { @@ -72,7 +71,7 @@ public int GetQueueLength(out GXBaseCollection errorMessage return queueLength; } - public GxUserType DeleteMessage(out GXBaseCollection errorMessages, out bool success) + public GxUserType DeleteMessage(string messageHandleId, out GXBaseCollection errorMessages, out bool success) { MessageQueueResult messageQueueResult = new MessageQueueResult(); GxUserType messageResult = new GxUserType(); @@ -80,7 +79,7 @@ public GxUserType DeleteMessage(out GXBaseCollection errorM try { ValidQueue(); - messageQueueResult = queue.DeleteMessage(out success); + messageQueueResult = queue.DeleteMessage(messageHandleId, out success); LoadAssemblyIfRequired(); try { @@ -103,7 +102,7 @@ public GxUserType DeleteMessage(out GXBaseCollection errorM return TransformMessageQueueResult(messageQueueResult); } - public IList DeleteMessages(List messageHandleId, GxUserType messageQueueOptions, out GXBaseCollection errorMessages, out bool success) + public IList DeleteMessages(List messageHandleId, out GXBaseCollection errorMessages, out bool success) { IList messageQueueResults = new List(); errorMessages = new GXBaseCollection(); @@ -111,11 +110,10 @@ public IList DeleteMessages(List messageHandleId, GxUserType success = false; try { - MessageQueueOptions options = TransformOptions(messageQueueOptions); try { ValidQueue(); - messageQueueResults = queue.DeleteMessages(messageHandleId, options, out success); + messageQueueResults = queue.DeleteMessages(messageHandleId, out success); LoadAssemblyIfRequired(); foreach (MessageQueueResult messageResult in messageQueueResults) { @@ -437,7 +435,7 @@ protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection Messa else return false; } - public T GetPropertyValue(string propertyName) { return (T)GetType().GetProperty($"gxTpr_{propertyName}").GetValue(this); } - public void SetPropertyValue(string propertyName, object propertyValue) { GetType().GetProperty($"gxTpr_{propertyName}").SetValue(this, propertyValue); diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs index 7099c4c4c..9f6d8e0cd 100644 --- a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs +++ b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs @@ -87,7 +87,7 @@ public void TestSendMessageOptionsMethod() options.TimetoLive = 3600; bool success = false; - MessageQueueResult messageQueueResult = queue.SendMessage(simpleQueueMessage, options, out success); + MessageQueueResult messageQueueResult = queue.SendMessage(simpleQueueMessage, out success); Assert.True(success); Assert.Equal(simpleQueueMessage.MessageId, messageQueueResult.MessageId); @@ -151,14 +151,13 @@ public void TestSendMessagesOptionsMethod() } - public void TestDeleteMessagesOptionsMethod() + public void TestDeleteMessagesMethod() { bool success = false; IList messageQueueResults = new List(); List messageHandleId = new List() { "TestMsgIdNotExists", "TestMsgId3" }; - MessageQueueOptions options = new MessageQueueOptions(); - options.MaxNumberOfMessages = 10; - messageQueueResults = queue.DeleteMessages(messageHandleId, options, out success); + + messageQueueResults = queue.DeleteMessages(messageHandleId, out success); Assert.True(success); Assert.True(messageQueueResults.Count == 1); @@ -166,12 +165,13 @@ public void TestDeleteMessagesOptionsMethod() } - public void TestDeleteMessageMethod() + /* public void TestDeleteMessageMethod() { bool success = false; MessageQueueResult messageQueueResult = queue.DeleteMessage(out success); Assert.True(success); } + */ [SkippableFact] public void TestGetQueueLength() From a8a07acff31b7d6cb10240812bf4e5472a379dec Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Thu, 23 Jun 2022 15:58:29 -0300 Subject: [PATCH 12/14] Minor fix: replace hard coded "" by string.Empty. --- .../dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs index d022cee19..443f5223e 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs @@ -43,7 +43,7 @@ public string GetEncryptedPropertyValue(string propertyName, string alternativeP { try { - string ret = ""; + string ret = String.Empty; if (CryptoImpl.Decrypt(ref ret, value)) { value = ret; From 02f046b33a1aace5ee3ba1c4823368879f1b2ef0 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Thu, 30 Jun 2022 12:33:25 -0300 Subject: [PATCH 13/14] Change in DeleteMessage signature --- .../Messaging/GXAmazonSQS/AWSQueue.cs | 30 +++----- .../Messaging/GXAzureQueue/AzureQueue.cs | 75 +++++++++---------- .../Providers/Messaging/GXQueue/Queue.cs | 3 +- .../Messaging/GXQueue/SimpleMessageQueue.cs | 42 +++-------- .../DotNetCoreUnitTest/Queue/QueueTest.cs | 29 ++----- 5 files changed, 61 insertions(+), 118 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index 894250a97..3ff9239a5 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -81,32 +81,22 @@ public void Clear(out bool success) } } - public MessageQueueResult DeleteMessage(string messageHandleId, out bool success) + public IList DeleteMessages(IList simpleQueueMessages, out bool success) { - success= false; - MessageQueueResult messageQueueResult = new MessageQueueResult(); - - List messageHandleIdToDelete = new List{ messageHandleId }; - IList messageQueueResults = RemoveMessages(messageHandleIdToDelete, out bool operationOK); - if ((operationOK) && (messageQueueResults != null)) - { - messageQueueResult = messageQueueResults[0]; - success= true; - } - return messageQueueResult; + return RemoveMessages(simpleQueueMessages, out success); } - - public IList DeleteMessages(List messageHandleId, out bool success) - { - return RemoveMessages(messageHandleId, out success); - } - private IList RemoveMessages(List messageHandleId, out bool success) + private IList RemoveMessages(IList simpleQueueMessages, out bool success) { IList messageQueueResults = new List(); + List messageHandleIds = new List(); success = false; try { - Task task = Task.Run(async () => await DeleteQueueMessageBatchAsync(messageHandleId)); + foreach (SimpleQueueMessage simpleQueueMessage in simpleQueueMessages) + { + messageHandleIds.Add(simpleQueueMessage.MessageHandleId); + } + Task task = Task.Run(async () => await DeleteQueueMessageBatchAsync(messageHandleIds)); DeleteMessageBatchResponse deleteMessageBatchResponse = task.Result; if (deleteMessageBatchResponse != null) @@ -123,7 +113,7 @@ private IList RemoveMessages(List messageHandleId, o MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); messageQueueResults.Add(messageQueueResult); } - + } catch (AggregateException ae) { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index d54d72924..8576ff00d 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -112,55 +112,35 @@ public void Clear(out bool success) } } - /// - /// Permanently removes the first message dequeued. - /// - - public MessageQueueResult DeleteMessage(string messageHandleId, out bool success) - { - //This method should receive messageHandleId + popReceipt - success=false; - MessageQueueResult messageQueueResult = new MessageQueueResult(); - if (_queueClient is QueueClient && _queueClient.Exists()) - { - Azure.Response receivedMessage = _queueClient.ReceiveMessage(); - - if ((receivedMessage != null) && (!receivedMessage.GetRawResponse().IsError) && (receivedMessage.Value != null) && (receivedMessage.Value.MessageId == messageHandleId)) - { - Azure.Response deleteResult = _queueClient.DeleteMessage(receivedMessage.Value.MessageId, receivedMessage.Value.PopReceipt); - - success = !deleteResult.IsError; - if (success) - { - return (AzQueueMessageToMessageQueueResult(receivedMessage.Value, MessageQueueResultStatus.Deleted)); - } - } - } - return messageQueueResult; - } - /// /// Deletes permanently the messages given on the list. /// - public IList DeleteMessages(List messageHandleId,out bool success) + public IList DeleteMessages(IList simpleQueueMessages, out bool success) { success = false; IList messageQueueResults = new List(); if (_queueClient is QueueClient && _queueClient.Exists()) { - QueueMessage[] receivedMessages = _queueClient.ReceiveMessages(); Azure.Response deleteResult; - foreach (QueueMessage message in receivedMessages) + foreach (SimpleQueueMessage simpleQueueMessage in simpleQueueMessages) { - if (messageHandleId.Contains(message.MessageId) ) - { - deleteResult = _queueClient.DeleteMessage(message?.MessageId, message?.PopReceipt); - if ((deleteResult != null) && (!deleteResult.IsError) && message is QueueMessage) - messageQueueResults.Add(AzQueueMessageToMessageQueueResult(queueMessage: message, status: MessageQueueResultStatus.Deleted)); + deleteResult = _queueClient.DeleteMessage(simpleQueueMessage?.MessageId, simpleQueueMessage?.MessageHandleId); + + if (deleteResult != null) + { + if (!deleteResult.IsError) + { + messageQueueResults.Add(SimpleQueueMessageToMessageQueueResult(simpleQueueMessage, MessageQueueResultStatus.Deleted)); + success = true; + } + else + { + messageQueueResults.Add(SimpleQueueMessageToMessageQueueResult(simpleQueueMessage, MessageQueueResultStatus.Failed)); + success = false; + } } - } - success = true; + } } return messageQueueResults; } @@ -330,7 +310,23 @@ public IList SendMessages(IList simpleQu success = !sendError; return messageQueueResults; } + public override string GetName() + { + return Name; + } + + #region Transform Methods + private MessageQueueResult SimpleQueueMessageToMessageQueueResult(SimpleQueueMessage simpleQueueMessage, string messageStatus) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + messageQueueResult.MessageId = simpleQueueMessage.MessageId; + messageQueueResult.MessageStatus = messageStatus; + messageQueueResult.ServerMessageId = simpleQueueMessage.MessageId; + messageQueueResult.MessageHandleId = simpleQueueMessage.MessageHandleId; + return messageQueueResult; + + } private MessageQueueResult AzQueueMessageToMessageQueueResult(QueueMessage queueMessage, string status) { MessageQueueResult messageQueueResult = new MessageQueueResult(); @@ -408,10 +404,7 @@ private SimpleQueueMessage AzQueueMessageToSimpleQueueMessage(QueueMessage queue } return simpleQueueMessage; } - public override string GetName() - { - return Name; - } + #endregion } } \ No newline at end of file diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs index 06aced55b..24b6ae8aa 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs @@ -17,8 +17,7 @@ public interface IQueue IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success); IList GetMessages(out bool success); IList GetMessages(MessageQueueOptions messageQueueOptions, out bool success); - MessageQueueResult DeleteMessage(string messageHandleId, out bool success); - IList DeleteMessages(List messageHandleId, out bool success); + IList DeleteMessages(IList simpleQueueMessages, out bool success); void Clear(out bool success); bool GetMessageFromException(Exception ex, SdtMessages_Message msg); } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index 9edfd069f..4655645d3 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -71,49 +71,25 @@ public int GetQueueLength(out GXBaseCollection errorMessage return queueLength; } - public GxUserType DeleteMessage(string messageHandleId, out GXBaseCollection errorMessages, out bool success) - { - MessageQueueResult messageQueueResult = new MessageQueueResult(); - GxUserType messageResult = new GxUserType(); - errorMessages = new GXBaseCollection(); - try - { - ValidQueue(); - messageQueueResult = queue.DeleteMessage(messageHandleId, out success); - LoadAssemblyIfRequired(); - try - { - if (messageQueueResult != null && TransformMessageQueueResult(messageQueueResult) is GxUserType result) - return result; - } - catch (Exception ex) - { - GXLogging.Error(logger, ex); - success = false; - throw ex; - } - } - catch (Exception ex) - { - QueueErrorMessagesSetup(ex, out errorMessages); - GXLogging.Error(logger, ex); - success = false; - } - return TransformMessageQueueResult(messageQueueResult); - } - - public IList DeleteMessages(List messageHandleId, out GXBaseCollection errorMessages, out bool success) + public IList DeleteMessages(IList simpleQueueMessages, out GXBaseCollection errorMessages, out bool success) { IList messageQueueResults = new List(); errorMessages = new GXBaseCollection(); IList messageResults = new List(); success = false; + + IList simpleQueueMessagesList = new List(); + foreach (GxUserType simpleQueueMessage in simpleQueueMessages) + { + if (TransformGXUserTypeToSimpleQueueMessage(simpleQueueMessage) is SimpleQueueMessage queueMessage) + simpleQueueMessagesList.Add(queueMessage); + } try { try { ValidQueue(); - messageQueueResults = queue.DeleteMessages(messageHandleId, out success); + messageQueueResults = queue.DeleteMessages(simpleQueueMessagesList, out success); LoadAssemblyIfRequired(); foreach (MessageQueueResult messageResult in messageQueueResults) { diff --git a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs index 9f6d8e0cd..04af1e6ab 100644 --- a/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs +++ b/dotnet/test/DotNetCoreUnitTest/Queue/QueueTest.cs @@ -1,12 +1,6 @@ using System; using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Net; -using DotNetUnitTest; using GeneXus.Messaging.Common; -using GeneXus.Services; -using GeneXus.Storage; using Xunit; @@ -32,7 +26,6 @@ public QueueTest(string queueName, Type queueType) Environment.SetEnvironmentVariable("QUEUE_AZUREQUEUE_CONNECTIONSTRING", ""); queue = (IQueue)Activator.CreateInstance(queueType); - Assert.NotNull(queue); } } @@ -149,36 +142,28 @@ public void TestSendMessagesOptionsMethod() Assert.Equal("TestMsgId4", simpleQueueMessages[1].MessageId); } - - public void TestDeleteMessagesMethod() { bool success = false; + IList simpleQueueMessages = new List(); + + SimpleQueueMessage simpleQueueMessage = new SimpleQueueMessage(); + simpleQueueMessage.MessageId = "TestMsgId3"; + simpleQueueMessage.MessageBody = "This is the message body 3"; + simpleQueueMessages.Add(simpleQueueMessage); IList messageQueueResults = new List(); - List messageHandleId = new List() { "TestMsgIdNotExists", "TestMsgId3" }; - - messageQueueResults = queue.DeleteMessages(messageHandleId, out success); + messageQueueResults = queue.DeleteMessages(simpleQueueMessages, out success); Assert.True(success); Assert.True(messageQueueResults.Count == 1); - } - - /* public void TestDeleteMessageMethod() - { - bool success = false; - MessageQueueResult messageQueueResult = queue.DeleteMessage(out success); - Assert.True(success); - } - */ [SkippableFact] public void TestGetQueueLength() { bool success = false; int length = queue.GetQueueLength(out success); - Assert.True(success); Assert.Equal(0, length); From fc8a76aff6d63eacdd20a13509568bc9d42cc399 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Thu, 30 Jun 2022 13:57:15 -0300 Subject: [PATCH 14/14] Preseve the old methods while the java implementation is not ready --- .../Messaging/GXAmazonSQS/AWSQueue.cs | 50 ++++++++++++++ .../Messaging/GXAzureQueue/AzureQueue.cs | 51 +++++++++++++- .../Providers/Messaging/GXQueue/Queue.cs | 2 + .../Messaging/GXQueue/SimpleMessageQueue.cs | 68 +++++++++++++++++++ 4 files changed, 170 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index 3ff9239a5..5fd3829c3 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -81,6 +81,56 @@ public void Clear(out bool success) } } + public MessageQueueResult DeleteMessage(string messageHandleId, out bool success) + { + success = false; + MessageQueueResult messageQueueResult = new MessageQueueResult(); + + List messageHandleIdToDelete = new List { messageHandleId }; + IList messageQueueResults = RemoveMessages(messageHandleIdToDelete, out bool operationOK); + if ((operationOK) && (messageQueueResults != null)) + { + messageQueueResult = messageQueueResults[0]; + success = true; + } + return messageQueueResult; + } + + public IList DeleteMessages(List messageHandleId, out bool success) + { + return RemoveMessages(messageHandleId, out success); + } + private IList RemoveMessages(List messageHandleId, out bool success) + { + IList messageQueueResults = new List(); + success = false; + try + { + Task task = Task.Run(async () => await DeleteQueueMessageBatchAsync(messageHandleId)); + + DeleteMessageBatchResponse deleteMessageBatchResponse = task.Result; + if (deleteMessageBatchResponse != null) + success = (deleteMessageBatchResponse.Failed.Count == 0); + + foreach (BatchResultErrorEntry entry in deleteMessageBatchResponse.Failed) + { + MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); + messageQueueResults.Add(messageQueueResult); + } + + foreach (DeleteMessageBatchResultEntry entry in deleteMessageBatchResponse.Successful) + { + MessageQueueResult messageQueueResult = SetupMessageQueueResult(entry); + messageQueueResults.Add(messageQueueResult); + } + + } + catch (AggregateException ae) + { + throw ae; + } + return messageQueueResults; + } public IList DeleteMessages(IList simpleQueueMessages, out bool success) { return RemoveMessages(simpleQueueMessages, out success); diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index 8576ff00d..e18c42e7d 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -112,10 +112,59 @@ public void Clear(out bool success) } } + public MessageQueueResult DeleteMessage(string messageHandleId, out bool success) + { + //This method should receive messageHandleId + popReceipt + success = false; + MessageQueueResult messageQueueResult = new MessageQueueResult(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + Azure.Response receivedMessage = _queueClient.ReceiveMessage(); + + if ((receivedMessage != null) && (!receivedMessage.GetRawResponse().IsError) && (receivedMessage.Value != null) && (receivedMessage.Value.MessageId == messageHandleId)) + { + Azure.Response deleteResult = _queueClient.DeleteMessage(receivedMessage.Value.MessageId, receivedMessage.Value.PopReceipt); + + success = !deleteResult.IsError; + if (success) + { + return (AzQueueMessageToMessageQueueResult(receivedMessage.Value, MessageQueueResultStatus.Deleted)); + } + } + } + return messageQueueResult; + } + /// /// Deletes permanently the messages given on the list. /// - + + public IList DeleteMessages(List messageHandleId, out bool success) + { + success = false; + IList messageQueueResults = new List(); + if (_queueClient is QueueClient && _queueClient.Exists()) + { + QueueMessage[] receivedMessages = _queueClient.ReceiveMessages(); + Azure.Response deleteResult; + foreach (QueueMessage message in receivedMessages) + { + if (messageHandleId.Contains(message.MessageId)) + { + deleteResult = _queueClient.DeleteMessage(message?.MessageId, message?.PopReceipt); + if ((deleteResult != null) && (!deleteResult.IsError) && message is QueueMessage) + messageQueueResults.Add(AzQueueMessageToMessageQueueResult(queueMessage: message, status: MessageQueueResultStatus.Deleted)); + } + } + success = true; + } + return messageQueueResults; + } + + /// + /// Deletes permanently the messages given on the list. + /// + public IList DeleteMessages(IList simpleQueueMessages, out bool success) { success = false; diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs index 24b6ae8aa..c63399590 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/Queue.cs @@ -17,6 +17,8 @@ public interface IQueue IList SendMessages(IList simpleQueueMessages, MessageQueueOptions messageQueueOptions, out bool success); IList GetMessages(out bool success); IList GetMessages(MessageQueueOptions messageQueueOptions, out bool success); + MessageQueueResult DeleteMessage(string messageHandleId, out bool success); + IList DeleteMessages(List messageHandleId, out bool success); IList DeleteMessages(IList simpleQueueMessages, out bool success); void Clear(out bool success); bool GetMessageFromException(Exception ex, SdtMessages_Message msg); diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index 4655645d3..c432357c0 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -71,6 +71,74 @@ public int GetQueueLength(out GXBaseCollection errorMessage return queueLength; } + public GxUserType DeleteMessage(string messageHandleId, out GXBaseCollection errorMessages, out bool success) + { + MessageQueueResult messageQueueResult = new MessageQueueResult(); + GxUserType messageResult = new GxUserType(); + errorMessages = new GXBaseCollection(); + try + { + ValidQueue(); + messageQueueResult = queue.DeleteMessage(messageHandleId, out success); + LoadAssemblyIfRequired(); + try + { + if (messageQueueResult != null && TransformMessageQueueResult(messageQueueResult) is GxUserType result) + return result; + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + success = false; + throw ex; + } + } + catch (Exception ex) + { + QueueErrorMessagesSetup(ex, out errorMessages); + GXLogging.Error(logger, ex); + success = false; + } + return TransformMessageQueueResult(messageQueueResult); + } + + public IList DeleteMessages(List messageHandleId, out GXBaseCollection errorMessages, out bool success) + { + IList messageQueueResults = new List(); + errorMessages = new GXBaseCollection(); + IList messageResults = new List(); + success = false; + try + { + try + { + ValidQueue(); + messageQueueResults = queue.DeleteMessages(messageHandleId, out success); + LoadAssemblyIfRequired(); + foreach (MessageQueueResult messageResult in messageQueueResults) + { + if (TransformMessageQueueResult(messageResult) is GxUserType result) + messageResults.Add(result); + } + success = true; + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + QueueErrorMessagesSetup(ex, out errorMessages); + success = false; + } + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + success = false; + throw ex; + } + + return messageResults; + } + public IList DeleteMessages(IList simpleQueueMessages, out GXBaseCollection errorMessages, out bool success) { IList messageQueueResults = new List();