Ejemplo n.º 1
0
        public static EventConsumptionWorker CreateWorker(IEventConsumerAsync consumer, string subscriptionName, bool batched)
        {
            var worker = new EventConsumptionWorker(
                eventConsumer: consumer,
                subscriptionName: subscriptionName,
                logger: serviceProvider.GetRequiredService <ILoggerFactory>().CreateLogger <EventConsumptionWorker>(),
                batchSize: batched ? 300 : 1,
                consumeModel: batched ? ConsumeModel.Batch : ConsumeModel.Single,

                consumeAction: !batched ? async(ceW) =>
            {
                //Console.WriteLine($"Consumed {ceW.Id} from thread {System.Threading.Thread.CurrentThread.ManagedThreadId}.");
                await Task.Delay(1);     // Some processing delay

                //if (DateTime.UtcNow.Millisecond < 50)
                //    throw new Exception("This exception was unhandled by the ConsumeAction.");

                //if (DateTime.UtcNow.Millisecond > 900)
                //    return ConsumeResult.MustRetry("ConsumeAction decided this event has to be retried.");

                return(ConsumeResult.Succeeded);
            } : default(Func <ConsumableEvent, Task <ConsumeResult> >),

                consumeBatchAction: batched ? async(ces) =>
            {
                await Task.Delay(ces.Count());

                return(ces
                       .Select(ce => new KeyValuePair <Int64, ConsumeResult>(ce.Id, ConsumeResult.Succeeded)) // Return success for all
                       .ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
            } : default(Func <IEnumerable <ConsumableEvent>, Task <IDictionary <Int64, ConsumeResult> > >)
                );

            return(worker);
        }
Ejemplo n.º 2
0
        public static void Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();

            ConfigureServices(serviceCollection);
            serviceProvider = serviceCollection.BuildServiceProvider();

            var publisher = serviceProvider.GetRequiredService <IEventPublisherAsync>();
            var consumer  = serviceProvider.GetRequiredService <IEventConsumerAsync>();

            // Make sure the topic exists
            var topic1 = publisher.GetTopicByNameAsync("Demo Topic 1").GetAwaiter().GetResult() ?? publisher.AddOrUpdateTopicAsync(new Topic {
                Name = "Demo Topic 1", Log = false
            }).GetAwaiter().GetResult();
            var subscription1 = consumer.GetSubscriptionByNameAsync("Demo Subscription 1").GetAwaiter().GetResult();

            subscription1 = consumer.AddOrUpdateSubscriptionAsync(new Subscription
            {
                Id                 = subscription1 != null ? subscription1.Id.Value : default(Int64?),
                Name               = "Demo Subscription 1",
                MaxDeliveries      = 2,        // Not too many delivery attempts
                DeliveryDelay      = 2,        // Deliverydelay, so that events cannot overtake eachother while publishing (because of IO latency of the DB)
                Ordered            = !BATCHED, // Batched processing of ordered subscription is usually not very usefull
                LogConsumed        = true,
                TopicSubscriptions = new List <TopicSubscription>
                {
                    new TopicSubscription
                    {
                        TopicId = topic1.Id.Value, Enabled = true,
                    },
                },
            }).GetAwaiter().GetResult();

            //var te = publisher.PublishAsync(topic1.Name, payload: "ŻŹŶŴŲŰŮŬŪŨŦŤŢŠŞŜŚŘŖŔŐŎŌŊŇŅŃŁĿĽĻĹĶĴĮĬĪĨĦĤĢĠĞĜĚĘĖĔĒĐĎČĊĈĆĄĂĀŸÝÜÛÚÙØÖÕÔÓÒÑÏÎÍÌËÊÉÈÇÅÄÃÂ").GetAwaiter().GetResult();
            //Thread.Sleep(TimeSpan.FromSeconds(3)); // Must be equal or more than the delivery delay!
            //var ce = consumer.ConsumeNextAsync(subscription1.Name).GetAwaiter().GetResult().FirstOrDefault();
            //if (ce != null)
            //    consumer.MarkConsumedAsync(ce.Id, ce.DeliveryKey).GetAwaiter().GetResult();

            var workers = new EventConsumptionWorker[WORKER_COUNT];

            for (int i = 0; i < WORKER_COUNT; i++)
            {
                workers[i] = CreateWorker(consumer, "Demo Subscription 1", BATCHED);
                workers[i].Start();
            }

            // Generate data WHILE also consuming (just like the real world)
            if (GENERATE_DATA)
            {
                var sw = new Stopwatch();
                sw.Start();

                var arrLen = 500;
                var nrs    = new List <int>(arrLen);
                for (int i = 0; i < arrLen; i++)
                {
                    nrs.Add(i);
                }
                ;

                nrs.AsParallel().ForAll((i) =>
                                        Task.Run(async() => // Threadpool task to wait for async parts in inner task
                {
                    Console.WriteLine($"Run {i:D4} - Start  [{Thread.CurrentThread.ManagedThreadId}]");
                    for (int fk = 1; fk <= 10; fk++)         // 1000 different functional keys, 4 TopicEvents per fk
                    {
                        await Task.Delay(1).ConfigureAwait(false);
                        var fkAsString = i.ToString();
                        try
                        {
                            await publisher.PublishAsync(topic1.Name, functionalKey: fkAsString, payload: "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); // 100 bytes
                        }
                        catch (Exception) { }                                                                                                                                                                      // Ignore repo-exceptions (probably deadlocks)
                    }
                    Console.WriteLine($"Run {i:D4} - Finish [{Thread.CurrentThread.ManagedThreadId}]");
                }
                                                 ).GetAwaiter().GetResult() // Block until all async work is done (ForAll does not await on Task as result-type)
                                        );

                sw.Stop();
                Console.WriteLine($"Total time for publishing: {sw.Elapsed.TotalSeconds} sec");
            }

            // Wait for a user to press Ctrl+C or when windows sends the stop process signal
            Console.WriteLine("Press Ctrl+C to stop the worker(s)...");
            var handle = new ManualResetEvent(false);

            Console.CancelKeyPress += (s, e) => { handle.Set(); e.Cancel = true; }; // Cancel must be true, to make sure the process is not killed and we can clean up nicely below
            handle.WaitOne();

            for (int i = 0; i < WORKER_COUNT; i++)
            {
                if (workers[i].IsRunning())
                {
                    workers[i].Stop();
                }
            }

            // Some housekeeping to clean up overtaken events etc.
            publisher.PerformHouseKeepingTasksAsync().GetAwaiter().GetResult();
        }