public static Fake Create(IReadOnlyList <IEnumerable <ServerAction> > msgs,
                                      TimeSpan?ackDeadline = null, TimeSpan?ackExtendWindow = null,
                                      int?flowMaxElements  = null, int?flowMaxBytes         = null,
                                      int clientCount      = 1, int threadCount = 1, TimeSpan?writeAsyncPreDelay = null,
                                      bool useMsgAsId      = false)
            {
                var             scheduler       = new TestScheduler(threadCount: threadCount);
                TaskHelper      taskHelper      = scheduler.TaskHelper;
                List <DateTime> clientShutdowns = new List <DateTime>();
                var             msgEn           = msgs.GetEnumerator();
                var             clients         = Enumerable.Range(0, clientCount)
                                                  .Select(_ => new FakeSubscriberServiceApiClient(msgEn, scheduler, scheduler.Clock, taskHelper, writeAsyncPreDelay ?? TimeSpan.Zero, useMsgAsId))
                                                  .ToList();
                var settings = new SubscriberClient.Settings
                {
                    Scheduler           = scheduler,
                    AckDeadline         = ackDeadline,
                    AckExtensionWindow  = ackExtendWindow,
                    FlowControlSettings = new FlowControlSettings(flowMaxElements, flowMaxBytes),
                };

                Task Shutdown()
                {
                    clientShutdowns.Locked(() => clientShutdowns.Add(scheduler.Clock.GetCurrentDateTimeUtc()));
                    return(Task.FromResult(0));
                }

                var subs = new SubscriberClientImpl(new SubscriptionName("projectid", "subscriptionid"), clients, settings, Shutdown, taskHelper);

                return(new Fake
                {
                    Scheduler = scheduler,
                    Time0 = scheduler.Clock.GetCurrentDateTimeUtc(),
                    TaskHelper = taskHelper,
                    Subscribers = clients,
                    ClientShutdowns = clientShutdowns,
                    Subscriber = subs,
                });
            }
Esempio n. 2
0
        static int Main(string[] args)
        {
            if (args.Length != 3)
            {
                Console.WriteLine("Call with three args: <emulator port> <input file> <output file>");
                Console.WriteLine("This connects to host 127.0.0.1, so requires the emulator to be started using ipv4, not ipv6:");
                Console.WriteLine("  E.g. cloud-pubsub-emulator.bat --host=127.0.0.1 --port=8700");
                Console.WriteLine("It reads and writes CSV files as specified in the 'Testing Ordering Keys' section of the");
                Console.WriteLine("  'Pub/Sub Ordering Key Client Libraries' doc.");
                Console.WriteLine();
                return(1);
            }

            // Read inputs.
            var port       = int.Parse(args[0]);
            var inputLines = File.ReadAllLines(args[1]).Select(line => new InputLine(line)).ToList();
            // Setup gRPC channel to pubsub emulator.
            var channel = new Channel("127.0.0.1", port, ChannelCredentials.Insecure);

            // Create topic and subscription names.
            var topicName        = new TopicName("project", $"topic-{Guid.NewGuid()}");
            var subscriptionName = new SubscriptionName("project", $"subscription-{Guid.NewGuid()}");
            // List that records all received messages.
            var recvMsgs = new List <PubsubMessage>();

            // Run test.
            CreateTopicAndSubscription();
            Task subTask = Subscribe();
            IEnumerable <Task> pubTasks = Publish();

            // Wait for publish and subscribe tasks to complete.
            Console.WriteLine("Waiting for all publish tasks to complete");
            Task.WaitAll(pubTasks.ToArray());
            Console.WriteLine("All publish tasks completed");
            Console.WriteLine("Waiting for subscribe task to complete");
            subTask.Wait();
            Console.WriteLine("Subscribe task completed");

            // Output ordered CSV file of recevied messages, for the validator.
            var csvLines = recvMsgs.Select(x => $"\"{x.OrderingKey}\",\"{x.Data.ToStringUtf8()}\"").ToList();

            File.WriteAllLines(args[2], csvLines);
            Console.WriteLine("Output file written; all done :)");

            return(0);

            void CreateTopicAndSubscription()
            {
                Console.WriteLine("Creating topic and subscription");
                var pubApi = CreatePublisher();
                var topic  = pubApi.CreateTopic(topicName);
                var subApi = CreateSubscriber();

                subApi.CreateSubscription(new Subscription
                {
                    EnableMessageOrdering = true,
                    TopicAsTopicName      = topicName,
                    SubscriptionName      = subscriptionName,
                    AckDeadlineSeconds    = 120,
                });
            }

            Task Subscribe()
            {
                Console.WriteLine("Creating subscribers");
                var subs = new[]
                {
                    CreateSubscriber(),
                    CreateSubscriber(),
                    CreateSubscriber()
                };
                var sub       = new SubscriberClientImpl(subscriptionName, subs, new SubscriberClient.Settings(), null);
                var recvCount = 0;
                var rnd       = new Random();

                Console.WriteLine("Starting subscriber callback");
                return(sub.StartAsync(async(msg, ct) =>
                {
                    lock (recvMsgs)
                    {
                        recvMsgs.Add(msg.Clone());
                        recvCount += 1;
                        if (recvCount == inputLines.Count)
                        {
                            Console.WriteLine("Received all messages, shutting down");
                            var dummyTask = sub.StopAsync(CancellationToken.None);
                        }
                    }
                    if (rnd.Next(3) == 0)
                    {
                        await Task.Delay(rnd.Next(3));
                    }
                    return SubscriberClient.Reply.Ack;
                }));
            }

            IEnumerable <Task> Publish()
            {
                Console.WriteLine("Creating publishers");
                var pubs = new[]
                {
                    CreatePublisher(),
                    CreatePublisher(),
                    CreatePublisher()
                };
                var pub = new PublisherClientImpl(topicName, pubs, new PublisherClient.Settings {
                    EnableMessageOrdering = true
                }, null);
                var publishTasks = new List <Task>();

                Console.WriteLine("Starting to publish");
                foreach (var inputLine in inputLines)
                {
                    var pubTask = pub.PublishAsync(inputLine.OrderingKey, inputLine.Message);
                    publishTasks.Add(pubTask);
                }
                Console.WriteLine("Publishing complete");
                return(publishTasks);
            }

            PublisherServiceApiClient CreatePublisher() => new PublisherServiceApiClientBuilder
            {
                CallInvoker = channel.CreateCallInvoker()
            }

            .Build();
            SubscriberServiceApiClient CreateSubscriber() => new SubscriberServiceApiClientBuilder
            {
                CallInvoker = channel.CreateCallInvoker()
            }

            .Build();
        }