You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by aa...@apache.org on 2023/03/16 07:35:20 UTC
[rocketmq-clients] 01/05: Make it compatible with .NET standard 2.1
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 <ya...@gmail.com>
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