This is an automated email from the ASF dual-hosted git repository. aaronai pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git
commit bbc8fc987f0488bf29c00dae5cd5553081183154 Author: Aaron Ai <[email protected]> AuthorDate: Wed Mar 15 22:35:42 2023 +0800 Make it compatible with .NET standard 2.1 --- csharp/examples/ProducerBenchmark.cs | 8 ++- csharp/examples/ProducerDelayMessageExample.cs | 2 +- csharp/examples/ProducerFifoMessageExample.cs | 2 +- csharp/examples/ProducerNormalMessageExample.cs | 2 +- .../examples/ProducerTransactionMessageExample.cs | 2 +- csharp/examples/SimpleConsumerExample.cs | 2 +- csharp/examples/examples.csproj | 2 +- csharp/rocketmq-client-csharp/Client.cs | 10 ++- .../ConfigFileCredentialsProvider.cs | 83 ---------------------- csharp/rocketmq-client-csharp/Consumer.cs | 2 +- csharp/rocketmq-client-csharp/Endpoints.cs | 2 +- csharp/rocketmq-client-csharp/Message.cs | 6 +- .../rocketmq-client-csharp/MessageIdGenerator.cs | 2 +- csharp/rocketmq-client-csharp/MessageView.cs | 6 +- csharp/rocketmq-client-csharp/MetadataConstants.cs | 2 +- csharp/rocketmq-client-csharp/MetricConstant.cs | 2 +- csharp/rocketmq-client-csharp/MqLogManager.cs | 10 +-- csharp/rocketmq-client-csharp/Producer.cs | 7 +- .../PublishingLoadBalancer.cs | 2 +- csharp/rocketmq-client-csharp/RpcClient.cs | 21 +++--- csharp/rocketmq-client-csharp/Session.cs | 2 +- csharp/rocketmq-client-csharp/SimpleConsumer.cs | 2 +- .../SubscriptionLoadBalancer.cs | 2 +- csharp/rocketmq-client-csharp/UserAgent.cs | 2 +- csharp/rocketmq-client-csharp/Utilities.cs | 37 +++++++++- .../rocketmq-client-csharp.csproj | 32 ++++----- csharp/tests/ConfigFileCredentialsProviderTest.cs | 59 --------------- csharp/tests/UtilitiesTest.cs | 50 +++++++++++++ 28 files changed, 152 insertions(+), 209 deletions(-) diff --git a/csharp/examples/ProducerBenchmark.cs b/csharp/examples/ProducerBenchmark.cs index 7e2679aa..f7de1c89 100644 --- a/csharp/examples/ProducerBenchmark.cs +++ b/csharp/examples/ProducerBenchmark.cs @@ -29,11 +29,13 @@ namespace examples { private static readonly Logger Logger = MqLogManager.Instance.GetCurrentClassLogger(); - private static readonly SemaphoreSlim Semaphore = new(0); + private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(0); private const int TpsLimit = 300; private static long _successCounter; private static long _failureCounter; - private static readonly BlockingCollection<Task<ISendReceipt>> Tasks = new(); + + private static readonly BlockingCollection<Task<ISendReceipt>> Tasks = + new BlockingCollection<Task<ISendReceipt>>(); private static void DoStats() { @@ -88,7 +90,7 @@ namespace examples const string topic = "yourNormalTopic"; // In most case, you don't need to create too many producers, single pattern is recommended. - await using var producer = await new Producer.Builder() + var producer = await new Producer.Builder() // Set the topic name(s), which is optional but recommended. // It makes producer could prefetch the topic route before message publishing. .SetTopics(topic) diff --git a/csharp/examples/ProducerDelayMessageExample.cs b/csharp/examples/ProducerDelayMessageExample.cs index 84808872..5d905408 100644 --- a/csharp/examples/ProducerDelayMessageExample.cs +++ b/csharp/examples/ProducerDelayMessageExample.cs @@ -43,7 +43,7 @@ namespace examples const string topic = "yourDelayTopic"; // In most case, you don't need to create too many producers, single pattern is recommended. // Producer here will be closed automatically. - await using var producer = await new Producer.Builder() + var producer = await new Producer.Builder() // Set the topic name(s), which is optional but recommended. // It makes producer could prefetch the topic route before message publishing. .SetTopics(topic) diff --git a/csharp/examples/ProducerFifoMessageExample.cs b/csharp/examples/ProducerFifoMessageExample.cs index 6a96fa0a..0ce94ee3 100644 --- a/csharp/examples/ProducerFifoMessageExample.cs +++ b/csharp/examples/ProducerFifoMessageExample.cs @@ -43,7 +43,7 @@ namespace examples const string topic = "yourFifoTopic"; // In most case, you don't need to create too many producers, single pattern is recommended. // Producer here will be closed automatically. - await using var producer = await new Producer.Builder() + var producer = await new Producer.Builder() // Set the topic name(s), which is optional but recommended. // It makes producer could prefetch the topic route before message publishing. .SetTopics(topic) diff --git a/csharp/examples/ProducerNormalMessageExample.cs b/csharp/examples/ProducerNormalMessageExample.cs index b9b85b73..2598c739 100644 --- a/csharp/examples/ProducerNormalMessageExample.cs +++ b/csharp/examples/ProducerNormalMessageExample.cs @@ -42,7 +42,7 @@ namespace examples const string topic = "yourNormalTopic"; // In most case, you don't need to create too many producers, single pattern is recommended. // Producer here will be closed automatically. - await using var producer = await new Producer.Builder() + var producer = await new Producer.Builder() // Set the topic name(s), which is optional but recommended. // It makes producer could prefetch the topic route before message publishing. .SetTopics(topic) diff --git a/csharp/examples/ProducerTransactionMessageExample.cs b/csharp/examples/ProducerTransactionMessageExample.cs index 1b5b7aa4..dff74268 100644 --- a/csharp/examples/ProducerTransactionMessageExample.cs +++ b/csharp/examples/ProducerTransactionMessageExample.cs @@ -51,7 +51,7 @@ namespace examples const string topic = "yourTransactionTopic"; // In most case, you don't need to create too many producers, single pattern is recommended. // Producer here will be closed automatically. - await using var producer = await new Producer.Builder() + var producer = await new Producer.Builder() // Set the topic name(s), which is optional but recommended. // It makes producer could prefetch the topic route before message publishing. .SetTopics(topic) diff --git a/csharp/examples/SimpleConsumerExample.cs b/csharp/examples/SimpleConsumerExample.cs index fd0d9d7a..11dbedb0 100644 --- a/csharp/examples/SimpleConsumerExample.cs +++ b/csharp/examples/SimpleConsumerExample.cs @@ -46,7 +46,7 @@ namespace examples var subscription = new Dictionary<string, FilterExpression> { { topic, new FilterExpression("*") } }; // In most case, you don't need to create too many consumers, single pattern is recommended. - await using var simpleConsumer = await new SimpleConsumer.Builder() + var simpleConsumer = await new SimpleConsumer.Builder() .SetClientConfig(clientConfig) .SetConsumerGroup(consumerGroup) .SetAwaitDuration(TimeSpan.FromSeconds(15)) diff --git a/csharp/examples/examples.csproj b/csharp/examples/examples.csproj index ebdf0af4..37f6a477 100644 --- a/csharp/examples/examples.csproj +++ b/csharp/examples/examples.csproj @@ -5,6 +5,6 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFramework>net5.0</TargetFramework> + <TargetFrameworks>net5.0;netcoreapp3.1</TargetFrameworks> </PropertyGroup> </Project> diff --git a/csharp/rocketmq-client-csharp/Client.cs b/csharp/rocketmq-client-csharp/Client.cs index ec0ea6a7..d619280b 100644 --- a/csharp/rocketmq-client-csharp/Client.cs +++ b/csharp/rocketmq-client-csharp/Client.cs @@ -205,7 +205,7 @@ namespace Org.Apache.Rocketmq try { Logger.Info($"Start to update topic route cache for a new round, clientId={ClientId}"); - Dictionary<string, Task<TopicRouteData>> responses = new(); + Dictionary<string, Task<TopicRouteData>> responses = new Dictionary<string, Task<TopicRouteData>>(); foreach (var topic in GetTopics()) { @@ -255,9 +255,7 @@ namespace Org.Apache.Rocketmq ThreadPool.GetAvailableThreads(out var availableWorker, out var availableIo); Logger.Info( $"ClientId={ClientId}, ClientVersion={MetadataConstants.Instance.ClientVersion}, " + - $".NET Version={Environment.Version}, ThreadCount={ThreadPool.ThreadCount}, " + - $"CompletedWorkItemCount={ThreadPool.CompletedWorkItemCount}, " + - $"PendingWorkItemCount={ThreadPool.PendingWorkItemCount}, AvailableWorkerThreads={availableWorker}, " + + $".NET Version={Environment.Version}, AvailableWorkerThreads={availableWorker}, " + $"AvailableCompletionPortThreads={availableIo}"); } @@ -345,8 +343,8 @@ namespace Org.Apache.Rocketmq { var endpoints = GetTotalRouteEndpoints(); var request = WrapHeartbeatRequest(); - Dictionary<Endpoints, Task<RpcInvocation<Proto.HeartbeatRequest, Proto.HeartbeatResponse>>> - invocations = new(); + var invocations = + new Dictionary<Endpoints, Task<RpcInvocation<Proto.HeartbeatRequest, Proto.HeartbeatResponse>>>(); // Collect task into a map. foreach (var item in endpoints) diff --git a/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs b/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs deleted file mode 100644 index 93b9e9ef..00000000 --- a/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.IO; -using System; -using System.Text.Json; -using System.Collections.Generic; -using NLog; - -namespace Org.Apache.Rocketmq -{ - /** - * File-based credentials provider that reads JSON configurations from ${HOME}/.rocketmq/config - * A sample config content is as follows: - * {"AccessKey": "key", "AccessSecret": "secret"} - */ - public class ConfigFileCredentialsProvider - { - private static readonly Logger Logger = MqLogManager.Instance.GetCurrentClassLogger(); - - public ConfigFileCredentialsProvider() - { - var configFilePath = DefaultConfigFilePath(); - - if (!File.Exists(configFilePath)) - { - Logger.Warn("Config file[{}] does not exist", configFilePath); - return; - } - - try - { - using var reader = new StreamReader(configFilePath); - string json = reader.ReadToEnd(); - var kv = JsonSerializer.Deserialize<Dictionary<string, string>>(json); - if (null == kv) - { - Logger.Error($"Failed to parse JSON configuration: {json}"); - return; - } - - _accessKey = kv["AccessKey"]; - _accessSecret = kv["AccessSecret"]; - _valid = true; - } - catch (IOException e) - { - Logger.Error($"Failed to read cofig file. Cause: {e.Message}"); - } - } - - public SessionCredentials GetCredentials() - { - return !_valid ? null : new SessionCredentials(_accessKey, _accessSecret); - } - - public static string DefaultConfigFilePath() - { - var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - string[] pathSegments = { home, ".rocketmq", "config" }; - return string.Join(Path.DirectorySeparatorChar, pathSegments); - } - - private readonly string _accessKey; - private readonly string _accessSecret; - - private readonly bool _valid; - } -} \ No newline at end of file diff --git a/csharp/rocketmq-client-csharp/Consumer.cs b/csharp/rocketmq-client-csharp/Consumer.cs index 998a3766..0bf7a45a 100644 --- a/csharp/rocketmq-client-csharp/Consumer.cs +++ b/csharp/rocketmq-client-csharp/Consumer.cs @@ -27,7 +27,7 @@ namespace Org.Apache.Rocketmq { public abstract class Consumer : Client { - internal static readonly Regex ConsumerGroupRegex = new("^[%a-zA-Z0-9_-]+$"); + internal static readonly Regex ConsumerGroupRegex = new Regex("^[%a-zA-Z0-9_-]+$"); protected readonly string ConsumerGroup; protected Consumer(ClientConfig clientConfig, string consumerGroup) : base( diff --git a/csharp/rocketmq-client-csharp/Endpoints.cs b/csharp/rocketmq-client-csharp/Endpoints.cs index dbf9bdfb..dc015e2b 100644 --- a/csharp/rocketmq-client-csharp/Endpoints.cs +++ b/csharp/rocketmq-client-csharp/Endpoints.cs @@ -28,7 +28,7 @@ namespace Org.Apache.Rocketmq private const string HttpsPrefix = "https://"; private const int DefaultPort = 80; - private static readonly AddressListEqualityComparer AddressListComparer = new(); + private static readonly AddressListEqualityComparer AddressListComparer = new AddressListEqualityComparer(); private const string EndpointSeparator = ":"; public List<Address> Addresses { get; } private AddressScheme Scheme { get; } diff --git a/csharp/rocketmq-client-csharp/Message.cs b/csharp/rocketmq-client-csharp/Message.cs index b71a4650..bbd2c20e 100644 --- a/csharp/rocketmq-client-csharp/Message.cs +++ b/csharp/rocketmq-client-csharp/Message.cs @@ -24,7 +24,7 @@ namespace Org.Apache.Rocketmq { public class Message { - internal static readonly Regex TopicRegex = new("^[%a-zA-Z0-9_-]+$"); + internal static readonly Regex TopicRegex = new Regex("^[%a-zA-Z0-9_-]+$"); private Message(string topic, byte[] body, string tag, List<string> keys, Dictionary<string, string> properties, DateTime? deliveryTimestamp, string messageGroup) @@ -75,8 +75,8 @@ namespace Org.Apache.Rocketmq private string _topic; private byte[] _body; private string _tag; - private List<string> _keys = new(); - private readonly Dictionary<string, string> _properties = new(); + private List<string> _keys = new List<string>(); + private readonly Dictionary<string, string> _properties = new Dictionary<string, string>(); private DateTime? _deliveryTimestamp; private string _messageGroup; diff --git a/csharp/rocketmq-client-csharp/MessageIdGenerator.cs b/csharp/rocketmq-client-csharp/MessageIdGenerator.cs index 60620ef0..b55b0456 100644 --- a/csharp/rocketmq-client-csharp/MessageIdGenerator.cs +++ b/csharp/rocketmq-client-csharp/MessageIdGenerator.cs @@ -28,7 +28,7 @@ namespace Org.Apache.Rocketmq public class MessageIdGenerator { public const string Version = "01"; - private static readonly MessageIdGenerator Instance = new(); + private static readonly MessageIdGenerator Instance = new MessageIdGenerator(); private readonly string _prefix; diff --git a/csharp/rocketmq-client-csharp/MessageView.cs b/csharp/rocketmq-client-csharp/MessageView.cs index 461f7781..63906344 100644 --- a/csharp/rocketmq-client-csharp/MessageView.cs +++ b/csharp/rocketmq-client-csharp/MessageView.cs @@ -104,7 +104,7 @@ namespace Org.Apache.Rocketmq } case Proto.DigestType.Md5: { - var expectedCheckSum = Convert.ToHexString(MD5.HashData(raw)); + var expectedCheckSum = Utilities.ComputeMd5Hash(raw); if (!expectedCheckSum.Equals(checkSum)) { corrupted = true; @@ -114,7 +114,7 @@ namespace Org.Apache.Rocketmq } case Proto.DigestType.Sha1: { - var expectedCheckSum = Convert.ToHexString(SHA1.HashData(raw)); + var expectedCheckSum = Utilities.ComputeSha1Hash(raw); if (!expectedCheckSum.Equals(checkSum)) { corrupted = true; @@ -158,7 +158,7 @@ namespace Org.Apache.Rocketmq var messageGroup = systemProperties.HasMessageGroup ? systemProperties.MessageGroup : null; DateTime? deliveryTime = null == systemProperties.DeliveryTimestamp ? null - : TimeZoneInfo.ConvertTimeFromUtc(systemProperties.DeliveryTimestamp.ToDateTime(), TimeZoneInfo.Local); + : (DateTime?)TimeZoneInfo.ConvertTimeFromUtc(systemProperties.DeliveryTimestamp.ToDateTime(), TimeZoneInfo.Local); var keys = systemProperties.Keys.ToList(); var bornHost = systemProperties.BornHost; diff --git a/csharp/rocketmq-client-csharp/MetadataConstants.cs b/csharp/rocketmq-client-csharp/MetadataConstants.cs index 07907758..1deddcd2 100644 --- a/csharp/rocketmq-client-csharp/MetadataConstants.cs +++ b/csharp/rocketmq-client-csharp/MetadataConstants.cs @@ -43,7 +43,7 @@ namespace Org.Apache.Rocketmq public string ClientVersion { get; } - public static readonly MetadataConstants Instance = new(); + public static readonly MetadataConstants Instance = new MetadataConstants(); private MetadataConstants() { diff --git a/csharp/rocketmq-client-csharp/MetricConstant.cs b/csharp/rocketmq-client-csharp/MetricConstant.cs index e19288de..bfc64b40 100644 --- a/csharp/rocketmq-client-csharp/MetricConstant.cs +++ b/csharp/rocketmq-client-csharp/MetricConstant.cs @@ -42,7 +42,7 @@ namespace Org.Apache.Rocketmq public readonly ExplicitBucketHistogramConfiguration AwaitTimeBucket; public readonly ExplicitBucketHistogramConfiguration ProcessTimeBucket; - public static readonly MetricConstant Instance = new(); + public static readonly MetricConstant Instance = new MetricConstant(); private MetricConstant() { diff --git a/csharp/rocketmq-client-csharp/MqLogManager.cs b/csharp/rocketmq-client-csharp/MqLogManager.cs index 1e67bb56..1e68ea43 100644 --- a/csharp/rocketmq-client-csharp/MqLogManager.cs +++ b/csharp/rocketmq-client-csharp/MqLogManager.cs @@ -33,19 +33,19 @@ namespace Org.Apache.Rocketmq { public static LogFactory Instance => LazyInstance.Value; - private static readonly Lazy<LogFactory> LazyInstance = new(BuildLogFactory); + private static readonly Lazy<LogFactory> LazyInstance = new Lazy<LogFactory>(BuildLogFactory); - private const string FileLogLevelKey = "rocketmq.log.level"; + private const string FileLogLevelKey = "rocketmq_log_level"; private const string FileLogLevel = "Info"; - private const string ConsoleAppenderEnabledKey = "mq.consoleAppender.enabled"; + private const string ConsoleAppenderEnabledKey = "mq_consoleAppender_enabled"; private const string ConsoleAppenderEnabled = "false"; private const string ConsoleAppenderLogLevel = "Off"; - private const string FileLogRootKey = "rocketmq.log.root"; + private const string FileLogRootKey = "rocketmq_log_root"; - private const string FileMaxIndexKey = "rocketmq.log.file.maxIndex"; + private const string FileMaxIndexKey = "rocketmq_log_file_maxIndex"; private const string FileMaxIndex = "10"; private static LogFactory BuildLogFactory() diff --git a/csharp/rocketmq-client-csharp/Producer.cs b/csharp/rocketmq-client-csharp/Producer.cs index a1f70989..78ee4e34 100644 --- a/csharp/rocketmq-client-csharp/Producer.cs +++ b/csharp/rocketmq-client-csharp/Producer.cs @@ -259,7 +259,7 @@ namespace Org.Apache.Rocketmq throw; } - if (exception is not TooManyRequestsException) + if (!(exception is TooManyRequestsException)) { // Retry immediately if the request is not throttled. Logger.Warn(e, $"Failed to send message, topic={message.Topic}, maxAttempts={maxAttempts}, " + @@ -349,7 +349,10 @@ namespace Org.Apache.Rocketmq public class Builder { private ClientConfig _clientConfig; - private readonly ConcurrentDictionary<string, bool> _publishingTopics = new(); + + private readonly ConcurrentDictionary<string, bool> _publishingTopics = + new ConcurrentDictionary<string, bool>(); + private int _maxAttempts = 3; private ITransactionChecker _checker; diff --git a/csharp/rocketmq-client-csharp/PublishingLoadBalancer.cs b/csharp/rocketmq-client-csharp/PublishingLoadBalancer.cs index b0cc0d2b..84285999 100644 --- a/csharp/rocketmq-client-csharp/PublishingLoadBalancer.cs +++ b/csharp/rocketmq-client-csharp/PublishingLoadBalancer.cs @@ -24,7 +24,7 @@ namespace Org.Apache.Rocketmq { public class PublishingLoadBalancer { - private static readonly Random Random = new(); + private static readonly Random Random = new Random(); private readonly List<MessageQueue> _messageQueues; private int _index; diff --git a/csharp/rocketmq-client-csharp/RpcClient.cs b/csharp/rocketmq-client-csharp/RpcClient.cs index abf70563..b8a02430 100644 --- a/csharp/rocketmq-client-csharp/RpcClient.cs +++ b/csharp/rocketmq-client-csharp/RpcClient.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Security; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Proto = Apache.Rocketmq.V2; @@ -55,23 +56,23 @@ namespace Org.Apache.Rocketmq } } + private static bool CertValidator( + object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + // Always return true to disable server certificate validation + return true; + } + /** * See https://docs.microsoft.com/en-us/aspnet/core/grpc/performance?view=aspnetcore-6.0 for performance consideration and * why parameters are configured this way. */ internal static HttpMessageHandler CreateHttpHandler() { - var sslOptions = new SslClientAuthenticationOptions - { - // Comment out the following line if server certificate validation is required. - // Disable server certificate validation during development phase. - RemoteCertificateValidationCallback = (_, _, _, _) => true - }; - var handler = new SocketsHttpHandler + // TODO + var handler = new HttpClientHandler { - PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan, - EnableMultipleHttp2Connections = true, - SslOptions = sslOptions, + ServerCertificateCustomValidationCallback = CertValidator, }; return handler; } diff --git a/csharp/rocketmq-client-csharp/Session.cs b/csharp/rocketmq-client-csharp/Session.cs index 69a2c197..f41694ec 100644 --- a/csharp/rocketmq-client-csharp/Session.cs +++ b/csharp/rocketmq-client-csharp/Session.cs @@ -31,7 +31,7 @@ namespace Org.Apache.Rocketmq private static readonly Logger Logger = MqLogManager.Instance.GetCurrentClassLogger(); private static readonly TimeSpan SettingsInitializationTimeout = TimeSpan.FromSeconds(3); - private readonly ManualResetEventSlim _event = new(false); + private readonly ManualResetEventSlim _event = new ManualResetEventSlim(false); private readonly AsyncDuplexStreamingCall<Proto::TelemetryCommand, Proto::TelemetryCommand> _streamingCall; diff --git a/csharp/rocketmq-client-csharp/SimpleConsumer.cs b/csharp/rocketmq-client-csharp/SimpleConsumer.cs index 2146e643..da372177 100644 --- a/csharp/rocketmq-client-csharp/SimpleConsumer.cs +++ b/csharp/rocketmq-client-csharp/SimpleConsumer.cs @@ -110,7 +110,7 @@ namespace Org.Apache.Rocketmq State = State.Stopping; Logger.Info($"Begin to shutdown the rocketmq simple consumer, clientId={ClientId}"); await base.Shutdown(); - Logger.Info($"The rocketmq simple consumer starts successfully, clientId={ClientId}"); + Logger.Info($"Shutdown the rocketmq simple consumer successfully, clientId={ClientId}"); State = State.Terminated; } catch (Exception) diff --git a/csharp/rocketmq-client-csharp/SubscriptionLoadBalancer.cs b/csharp/rocketmq-client-csharp/SubscriptionLoadBalancer.cs index e2575a4b..a5a88a6b 100644 --- a/csharp/rocketmq-client-csharp/SubscriptionLoadBalancer.cs +++ b/csharp/rocketmq-client-csharp/SubscriptionLoadBalancer.cs @@ -24,7 +24,7 @@ namespace Org.Apache.Rocketmq { internal sealed class SubscriptionLoadBalancer { - private static readonly Random Random = new(); + private static readonly Random Random = new Random(); private readonly List<MessageQueue> _messageQueues; private int _index; diff --git a/csharp/rocketmq-client-csharp/UserAgent.cs b/csharp/rocketmq-client-csharp/UserAgent.cs index b457b608..9b5a1157 100644 --- a/csharp/rocketmq-client-csharp/UserAgent.cs +++ b/csharp/rocketmq-client-csharp/UserAgent.cs @@ -26,7 +26,7 @@ namespace Org.Apache.Rocketmq private readonly string _platform; private readonly string _hostName; - public static readonly UserAgent Instance = new(); + public static readonly UserAgent Instance = new UserAgent(); private UserAgent() { diff --git a/csharp/rocketmq-client-csharp/Utilities.cs b/csharp/rocketmq-client-csharp/Utilities.cs index d032ae1e..5505a277 100644 --- a/csharp/rocketmq-client-csharp/Utilities.cs +++ b/csharp/rocketmq-client-csharp/Utilities.cs @@ -19,8 +19,10 @@ using System.Linq; using System.Net.NetworkInformation; using System.Text; using System; +using System.Diagnostics; using System.IO; using System.IO.Compression; +using System.Security.Cryptography; using System.Threading; namespace Org.Apache.Rocketmq @@ -45,7 +47,7 @@ namespace Org.Apache.Rocketmq public static int GetProcessId() { - return Environment.ProcessId; + return Process.GetCurrentProcess().Id; } public static string GetHostName() @@ -56,13 +58,31 @@ namespace Org.Apache.Rocketmq public static string GetClientId() { var hostName = System.Net.Dns.GetHostName(); - var pid = Environment.ProcessId; + var pid = Process.GetCurrentProcess().Id; var index = Interlocked.Increment(ref _instanceSequence); var nowMillisecond = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds; var no = DecimalToBase36(nowMillisecond); return $"{hostName}@{pid}@{index}@{no}"; } + public static string ComputeMd5Hash(byte[] data) + { + using (var md5 = MD5.Create()) + { + var hashBytes = md5.ComputeHash(data); + return BitConverter.ToString(hashBytes).Replace("-", ""); + } + } + + public static string ComputeSha1Hash(byte[] data) + { + using (var sha1 = SHA1.Create()) + { + var hashBytes = sha1.ComputeHash(data); + return BitConverter.ToString(hashBytes).Replace("-", ""); + } + } + private static string DecimalToBase36(long decimalNumber) { @@ -92,6 +112,19 @@ namespace Org.Apache.Rocketmq return result.ToString(); } + public static byte[] CompressBytesGzip(byte[] src, CompressionLevel level) + { + using (var ms = new MemoryStream()) + { + using (var gzip = new GZipStream(ms, level)) + { + gzip.Write(src, 0, src.Length); + } + + return ms.ToArray(); + } + } + public static byte[] DecompressBytesGzip(byte[] src) { var inputStream = new MemoryStream(src); diff --git a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj index bff3801b..83b0d293 100644 --- a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj +++ b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj @@ -1,12 +1,12 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <PackageId>RocketMQ.Client</PackageId> - <PackageVersion>0.0.11-SNAPSHOT</PackageVersion> + <PackageVersion>0.0.14-SNAPSHOT</PackageVersion> <Version>$(PackageVersion)</Version> <Authors>RocketMQ Authors</Authors> <Company>Apache Software Foundation</Company> - <TargetFramework>net5.0</TargetFramework> + <TargetFrameworks>net5.0;netstandard21</TargetFrameworks> <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression> <RootNamespace>Org.Apache.Rocketmq</RootNamespace> <PackageReadmeFile>README.md</PackageReadmeFile> @@ -18,30 +18,28 @@ </PropertyGroup> <ItemGroup> - <None Include="..\README.md" Pack="true" PackagePath="\"/> - <PackageReference Include="Crc32.NET" Version="1.2.0"/> - <PackageReference Include="Google.Protobuf" Version="3.19.4"/> - <PackageReference Include="Grpc.Net.Client" Version="2.43.0"/> + <None Include="..\README.md" Pack="true" PackagePath="\" /> + <PackageReference Include="Crc32.NET" Version="1.2.0" /> + <PackageReference Include="Google.Protobuf" Version="3.19.4" /> + <PackageReference Include="Grpc.Net.Client" Version="2.43.0" /> <PackageReference Include="Grpc.Tools" Version="2.43.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> - <PackageReference Include="NLog" Version="4.7.13"/> - <PackageReference Include="OpenTelemetry" Version="1.3.1"/> - <PackageReference Include="OpenTelemetry.Api" Version="1.3.1"/> - <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.3.1"/> + <PackageReference Include="NLog" Version="4.7.13" /> + <PackageReference Include="OpenTelemetry" Version="1.3.1" /> + <PackageReference Include="OpenTelemetry.Api" Version="1.3.1" /> + <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.3.1" /> - <Protobuf Include="Protos\apache\rocketmq\v2\definition.proto" ProtoRoot="Protos" GrpcServices="Client"/> - <Protobuf Include="Protos\google\rpc\code.proto" ProtoRoot="Protos" GrpcServices="Client"/> - <Protobuf Include="Protos\google\rpc\error_details.proto" ProtoRoot="Protos" GrpcServices="Client"/> - <Protobuf Include="Protos\google\rpc\status.proto" ProtoRoot="Protos" GrpcServices="Client"/> + <Protobuf Include="Protos\apache\rocketmq\v2\definition.proto" ProtoRoot="Protos" GrpcServices="Client" /> + <Protobuf Include="Protos\google\rpc\code.proto" ProtoRoot="Protos" GrpcServices="Client" /> + <Protobuf Include="Protos\google\rpc\error_details.proto" ProtoRoot="Protos" GrpcServices="Client" /> + <Protobuf Include="Protos\google\rpc\status.proto" ProtoRoot="Protos" GrpcServices="Client" /> <Protobuf Include="Protos\apache\rocketmq\v2\service.proto" ProtoRoot="Protos" GrpcServices="Client"> <Link>Protos\apache\rocketmq\v2\definition.proto</Link> <Link>Protos\google\rpc\status.proto</Link> <Link>Protos\google\rpc\error_details.proto</Link> </Protobuf> - <None Update="logo.png" PackagePath=""> - <Pack>True</Pack> - </None> + <None Include="logo.png" Pack="true" PackagePath=""/> </ItemGroup> </Project> diff --git a/csharp/tests/ConfigFileCredentialsProviderTest.cs b/csharp/tests/ConfigFileCredentialsProviderTest.cs deleted file mode 100644 index d65439be..00000000 --- a/csharp/tests/ConfigFileCredentialsProviderTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.IO; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Org.Apache.Rocketmq; - -namespace tests -{ - [TestClass] - public class ConfigFileCredentialsProviderTest - { - [TestInitialize] - public void Setup() - { - var configFilePath = ConfigFileCredentialsProvider.DefaultConfigFilePath(); - var fileInfo = new FileInfo(configFilePath); - var dir = fileInfo.Directory; - if (dir != null && !dir.Exists) - { - dir.Create(); - } - - var json = "{\"AccessKey\": \"key\", \"AccessSecret\": \"secret\"}"; - File.WriteAllText(configFilePath, json); - } - - [TestMethod] - public void TestGetCredentials() - { - var provider = new ConfigFileCredentialsProvider(); - var credentials = provider.GetCredentials(); - Assert.IsNotNull(credentials); - Assert.AreEqual(credentials.AccessKey, "key"); - Assert.AreEqual(credentials.AccessSecret, "secret"); - } - - [TestCleanup] - public void TearDown() - { - var configFilePath = ConfigFileCredentialsProvider.DefaultConfigFilePath(); - File.Delete(configFilePath); - } - } -} \ No newline at end of file diff --git a/csharp/tests/UtilitiesTest.cs b/csharp/tests/UtilitiesTest.cs new file mode 100644 index 00000000..5c82fcaa --- /dev/null +++ b/csharp/tests/UtilitiesTest.cs @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.IO.Compression; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Org.Apache.Rocketmq; + +namespace tests +{ + [TestClass] + public class UtilitiesTest + { + [TestMethod] + public void TestDecompressBytesGzip() + { + var originalData = new byte[] { 1, 2, 3, 4, 5 }; + var compressedData = Utilities.CompressBytesGzip(originalData, CompressionLevel.Fastest); + CollectionAssert.AreEqual(Utilities.DecompressBytesGzip(compressedData), originalData); + } + + [TestMethod] + public void TestComputeMd5Hash() + { + var bytes = Encoding.UTF8.GetBytes("foobar"); + Assert.AreEqual(Utilities.ComputeMd5Hash(bytes), "3858F62230AC3C915F300C664312C63F"); + } + + [TestMethod] + public void TestComputeSha1Hash() + { + var bytes = Encoding.UTF8.GetBytes("foobar"); + Assert.AreEqual(Utilities.ComputeSha1Hash(bytes), "8843D7F92416211DE9EBB963FF4CE28125932878"); + } + } +} \ No newline at end of file
