### Hello World: Produce and Consume Messages Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/api/index.md This example demonstrates a basic 'Hello World' scenario using DotPulsar. It produces a message to a topic and then consumes it. The topic and subscription are automatically created if they do not exist. Ensure you have a local Pulsar setup running. ```csharp using DotPulsar; using DotPulsar.Extensions; const string myTopic = "persistent://public/default/mytopic"; // connecting to pulsar://localhost:6650 await using var client = PulsarClient.Builder().Build(); // produce a message await using var producer = client.NewProducer(Schema.String).Topic(myTopic).Create(); await producer.Send("Hello World"); // consume messages await using var consumer = client.NewConsumer(Schema.String) .SubscriptionName("MySubscription") .Topic(myTopic) .InitialPosition(SubscriptionInitialPosition.Earliest) .Create(); await foreach (var message in consumer.Messages()) { Console.WriteLine($"Received: {message.Value()}"); await consumer.Acknowledge(message); } ``` -------------------------------- ### Install .NET SDK on macOS Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Use Homebrew to install the .NET SDK on macOS. Ensure you have the latest version compatible with DotPulsar. ```shell brew install --cask dotnet-sdk ``` -------------------------------- ### Show .NET SDK Version Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Verify the installed .NET SDK version. DotPulsar requires version 9.0.x. ```shell dotnet --info ``` -------------------------------- ### Create Pulsar Reader using Options Source: https://github.com/apache/pulsar-dotpulsar/wiki/Reader Instantiate a reader by providing ReaderOptions, which include the starting message ID and topic. This method bypasses the builder pattern. ```csharp var options = new ReaderOptions(MessageId.Earliest, "persistent://public/default/mytopic"); var reader = client.CreateReader(options); ``` -------------------------------- ### Create Pulsar Reader using Builder Source: https://github.com/apache/pulsar-dotpulsar/wiki/Reader Use the builder pattern to configure and create a reader instance. Specify the starting message ID and the topic. ```csharp var reader = client.NewReader() .StartMessageId(MessageId.Earliest) .Topic("persistent://public/default/mytopic") .Create(); ``` -------------------------------- ### Consume Messages from a Topic Source: https://github.com/apache/pulsar-dotpulsar/blob/master/src/DotPulsar/README.md Create a consumer to subscribe to a topic and receive messages. The subscription name and topic are specified, and the consumer starts from the earliest available message. Messages are acknowledged after processing. ```csharp await using var consumer = client.NewConsumer(Schema.String) .SubscriptionName("MySubscription") .Topic("persistent://public/default/mytopic") .InitialPosition(SubscriptionInitialPosition.Earliest) .Create(); await foreach (var message in consumer.Messages()) { Console.WriteLine($"Received: {message.Value()}"); await consumer.Acknowledge(message); } ``` -------------------------------- ### Run Pulsar Docker Container and Application Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Build the Pulsar application, pull the latest Pulsar Docker image, run a standalone Pulsar instance, wait for it to start, and then execute the application. Finally, stop the Pulsar container. ```shell dotnet build docker pull apachepulsar/pulsar:latest docker run --name pulsar-standalone -d --rm -it -p 8080:8080 -p 6650:6650 apachepulsar/pulsar:latest /pulsar/bin/pulsar standalone -nss -nfw echo "Waiting 10 seconds for Pulsar to start..." sleep 10 echo "Running application..." dotnet run docker stop pulsar-standalone ``` -------------------------------- ### Monitor Consumer State Transitions with StateChangedFrom Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring Continuously monitor a consumer's state transitions, starting from 'Disconnected'. Logs each state change and stops when a final state is reached. ```csharp private static async ValueTask Monitor(IConsumer consumer, CancellationToken cancellationToken) { var state = ConsumerState.Disconnected; while (!cancellationToken.IsCancellationRequested) { var stateChanged = await consumer.StateChangedFrom(state, cancellationToken); state = stateChanged.ConsumerState; Console.WriteLine($"The consumer for topic '{stateChanged.Consumer.Topic}' changed state to '{stateChanged.ConsumerState}'"); if (consumer.IsFinalState(state)) return; } } ``` -------------------------------- ### Acknowledge Messages Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Provides examples for acknowledging a single message or acknowledging all messages up to a certain point. ```APIDOC ## Single acknowledgment ```csharp await consumer.Acknowledge(message); ``` ## Cumulative acknowledgment ```csharp await consumer.AcknowledgeCumulative(message); ``` Please do note: We can't do this if the subscription is shared! ``` -------------------------------- ### Monitor Producer State Transitions with StateChangedFrom Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring Continuously monitor a producer's state transitions, starting from 'Disconnected'. Logs each state change and stops when a final state is reached. ```csharp private static async ValueTask Monitor(IProducer producer, CancellationToken cancellationToken) { var state = ProducerState.Disconnected; while (!cancellationToken.IsCancellationRequested) { var stateChanged = await producer.StateChangedFrom(state, cancellationToken); state = stateChanged.ProducerState; Console.WriteLine($"The producer for topic '{stateChanged.Producer.Topic}' changed state to '{stateChanged.ProducerState}'"); if (producer.IsFinalState(state)) return; } } ``` -------------------------------- ### Monitor Reader State Transitions with StateChangedFrom Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring Continuously monitor a reader's state transitions, starting from 'Disconnected'. Logs each state change and stops when a final state is reached. ```csharp private static async ValueTask Monitor(IReader reader, CancellationToken cancellationToken) { var state = ReaderState.Disconnected; while (!cancellationToken.IsCancellationRequested) { var stateChanged = await reader.StateChangedFrom(state, cancellationToken); state = stateChanged.ReaderState; Console.WriteLine($"The reader for topic '{stateChanged.Reader.Topic}' changed state to '{stateChanged.ReaderState}'"); if (reader.IsFinalState(state)) return; } } ``` -------------------------------- ### Implement Custom Exception Handler in C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Resilience Implement the IHandleException interface to create a custom exception handler. This example retries SocketExceptions with a specified interval. Set ExceptionHandled to true to prevent further handlers from being called. ```csharp public sealed class CustomExceptionHandler : IHandleException { private readonly TimeSpan _retryInterval; public CustomExceptionHandler(TimeSpan retryInterval) => _retryInterval = retryInterval; public async ValueTask OnException(ExceptionContext exceptionContext) { if (exceptionContext.Exception is SocketException socketException) { await Task.Delay(_retryInterval, exceptionContext.CancellationToken); exceptionContext.Result = FaultAction.Retry; exceptionContext.ExceptionHandled = true; } } } ``` -------------------------------- ### Email Template for Release Vote Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md This is an email template to initiate the voting process for a release candidate on the Pulsar Dev mailing list. It includes links to release notes, source packages, and validation guides. ```email To: dev@pulsar.apache.org Subject: [VOTE] DotPulsar Release $DOTPULSAR_VERSION_RC Hi everyone, Please review and vote on the release candidate $N for the version $DOTPULSAR_VERSION, as follows: [ ] +1, Approve the release [ ] -1, Do not approve the release (please provide specific comments) DotPulsar's KEYS file contains the PGP keys we used to sign this release: https://downloads.apache.org/pulsar/KEYS Please download these packages and review this release candidate: - Review release notes - Download the source package (verify shasum, and asc) and follow the README.md to build and run DotPulsar. The vote will be open for at least 72 hours. It is adopted by majority approval, with at least 3 PMC affirmative votes. Guide for Validating DotPulsar Release on Linux and MacOS https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Source file: https://dist.apache.org/repos/dist/dev/pulsar/pulsar-dotpulsar-$DOTPULSAR_VERSION_RC/ Nuget package: https://www.nuget.org/packages/DotPulsar/$DOTPULSAR_VERSION_RC The tag to be voted upon: https://github.com/apache/pulsar-dotpulsar/tree/$DOTPULSAR_VERSION_RC SHA-512 checksums: 97bb1000f70011e9a585186590e0688586590e09 pulsar-dotpulsar-$DOTPULSAR_VERSION-src.tar.gz ``` -------------------------------- ### Create and Populate SVN Staging Directory Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md Create a directory in the Apache SVN repository for staging the release artifacts. Then, check out this directory, copy the signed artifacts into it, and commit the changes. ```shell svn mkdir -m "Create DotPulsar pre-release dir" https://dist.apache.org/repos/dist/dev/pulsar/pulsar-dotpulsar-$DOTPULSAR_VERSION_RC svn co https://dist.apache.org/repos/dist/dev/pulsar/pulsar-dotpulsar-$DOTPULSAR_VERSION_RC cd pulsar-dotpulsar-$DOTPULSAR_VERSION_RC cp /path/to/pulsar-dotpulsar-$DOTPULSAR_VERSION-src.* . svn add * svn ci -m 'Staging artifacts and signature for DotPulsar $DOTPULSAR_VERSION_RC' ``` -------------------------------- ### Create Consumer Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Demonstrates two ways to create a consumer: using a builder pattern or a ConsumerOptions object. ```APIDOC ## Create a consumer using the builder ```csharp var consumer = client.NewConsumer() .SubscriptionName("MySubscription") .Topic("persistent://public/default/mytopic") .Create(); ``` ## Create a consumer without the builder ```csharp var options = new ConsumerOptions("MySubscription", "persistent://public/default/mytopic"); var consumer = client.CreateConsumer(options); ``` ``` -------------------------------- ### Create a basic Pulsar client Source: https://github.com/apache/pulsar-dotpulsar/wiki/Client Creates a client connected to the default Pulsar service URL ('pulsar://localhost:6650'). Assumes a standalone cluster. ```csharp var client = PulsarClient.Builder().Build(); ``` -------------------------------- ### Create and Configure a Simple Pulsar Application Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Generate a new console application, add the DotPulsar package, and define the application logic to produce and consume messages. ```shell dotnet new console -n PulsarApp cd PulsarApp dotnet add package DotPulsar --version "$DOTPULSAR_VERSION_RC" ``` ```csharp using DotPulsar; using DotPulsar.Extensions; const string myTopic = "persistent://public/default/mytopic"; Console.WriteLine("Connecting to pulsar://localhost:6650"); await using var client = PulsarClient.Builder().Build(); Console.WriteLine("Connected"); Console.WriteLine("Creating consumer"); // consume messages await using var consumer = client.NewConsumer(Schema.String) .SubscriptionName("MySubscription") .Topic(myTopic) .InitialPosition(SubscriptionInitialPosition.Earliest) .Create(); Console.WriteLine("Created."); // produce a message Console.WriteLine("Creating a producer."); await using var producer = client.NewProducer(Schema.String).Topic(myTopic).Create(); Console.WriteLine("Sending a message."); await producer.Send("Hello World"); Console.WriteLine("Sent."); Console.WriteLine("Waiting for a message."); var message = consumer.Receive().Result; Console.WriteLine("Received: " + message.Value()); await consumer.Acknowledge(message); Console.WriteLine("Acknowledged message"); ``` -------------------------------- ### Create Consumer using Builder - C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Use the builder pattern to configure and create a consumer instance. Requires subscription name and topic. ```csharp var consumer = client.NewConsumer() .SubscriptionName("MySubscription") .Topic("persistent://public/default/mytopic") .Create(); ``` -------------------------------- ### Create Producer with Builder Source: https://github.com/apache/pulsar-dotpulsar/wiki/Producer Use the builder pattern to create a producer, specifying the topic. Ensure a client is already initialized. ```csharp var producer = client.NewProducer() .Topic("persistent://public/default/mytopic") .Create(); ``` -------------------------------- ### Build DotPulsar Source Package Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Extract the source tarball, navigate into the source directory, and build the package using the .NET CLI. ```shell tar zxvf pulsar-dotpulsar-${DOTPULSAR_VERSION}-src.tar.gz cd pulsar-dotpulsar-${DOTPULSAR_VERSION}-src dotnet build ``` -------------------------------- ### Define Release Version Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md Set environment variables for the release and release candidate versions. Adjust these to the actual versions for your release. ```shell export DOTPULSAR_VERSION=3.0.0 export DOTPULSAR_VERSION_RC=3.0.0-rc.1 ``` -------------------------------- ### Create Producer without Builder Source: https://github.com/apache/pulsar-dotpulsar/wiki/Producer Create a producer by instantiating ProducerOptions with the topic and then passing it to the client's CreateProducer method. Ensure a client is already initialized. ```csharp var options = new ProducerOptions("persistent://public/default/mytopic"); var producer = client.CreateProducer(options); ``` -------------------------------- ### Create a Pulsar client with custom options Source: https://github.com/apache/pulsar-dotpulsar/wiki/Client Configures a client with a specific service URL and retry interval using the builder pattern. ```csharp var client = PulsarClient.Builder() .ServiceUrl("pulsar://example.com:6650") .RetryInterval(TimeSpan.FromSeconds(5)) .Build(); ``` -------------------------------- ### File Header Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CONTRIBUTING.md Use this standard Apache 2.0 license header for all new files in the repository. ```text /* * Licensed 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. */ ``` -------------------------------- ### Create Consumer without Builder - C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Create a consumer using predefined options. Requires a ConsumerOptions object with subscription name and topic. ```csharp var options = new ConsumerOptions("MySubscription", "persistent://public/default/mytopic"); var consumer = client.CreateConsumer(options); ``` -------------------------------- ### Import GPG Public Keys Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Import the Apache Pulsar GPG public keys to verify the authenticity of the downloaded release artifacts. ```shell gpg --import <(curl -s https://downloads.apache.org/pulsar/KEYS) ``` -------------------------------- ### Create a Pulsar client with TLS client certificate authentication Source: https://github.com/apache/pulsar-dotpulsar/wiki/Client Authenticates using a client certificate loaded from a PFX file. Ensure the PFX is passwordless for simplicity. ```csharp var clientCertificate = new X509Certificate2("admin.pfx"); var client = PulsarClient.Builder() .AuthenticateUsingClientCertificate(clientCertificate) .Build(); ``` -------------------------------- ### Create Pulsar Client Source: https://github.com/apache/pulsar-dotpulsar/blob/master/src/DotPulsar/README.md Instantiate a Pulsar client to connect to the Pulsar service. The client is used to create consumers and producers. Ensure the Pulsar service is running at the specified address. ```csharp using DotPulsar; using DotPulsar.Extensions; await using var client = PulsarClient.Builder().Build(); // Connecting to pulsar://localhost:6650 ``` -------------------------------- ### Create a Pulsar client with JWT authentication Source: https://github.com/apache/pulsar-dotpulsar/wiki/Client Authenticates the client using a JSON Web Token. The token should be provided directly. ```csharp var client = PulsarClient.Builder() .Authenticate(AuthenticationFactory.Token("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.ipevRNuRP6HflG8cFKnmUPtypruRC4fb1DWtoLL62SY")) .Build(); ``` -------------------------------- ### Create Consumer with StateChangedHandler Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring Configure a new consumer to use a custom handler for state change events. The handler will be invoked when the consumer's state transitions. ```csharp await using var consumer = client.NewConsumer() .StateChangedHandler(Monitor) .SubscriptionName("MySubscription") .Topic("persistent://public/default/mytopic") .Create(); ``` -------------------------------- ### Download DotPulsar Source Release Artifacts Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Download the source tarball, its GPG signature, and SHA512 checksum file using wget. ```shell wget https://dist.apache.org/repos/dist/dev/pulsar/pulsar-dotpulsar-${DOTPULSAR_VERSION_RC}/pulsar-dotpulsar-${DOTPULSAR_VERSION}-src.tar.gz{,.asc,.sha512} ``` -------------------------------- ### List Release Artifacts in SVN Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md List all directories (releases) present in the release repository for Pulsar. This is useful for identifying older releases that may need to be removed. ```shell svn ls https://dist.apache.org/repos/dist/release/pulsar | grep dotpulsar ``` -------------------------------- ### Create a Pulsar client with TLS certificate verification Source: https://github.com/apache/pulsar-dotpulsar/wiki/Client Establishes an encrypted connection, explicitly trusting a CA certificate and configuring certificate name verification. ```csharp var certificate = new X509Certificate2("ca.cert.pem"); var client = PulsarClient.Builder() .TrustedCertificateAuthority(certificate) //If the CA is not trusted on the host, we can add it explicitly. .VerifyCertificateAuthority(true) //Default is 'true' .VerifyCertificateName(false) //Default is 'false' .Build(); ``` -------------------------------- ### Seek Consumer by Publish Time (DateTimeOffset) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Seek the consumer to a specific message publish time using DateTimeOffset. Requires 'DotPulsar.Extensions' namespace. ```csharp Consumer.Seek(DateTimeOffset publishTime, CancellationToken cancellationToken) ``` -------------------------------- ### Seek Consumer by Publish Time (DateTime) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Seek the consumer to a specific message publish time using DateTime. Requires 'DotPulsar.Extensions' namespace. ```csharp Consumer.Seek(DateTime publishTime, CancellationToken cancellationToken) ``` -------------------------------- ### Delay Consumer Monitor with TimeSpan Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring Use the DelayedStateMonitor extension method to set up a delayed state monitor for a consumer. This is recommended for ignoring short disconnects common in distributed systems. It specifies the operational state, the duration to wait before acting on a non-operational state, and callbacks for when a connection is lost or regained. ```csharp _ = consumer.DelayedStateMonitor( ConsumerState.Active, TimeSpan.FromSeconds(5), _logger.ConsumerLostConnection, _logger.ConsumerRegainedConnection, cancellationToken); ``` -------------------------------- ### Enable DotPulsar Tracing in OpenTelemetry Source: https://github.com/apache/pulsar-dotpulsar/wiki/Tracing Add the 'DotPulsar' source to OpenTelemetry's TracerProviderBuilder to enable tracing. This is the primary step for integrating DotPulsar's tracing capabilities. ```csharp .ConfigureServices(services => { services.AddOpenTelemetryTracing(builder => { builder.AddSource("DotPulsar"); }); }) ``` -------------------------------- ### Validate Release Artifacts Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Verify the integrity of the downloaded files using SHA512 checksums and GPG signatures. ```shell sha512sum -c *.sha512 gpg --verify-files *.asc ``` -------------------------------- ### Set DotPulsar Release Environment Variables Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release_validation_linux_macos.md Set environment variables for the DotPulsar release candidate and the base version before downloading artifacts. ```shell export DOTPULSAR_VERSION_RC=3.3.0-rc.1 export DOTPULSAR_VERSION=${DOTPULSAR_VERSION_RC%-rc.*} ``` -------------------------------- ### Create a Pulsar client with encrypted connections Source: https://github.com/apache/pulsar-dotpulsar/wiki/Client Configures the client to enforce encrypted connections using the 'EnforceEncrypted' policy. ```csharp var client = PulsarClient.Builder() .ConnectionSecurity(EncryptionPolicy.EnforceEncrypted) .Build(); ``` -------------------------------- ### Promote Release Artifacts Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md Move the release artifacts from the development staging directory to the official release directory in the SVN repository. This command assumes you have PMC permissions. ```shell svn move -m "release $DOTPULSAR_VERSION" https://dist.apache.org/repos/dist/dev/pulsar/pulsar-dotpulsar-$DOTPULSAR_VERSION_RC \ https://dist.apache.org/repos/dist/release/pulsar/pulsar-dotpulsar-$DOTPULSAR_VERSION ``` -------------------------------- ### Use ExceptionHandler Shortcut with Action Source: https://github.com/apache/pulsar-dotpulsar/wiki/Resilience Utilize the shortcut provided by IPulsarClientBuilder to register a custom exception handler using an Action delegate. This approach is less verbose than implementing the IHandleException interface directly. ```csharp await using var client = PulsarClient.Builder() .ExceptionHandler(CustomExceptionHandler) .Build(); //Connecting to pulsar://localhost:6650 ``` ```csharp private void CustomExceptionHandler(ExceptionContext exceptionContext) { Console.WriteLine("I got this awesome exception: " + exceptionContext.Exception); } ``` -------------------------------- ### Enable DotPulsar Metrics with OpenTelemetry Source: https://github.com/apache/pulsar-dotpulsar/wiki/Metrics Add the 'DotPulsar' meter to your OpenTelemetry MeterProviderBuilder to enable metrics collection. This is typically done during service configuration. ```csharp .ConfigureServices(services => { services.AddOpenTelemetryMetrics(builder => { builder.AddMeter("DotPulsar"); }); }) ``` -------------------------------- ### Package Source Code Tarball Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md Check out the release candidate tag and create a compressed tarball of the source code. This command also sets a prefix for the archive contents. ```shell git checkout $DOTPULSAR_VERSION_RC git archive --format=tar.gz \ --output=$(pwd)/pulsar-dotpulsar-$DOTPULSAR_VERSION_RC/pulsar-dotpulsar-$DOTPULSAR_VERSION-src.tar.gz \ --prefix="pulsar-dotpulsar-$DOTPULSAR_VERSION-src/" HEAD ``` -------------------------------- ### Send Data with Custom Metadata using Builder Source: https://github.com/apache/pulsar-dotpulsar/wiki/Producer Send a message with custom key-value properties using the builder pattern. The message data is provided as a byte array. ```csharp var data = Encoding.UTF8.GetBytes("Hello World"); var messageId = await producer.NewMessage() .Property("SomeKey", "SomeValue") .Send(data); ``` -------------------------------- ### Wait for Consumer State Change Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring Asynchronously wait for a consumer to transition from a specified state to any other state. Returns an object containing the consumer and its new state. ```csharp var stateChanged = await consumer.StateChangedFrom(ConsumerState.Active, cancellationToken); ``` -------------------------------- ### Produce Messages to a Topic Source: https://github.com/apache/pulsar-dotpulsar/blob/master/src/DotPulsar/README.md Create a producer to send messages to a specified topic. The message is sent asynchronously, and the message ID is returned upon successful sending. ```csharp await using var producer = client.NewProducer(Schema.String).Topic("persistent://public/default/mytopic").Create(); var messageId = await producer.Send("Hello World"); ``` -------------------------------- ### Commit Message Format Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CONTRIBUTING.md Follow this format for commit messages to ensure consistency. Include a summary, detailed explanation, and issue tracking if applicable. ```git Summarize change in 50 characters or less Provide more detail after the first line. Leave one blank line below the summary and wrap all lines at 72 characters or less. If the change fixes an issue, leave another blank line after the final paragraph and indicate which issue is fixed in the specific format below. Fix #42 ``` -------------------------------- ### Seek Reader by Publish Time (DateTimeOffset) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Seek the reader to a specific message publish time using DateTimeOffset. Requires 'DotPulsar.Extensions' namespace. ```csharp Reader.Seek(DateTimeOffset publishTime, CancellationToken cancellationToken) ``` -------------------------------- ### Send Data Source: https://github.com/apache/pulsar-dotpulsar/wiki/Producer Send a byte array message to the configured topic. Ensure the producer is created and the data is properly encoded. ```csharp var data = Encoding.UTF8.GetBytes("Hello World"); await producer.Send(data); ``` -------------------------------- ### Seek Reader by Publish Time (DateTime) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Seek the reader to a specific message publish time using DateTime. Requires 'DotPulsar.Extensions' namespace. ```csharp Reader.Seek(DateTime publishTime, CancellationToken cancellationToken) ``` -------------------------------- ### Monitor Consumer State Changes Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring A handler function to log consumer state changes. It receives the state change event and cancellation token, printing the topic and new state. ```csharp private static void Monitor(ConsumerStateChanged stateChanged, CancellationToken cancellationToken) { Console.WriteLine($"The consumer for topic '{stateChanged.Consumer.Topic}' changed state to '{stateChanged.ConsumerState}'"); } ``` -------------------------------- ### Dispose Consumer Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Explains that the Consumer implements IAsyncDisposable and should be disposed when no longer needed. ```APIDOC ## Disposing the consumer The Consumer implements IAsyncDisposable and should be disposed when it's no longer needed. Disposing the client will dispose all consumers. ``` -------------------------------- ### Send Message with Metadata (ReadOnlyMemory) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Send a message with metadata using ReadOnlyMemory. Requires 'DotPulsar.Extensions' namespace. ```csharp Producer.Send(MessageMetadata metadata, ReadOnlyMemory data, CancellationToken cancellationToken) ``` -------------------------------- ### Receive Messages Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Shows how to receive a single message or iterate over messages using an IAsyncEnumerable. ```APIDOC ## Receive a single message ```csharp var message = await consumer.Receive(); Console.WriteLine("Received: " + Encoding.UTF8.GetString(message.Data.ToArray())); ``` ## Receive messages as an IAsyncEnumerable ```csharp await foreach (var message in consumer.Messages()) { Console.WriteLine("Received: " + Encoding.UTF8.GetString(message.Data.ToArray())); } ``` ``` -------------------------------- ### Send Message with Metadata (byte array) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Send a message with metadata using a byte array. Requires 'DotPulsar.Extensions' namespace. ```csharp Producer.Send(MessageMetadata metadata, byte[] data, CancellationToken cancellationToken) ``` -------------------------------- ### Sign and Hash Source Artifacts Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md Generate a detached GPG signature and a SHA512 checksum for the source tarball. These are crucial for verifying the integrity of the release artifacts. ```shell gpg -b --armor pulsar-dotpulsar-$DOTPULSAR_VERSION-src.tar.gz shasum -a 512 pulsar-dotpulsar-$DOTPULSAR_VERSION-src.tar.gz > pulsar-dotpulsar-$DOTPULSAR_VERSION-src.tar.gz.sha512 ``` -------------------------------- ### Consumer State Changed From Event Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Use this extension method to subscribe to consumer state changes from a specific state. Requires 'DotPulsar.Extensions' namespace. ```csharp Consumer.StateChangedFrom(ConsumerState state, CancellationToken cancellationToken) ``` -------------------------------- ### Send Message (byte array) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Send a message using a byte array. Requires 'DotPulsar.Extensions' namespace. ```csharp Producer.Send(byte[] data, CancellationToken cancellationToken) ``` -------------------------------- ### Unsubscribe Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Shows how to unsubscribe the consumer from the topic. ```APIDOC ## Unsubscribing ```csharp await consumer.Unsubscribe(); ``` Please do note: We can't use the consumer after unsubscribing and therefore should dispose it. ``` -------------------------------- ### Send Data with Custom Metadata without Builder Source: https://github.com/apache/pulsar-dotpulsar/wiki/Producer Send a message with custom metadata, including key-value pairs, and the message data. The metadata is set on a MessageMetadata object. ```csharp var data = Encoding.UTF8.GetBytes("Hello World"); var metadata = new MessageMetadata(); metadata["SomeKey"] = "SomeValue"; var messageId = await producer.Send(metadata, data)); ``` -------------------------------- ### Send Message (ReadOnlyMemory) Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Send a message using ReadOnlyMemory. Requires 'DotPulsar.Extensions' namespace. ```csharp Producer.Send(ReadOnlyMemory data, CancellationToken cancellationToken) ``` -------------------------------- ### Consumer State Changed To Event Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Use this extension method to subscribe to consumer state changes to a specific state. Requires 'DotPulsar.Extensions' namespace. ```csharp Consumer.StateChangedTo(ConsumerState state, CancellationToken cancellationToken) ``` -------------------------------- ### Email Template for Release Vote Summary Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md This email template is used to announce the outcome of the release vote. It confirms whether the release passed or failed and lists the binding votes. ```email To: dev@pulsar.apache.org Subject: [RESULT][VOTE] Apache Pulsar DotPulsar $DOTPULSAR_VERSION released [RESULT][VOTE] Release Apache DotPulsar $DOTPULSAR_VERSION The vote to release Apache DotPulsar $DOTPULSAR_VERSION has passed. The vote PASSED with xxx binding +1 and 0 -1 votes: Binding votes: - Yuan Wang - tison - hulk - Liang Chen - Jean-Baptiste Onofré - Xiaoqiao He - donghui liu Vote thread: https://lists.apache.org/thread/XXX Thank you to all the above members for helping us to verify and vote for the $DOTPULSAR_VERSION release. Thanks ``` -------------------------------- ### Unsubscribe Consumer - C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Unsubscribe the consumer from the topic. After unsubscribing, the consumer can no longer be used and should be disposed. ```csharp await consumer.Unsubscribe(); ``` -------------------------------- ### Consume Messages Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Retrieve messages from the consumer. Requires 'DotPulsar.Extensions' namespace. ```csharp Consumer.Messages(CancellationToken cancellationToken) ``` -------------------------------- ### Monitor Producer State Changes Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring A handler function to log producer state changes. It receives the state change event and cancellation token, printing the topic and new state. ```csharp private static void Monitor(ProducerStateChanged stateChanged, CancellationToken cancellationToken) { Console.WriteLine($"The producer for topic '{stateChanged.Producer.Topic}' changed state to '{stateChanged.ProducerState}'"); } ``` -------------------------------- ### Seek to Message Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Demonstrates how to reset the consumer's cursor to a specific message ID. ```APIDOC ## Seeking ```csharp await consumer.Seek(MessageId.Earliest); // Provide the message-id to reset to. ``` Please do note: When seeking we will shortly be disconnected, as that's how Pulsar handles seek requests. ``` -------------------------------- ### Seek to Earliest Message - C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Reset the consumer's cursor to the earliest available message in the topic. Note that this action may temporarily disconnect the consumer. ```csharp await consumer.Seek(MessageId.Earliest); // Provide the message-id to reset to. ``` -------------------------------- ### Add Custom Exception Handler to PulsarClient Builder Source: https://github.com/apache/pulsar-dotpulsar/wiki/Resilience Configure the PulsarClient to use a custom exception handler by providing an instance to the ExceptionHandler method in the builder. The same handler instance is used for all producers, consumers, and readers. ```csharp var retryInterval = TimeSpan.FromSeconds(5); var customExceptionHandler = new CustomExceptionHandler(retryInterval); await using var client = PulsarClient.Builder() .ExceptionHandler(customExceptionHandler) .Build(); ``` -------------------------------- ### Receive a Single Message - C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Retrieve a single message from the consumer. The message data is available as a ReadOnlySequence. ```csharp var message = await consumer.Receive(); Console.WriteLine("Received: " + Encoding.UTF8.GetString(message.Data.ToArray())); ``` -------------------------------- ### Receive a Single Message from Reader Source: https://github.com/apache/pulsar-dotpulsar/wiki/Reader Retrieve a single message from the reader. The message data is then decoded from UTF-8. ```csharp var message = await reader.Receive(); Console.WriteLine("Received: " + Encoding.UTF8.GetString(message.Data.ToArray())); ``` -------------------------------- ### Release Announcement Email Template Source: https://github.com/apache/pulsar-dotpulsar/blob/master/docs/release-process.md A template for announcing a new DotPulsar release to the Apache Pulsar mailing lists. Remember to replace `$DOTPULSAR_VERSION` and `X.X.X` with the actual version numbers. ```email To: dev@pulsar.apache.org, users@pulsar.apache.org, announce@apache.org Subject: [ANNOUNCE] Apache Pulsar C# Client DotPulsar $DOTPULSAR_VERSION released The Apache Pulsar team is proud to announce DotPulsar version $DOTPULSAR_VERSION. Pulsar is a highly scalable, low-latency messaging platform running on commodity hardware. It provides simple pub-sub semantics over topics, guaranteed at least once delivery of messages, automatic cursor management for subscribers, and cross-datacenter replication. For Pulsar release details and downloads, visit: https://github.com/apache/pulsar-dotpulsar/releases/tag/X.X.X Nuget package: https://www.nuget.org/packages/DotPulsar/X.X.X Release Notes are at: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md We would like to thank the contributors who made the release possible. Regards, The Pulsar Team ``` -------------------------------- ### Producer State Changed From Event Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Use this extension method to subscribe to producer state changes from a specific state. Requires 'DotPulsar.Extensions' namespace. ```csharp Producer.StateChangedFrom(ProducerState state, CancellationToken cancellationToken) ``` -------------------------------- ### Monitor Reader State Changes Source: https://github.com/apache/pulsar-dotpulsar/wiki/Monitoring A handler function to log reader state changes. It receives the state change event and cancellation token, printing the topic and new state. ```csharp private static void Monitor(ReaderStateChanged stateChanged, CancellationToken cancellationToken) { Console.WriteLine($"The reader for topic '{stateChanged.Reader.Topic}' changed state to '{stateChanged.ReaderState}'"); } ``` -------------------------------- ### Producer State Changed To Event Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Use this extension method to subscribe to producer state changes to a specific state. Requires 'DotPulsar.Extensions' namespace. ```csharp Producer.StateChangedTo(ProducerState state, CancellationToken cancellationToken) ``` -------------------------------- ### Read Messages Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Retrieve messages from the reader. Requires 'DotPulsar.Extensions' namespace. ```csharp Reader.Messages(CancellationToken cancellationToken) ``` -------------------------------- ### Reader State Changed From Event Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Use this extension method to subscribe to reader state changes from a specific state. Requires 'DotPulsar.Extensions' namespace. ```csharp Reader.StateChangedFrom(ReaderState state, CancellationToken cancellationToken) ``` -------------------------------- ### Receive Messages as IAsyncEnumerable - C# Source: https://github.com/apache/pulsar-dotpulsar/wiki/Consumer Process messages as an asynchronous stream using the Messages() extension method. Useful for continuous message consumption. ```csharp await foreach (var message in consumer.Messages()) { Console.WriteLine("Received: " + Encoding.UTF8.GetString(message.Data.ToArray())); } ``` -------------------------------- ### Receive Messages as IAsyncEnumerable Source: https://github.com/apache/pulsar-dotpulsar/wiki/Reader Utilize the Messages() extension method to read messages from the reader as an asynchronous stream. This is suitable for continuous message processing. ```csharp await foreach (var message in reader.Messages()) { Console.WriteLine("Received: " + Encoding.UTF8.GetString(message.Data.ToArray())); } ``` -------------------------------- ### Reader State Changed To Event Source: https://github.com/apache/pulsar-dotpulsar/blob/master/CHANGELOG.md Use this extension method to subscribe to reader state changes to a specific state. Requires 'DotPulsar.Extensions' namespace. ```csharp Reader.StateChangedTo(ReaderState state, CancellationToken cancellationToken) ```