public void Client() { string projectId = _fixture.ProjectId; string topicId = _fixture.CreateTopicId(); // Sample: ClientWide // Create a default PublisherServiceApiSettings, with a custom header for calls to all RPC methods. PublisherServiceApiSettings publisherSettings = new PublisherServiceApiSettings { CallSettings = new CallSettings(null, null, null, metadata => metadata.Add("ClientVersion", "1.0.0"), null, null) }; PublisherServiceApiClient client = PublisherServiceApiClient.Create(settings: publisherSettings); // Create a topic name from the projectId and topicId. TopicName topicName = new TopicName(projectId, topicId); // The custom 'ClientVersion' header will be included in the RPC call, due to // the client being configured with 'publishersettings' above. Topic topic = client.CreateTopic(topicName); // End sample }
public void ClientPerMethod() { string projectId = _fixture.ProjectId; string topicId = _fixture.CreateTopicId(); // Sample: ClientPerMethod // Create a default PublisherServiceApiSettings, with a custom header for calls // to the CreateTopic RPC method. PublisherServiceApiSettings publisherSettings = new PublisherServiceApiSettings(); publisherSettings.CreateTopicSettings = publisherSettings.CreateTopicSettings.WithHeader("ClientVersion", "1.0.0"); PublisherServiceApiClient client = PublisherServiceApiClient.Create(settings: publisherSettings); // Create a topic name from the projectId and topicId. TopicName topicName = new TopicName(projectId, topicId); // The custom 'ClientVersion' header will be included in the RPC call, due to // the client being configured with 'publishersettings' above. Topic topic = client.CreateTopic(topicName); // End sample }
public void Overrides() { string projectId = _fixture.ProjectId; string topicId = _fixture.CreateTopicId(); DateTime deadline = DateTime.MaxValue; CancellationToken cancellationToken = new CancellationTokenSource().Token; // Sample: Overrides // Create a default PublisherServiceApiSettings, with customizations for CreateTopic RPCs: // * A custom "ClientVersion" header. // * A custom 5-second timeout Timing. // * No cancellation token. PublisherServiceApiSettings publisherSettings = new PublisherServiceApiSettings(); publisherSettings.CreateTopicSettings = publisherSettings.CreateTopicSettings .WithCancellationToken(CancellationToken.None) .WithTimeout(TimeSpan.FromSeconds(5)) .WithHeader("ClientVersion", "1.0.0"); // Override the above Timing and CancellationToken in the client-wide CallSettings; // the Headers are not overridden. publisherSettings.CallSettings = CallSettings .FromExpiration(Expiration.FromDeadline(deadline)) .WithCancellationToken(CancellationToken.None); // Create the client with the configured publisherSettings PublisherServiceApiClient client = new PublisherServiceApiClientBuilder { Settings = publisherSettings }.Build(); // Create a topic name from the projectId and topicId. TopicName topicName = new TopicName(projectId, topicId); // Call CreateTopic(). Override only the CancellationToken, using a per-RPC-method CallSettings. // The CallSettings used during this RPC invocation is: // * A custom "ClientVersion" header. // * A Timing deadline of 'deadline' (*not* the overridden 5-second timeout). // * The CancellationToken 'cancellationToken' (*not* CancellationToken.None). Topic topic = client.CreateTopic(topicName, CallSettings.FromCancellationToken(cancellationToken)); // End sample }
private async Task RunBulkMessagingImpl( TopicName topicName, SubscriptionName subscriptionName, int messageCount, int minMessageSize, int maxMessageSize, int maxMessagesInFlight, int initialNackCount, TimeSpan?timeouts = null, int?cancelAfterRecvCount = null, TimeSpan?interPublishDelay = null, TimeSpan?debugOutputPeriod = null, int?publisherChannelCount = null, int?clientCount = null) { // Force messages to be at least 4 bytes long, so an int ID can be used. minMessageSize = Math.Max(4, minMessageSize); // Create PublisherClient and SubscriberClient var publisher = await PublisherClient.CreateAsync(topicName, clientCreationSettings : new PublisherClient.ClientCreationSettings( clientCount: publisherChannelCount, publisherServiceApiSettings: timeouts == null ? null : new PublisherServiceApiSettings { PublishSettings = CallSettings.FromCallTiming(CallTiming.FromRetry(new RetrySettings( retryBackoff: PublisherServiceApiSettings.GetMessagingRetryBackoff(), timeoutBackoff: new BackoffSettings(timeouts.Value, timeouts.Value, 1.0), totalExpiration: Expiration.FromTimeout(timeouts.Value), retryFilter: PublisherServiceApiSettings.NonIdempotentRetryFilter ))) } )).ConfigureAwait(false); var subscriber = await SubscriberClient.CreateAsync(subscriptionName, clientCreationSettings : new SubscriberClient.ClientCreationSettings(clientCount: clientCount), settings : new SubscriberClient.Settings { AckDeadline = timeouts, FlowControlSettings = new FlowControlSettings(maxMessagesInFlight, null) }).ConfigureAwait(false); Console.WriteLine("Topic, Subscription, Publisher and Subscriber all created"); // Subscribe int recvCount = 0; // Count of received messages int dupCount = 0; // Count of duplicate messages long recvSum = 0L; // Sum of bytes of received messages var recvedIds = new ConcurrentDictionary <int, bool>(); var nackedIds = new HashSet <int>(); Task subTask = subscriber.StartAsync((msg, ct) => { int id = BitConverter.ToInt32(msg.Data.ToArray(), 0); lock (nackedIds) { if (nackedIds.Count < initialNackCount) { if (nackedIds.Add(id)) { // This ID not already nacked Interlocked.Increment(ref recvCount); return(Task.FromResult(SubscriberClient.Reply.Nack)); } } } bool wasAdded = recvedIds.TryAdd(id, false); if (wasAdded) { var localRecvCount = Interlocked.Increment(ref recvCount); Interlocked.Add(ref recvSum, msg.Data.Sum(x => (long)x)); if (localRecvCount == cancelAfterRecvCount || localRecvCount >= messageCount + initialNackCount) { // Test finished, so stop subscriber Console.WriteLine("All msgs received, stopping subscriber."); Task unused = subscriber.StopAsync(TimeSpan.FromSeconds(15)); } } else { Interlocked.Add(ref dupCount, 1); } // ACK all messages return(Task.FromResult(SubscriberClient.Reply.Ack)); }); // Publish var rnd = new Random(1234); var activePubs = new HashSet <Task>(); int sentCount = 0; long sentSum = 0L; // Sum of bytes of sent messages // Watchdog to report progress and fail test on deadlock CancellationTokenSource watchdogCts = new CancellationTokenSource(); Task.Run(async() => { var debugOutputPeriod1 = debugOutputPeriod ?? TimeSpan.FromSeconds(1); int prevSentCount = -1; int prevRecvCount = -1; int noProgressCount = 0; while (true) { await Task.Delay(debugOutputPeriod1, watchdogCts.Token).ConfigureAwait(false); var localSentCount = Interlocked.Add(ref sentCount, 0); var localRecvCount = Interlocked.Add(ref recvCount, 0); var localDupCount = Interlocked.Add(ref dupCount, 0); if (prevSentCount == localSentCount && prevRecvCount == localRecvCount) { if (noProgressCount > 60) { // Deadlock, shutdown subscriber, and cancel Console.WriteLine("Deadlock detected. Cancelling test"); subscriber.StopAsync(new CancellationToken(true)); watchdogCts.Cancel(); break; } noProgressCount += 1; } else { noProgressCount = 0; } prevSentCount = localSentCount; prevRecvCount = localRecvCount; Console.WriteLine($"[{DateTime.Now}] Sent: {localSentCount} (in-flight: {activePubs.Locked(() => activePubs.Count)}); Recv: {localRecvCount} (dups: {localDupCount})"); } }); for (int i = 0; i < messageCount; i++) { if (watchdogCts.IsCancellationRequested) { Assert.True(false, "Test cancelled by watchdog"); } if (subTask.IsCompleted) { break; } if (i > 0 && interPublishDelay is TimeSpan delay) { await Task.Delay(delay, watchdogCts.Token).ConfigureAwait(false); } var msgSize = rnd.Next(minMessageSize, maxMessageSize + 1); var msg = new byte[msgSize]; rnd.NextBytes(msg); // Insert an int ID into message Array.Copy(BitConverter.GetBytes(i), msg, 4); sentSum += msg.Sum(x => (long)x); // Send message, and record Task var pubTask = publisher.PublishAsync(msg); Interlocked.Increment(ref sentCount); activePubs.Locked(() => activePubs.Add(pubTask)); // Remove Task from active when the message has been sent to server pubTask.ContinueWith(t => activePubs.Locked(() => activePubs.Remove(pubTask))); // If too many messages are currently in flight, wait a bit while (activePubs.Locked(() => activePubs.Count) >= maxMessagesInFlight) { await Task.Delay(TimeSpan.FromMilliseconds(1)).ConfigureAwait(false); } } Console.WriteLine("Publishing complete"); // Wait for all messages to be sent to server await Task.WhenAll(activePubs.Locked(() => activePubs.ToArray())).ConfigureAwait(false); Console.WriteLine("Publishing completed sending to server"); // Wait for subscriber to finish shutdown await subTask.ConfigureAwait(false); watchdogCts.Cancel(); Console.WriteLine("Subscriber finished shutdown"); Console.WriteLine($"Sent: {sentCount}; Recv: {recvCount}"); if (cancelAfterRecvCount is int cancelAfter) { Assert.True(recvCount >= cancelAfter && recvCount <= cancelAfter + maxMessagesInFlight, $"Incorrect recvCount: {recvCount}"); } else { // Check that all messages are correctly received. Assert.Equal(messageCount + initialNackCount, recvCount); // This isn't foolproof (we can get to the right sum with wrong values) but it's a pretty strong indicator. Assert.Equal(sentSum, recvSum); } Console.WriteLine("Test complete."); }