Пример #1
0
        public void Publish(IntegrationEvent @event)
        {
            var eventName   = @event.GetType().Name.Replace(INTEGRATION_EVENT_SUFFIX, "");
            var jsonMessage = JsonConvert.SerializeObject(@event);
            var body        = Encoding.UTF8.GetBytes(jsonMessage);

            var message = new Message
            {
                MessageId = Guid.NewGuid().ToString(),
                Body      = body,
                Label     = eventName,
            };

            var topicClient = _serviceBusPersisterConnection.CreateModel();

            topicClient.SendAsync(message)
            .GetAwaiter()
            .GetResult();
        }
Пример #2
0
        public void Publish(IntegrationEvent @event)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }

            var policy = RetryPolicy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message);
            });

            var eventName = @event.GetType().Name;

            _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName);

            using (var channel = _persistentConnection.CreateModel())
            {
                _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id);

                channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct");

                var message = JsonConvert.SerializeObject(@event);
                var body    = Encoding.UTF8.GetBytes(message);

                policy.Execute(() =>
                {
                    var properties          = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2; // persistent

                    _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id);

                    channel.BasicPublish(
                        exchange: BROKER_NAME,
                        routingKey: eventName,
                        mandatory: true,
                        basicProperties: properties,
                        body: body);
                });
            }
        }
        // Must return TRUE to indicate that the call was successfully processed
        public async Task <bool> Process(IntegrationEvent integrationEvent)
        {
            // We know we're only called when Calls are saved, so the ObjectID will be the Call ID
            int callID = integrationEvent.Object.ObjectID;

            var manifest = await api.GetCallQuestionnaireManifest(callID);

            var answers = await api.GetCallAnswers(callID);

            var call = await api.GetCall(callID);

            var target = await api.GetTarget(call.ProjectID.Value, call.TargetID.Value);

            // Identify the Picture Answers by the fact they will have a non-null Picture property
            var pictureAnswers = from a in answers where a.Picture != null select a;

            Console.WriteLine("The answers for Call ID {0}, visiting {1} were saved", callID, target.Name);

            foreach (var pictureAnswer in pictureAnswers)
            {
                // Figure out which Question and Item this Picture is for
                var question = (from q in manifest.Questions where q.QuestionID == pictureAnswer.QuestionID select q).Single();
                var item     = (from i in manifest.Items where i.ItemID == pictureAnswer.ItemID select i).SingleOrDefault() ?? new QuestionnaireItem {
                    Caption = "(No item)"
                };

                Console.WriteLine("Picture {0} is the answer to {1} for {2}", pictureAnswer.Picture, question.Caption, item.Caption);

                // Download the Picture's contents from the server
                var bytes = await api.GetPicture(pictureAnswer.Picture.Value);

                Console.WriteLine("Downloaded picture ({0}KB)", bytes.Length / 1024);

                // Construct a filename
                var filename = String.Format("{0}_{1}_{2}_{3}.jpg", target.Name, call.ActualStart.Value.ToShortDateString().Replace("/", "-"), question.Caption, item.Caption);

                // Save the Picture locally
                System.IO.File.WriteAllBytes(filename, bytes);
            }

            return(true);
        }
Пример #4
0
        protected override void Publish(Type eventType, IntegrationEvent eventDate)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }
            var policy = Policy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", eventDate.Id, $"{time.TotalSeconds:n1}", ex.Message);
            });

            var eventName = EventNameAttribute.GetNameOrDefault(eventType);

            _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", eventDate.Id, eventName);

            using (var channel = _persistentConnection.CreateModel())
            {
                _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", eventDate.Id);
                var message = JsonConvert.SerializeObject(eventDate);
                var body    = Encoding.UTF8.GetBytes(message).AsMemory();

                var model        = channel;
                var exchangeName = _eventBusRabbitMqOptions.RabbitMqPublishConfigure.GetExchangeName() ?? EXCHANGE_NAME;
                model.ExchangeDeclare(exchange: exchangeName, type: "direct", durable: true);
                policy.Execute(() =>
                {
                    var properties          = model.CreateBasicProperties();
                    properties.DeliveryMode = 2; // persistent

                    _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", eventDate.Id);

                    model.BasicPublish(
                        exchange: exchangeName,
                        routingKey: eventName,
                        mandatory: true,
                        basicProperties: properties,
                        body: body);
                });
            }
        }
Пример #5
0
        /// <summary>
        ///     used to publish event.
        ///     this will resilient by default thanks to polly.
        /// </summary>
        /// <param name="event">
        ///     Event to publish.
        /// </param>
        public void Publish(IntegrationEvent @event)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }

            var policy = Policy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .WaitAndRetry(
                _retryCount,
                retryAttempt =>
                TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                (ex, time) => { _logger.LogWarning(ex.ToString()); });

            using (var channel = _persistentConnection.CreateModel())
            {
                var eventName = @event.GetType().Name;

                // to guarantee exchange exists.
                // type direct means it will directly use bindingkey or routingkey instead of queue name.
                channel.ExchangeDeclare(BrokerName,
                                        "direct");

                var message = JsonConvert.SerializeObject(@event);
                var body    = Encoding.UTF8.GetBytes(message);

                policy.Execute(() =>
                {
                    // ReSharper disable once AccessToDisposedClosure
                    var properties          = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2; // persistent

                    // ReSharper disable once AccessToDisposedClosure
                    channel.BasicPublish(BrokerName,
                                         eventName,
                                         true,
                                         properties,
                                         body);
                });
            }
        }
        public static IApplicationBuilder UseEventBus(this IApplicationBuilder app)
        {
            using (var serviceScope = app.ApplicationServices
                                      .GetRequiredService <IServiceScopeFactory>()
                                      .CreateScope())
            {
                var busClient = serviceScope.ServiceProvider.GetService <IBusClient>();
                IntegrationEvent.Subscribe(busClient, message =>
                {
                    using (var mediatorServiceScope = app.ApplicationServices
                                                      .GetRequiredService <IServiceScopeFactory>()
                                                      .CreateScope())
                    {
                        return(mediatorServiceScope.ServiceProvider.GetService <IMediator>().Publish(message));
                    }
                });
            }

            return(app);
        }
Пример #7
0
        public void Publish(IntegrationEvent @event)
        {
            if (!_connection.IsConnected)
            {
                if (!_connection.Connect())
                {
                    _logger.LogWarning($"Couldn't publish event {@event.Id}. No available connection was found.");
                    return;
                }
            }

            using (var ch = _connection.CreateModel())
            {
                DeclareExchange(ch);
                var msg = JsonSerializer.SerializeToUtf8Bytes(@event, @event.GetType());
                ch.BasicPublish(_exchangeName,
                                routingKey: _subscriptionManager.GetEventKey(@event.GetType()),
                                body: msg);
            }
        }
Пример #8
0
        public async Task SaveEventAsync(IntegrationEvent integrationEvent)
        {
            Guard.Requires(integrationEvent, nameof(integrationEvent)).IsNotNull();

            if (await repository.CheckIfExistsByEventIdAsync(integrationEvent.EventId))
            {
                throw new Exception($"Internal error - event id: {integrationEvent.EventId} exists in event log");
            }

            await repository.CreateAsync(
                new IntegrationEventLog
            {
                State             = IntegrationEventState.ReadyToPublish,
                EventId           = integrationEvent.EventId,
                EventCreationDate = integrationEvent.EventCreationDate,
                EventType         = integrationEvent.GetType().FullName,
                EventBody         = JsonConvert.SerializeObject(integrationEvent)
            }
                );
        }
        public async Task MarkAsPublishedAsync(IntegrationEvent @event)
        {
            if (@event == null)
            {
                throw new ArgumentNullException(nameof(@event));
            }

            var eventLog = await EventLogContext.IntegrationEventLogs.SingleOrDefaultAsync(x => x.EventId == @event.Id);

            if (eventLog == null)
            {
                throw new EventLogNotFoundException(@event.Id);
            }

            eventLog.SetContent(@event); // Set content as published event has PublisherId set on publish.
            eventLog.TimesSent++;
            eventLog.StateId = (int)EventStateEnum.Published;
            EventLogContext.IntegrationEventLogs.Update(eventLog);
            await EventLogContext.SaveChangesAsync();
        }
Пример #10
0
        // METHODS
        #region Publish
        public void Publish(IntegrationEvent integrationEvent)
        {
            string eventName   = integrationEvent.GetType().Name.Replace(INTEGRATION_EVENT_SUFFIX, "");
            string jsonMessage = JsonConvert.SerializeObject(integrationEvent);

            byte[] body = Encoding.UTF8.GetBytes(jsonMessage);

            Message message = new Message
            {
                MessageId = Guid.NewGuid().ToString(),
                Body      = body,
                Label     = eventName,
            };

            _persisterConnection
            .CreateModel()
            .SendAsync(message)
            .GetAwaiter()
            .GetResult();
        }
Пример #11
0
        public void Post <T>(IntegrationEvent <T> @event) where T : class
        {
            var message     = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(@event));
            var messageType = new ServiceEvent(@event.Service, @event.Event);

            var basicProperties = _responseQueueChannelManager.GetChannel().CreateBasicProperties();

            basicProperties.ContentType = "application/json";
            basicProperties.MessageId   = JsonConvert.SerializeObject(messageType);
            basicProperties.Headers     = new Dictionary <string, object> {
                { "SeenBy", 0 }
            };

            _responseQueueChannelManager
            .GetChannel()
            .BasicPublish(exchange: _settings.ExchangeName,
                          routingKey: _settings.RoutingKey,
                          basicProperties: basicProperties,
                          body: message);
        }
        public async Task PublishAsync(IntegrationEvent integrationEvent)
        {
            var eventType   = integrationEvent.GetType().ToString();
            var jsonMessage = JsonConvert.SerializeObject(integrationEvent);
            var body        = Encoding.UTF8.GetBytes(jsonMessage);

            var message = new ServiceBusMessage(body)
            {
                MessageId             = integrationEvent.Id.ToString(),
                CorrelationId         = integrationEvent.CorrelationId ?? string.Empty,
                ApplicationProperties =
                {
                    ["event-type"] = eventType
                }
            };

            await _sender.SendMessageAsync(message);

            _logger.LogInformation($"Publish Event Successfully. Event ID: {integrationEvent.Id.ToString()}");
        }
Пример #13
0
        public Task PublishAsync(IntegrationEvent evt)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }

            var policy = Policy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .WaitAndRetry(_options.RetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                _logger.LogWarning(ex.ToString());
            });

            using (var channel = _persistentConnection.CreateModel())
            {
                var eventName = evt.GetType().Name;

                channel.ExchangeDeclare(exchange: _options.BrokerName,
                                        type: "direct",
                                        durable: _options.Durable,
                                        autoDelete: _options.AutoDelete);

                var message = JsonConvert.SerializeObject(evt);
                var body    = Encoding.UTF8.GetBytes(message);

                policy.Execute(() =>
                {
                    var properties          = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2; // persistent

                    channel.BasicPublish(exchange: _options.BrokerName,
                                         routingKey: eventName,
                                         mandatory: true,
                                         basicProperties: properties,
                                         body: body);
                });

                return(Task.CompletedTask);
            }
        }
Пример #14
0
        private async Task CreateAndAssignIntegrationEvents(string[] buyerClientIDs, string localBuyerClientID, string token)
        {
            var checkoutEvent = new IntegrationEvent()
            {
                ElevatedRoles           = new[] { ApiRole.FullAccess },
                ID                      = "HeadStartCheckout",
                EventType               = IntegrationEventType.OrderCheckout,
                Name                    = "HeadStart Checkout",
                CustomImplementationUrl = _settings.EnvironmentSettings.MiddlewareBaseUrl,
                HashKey                 = _settings.OrderCloudSettings.WebhookHashKey,
                ConfigData              = new
                {
                    ExcludePOProductsFromShipping = false,
                    ExcludePOProductsFromTax      = true,
                }
            };
            await _oc.IntegrationEvents.SaveAsync(checkoutEvent.ID, checkoutEvent, token);

            var localCheckoutEvent = new IntegrationEvent()
            {
                ElevatedRoles           = new[] { ApiRole.FullAccess },
                ID                      = "HeadStartCheckoutLOCAL",
                EventType               = IntegrationEventType.OrderCheckout,
                CustomImplementationUrl = "https://marketplaceteam.ngrok.io", // local webhook url
                Name                    = "HeadStart Checkout LOCAL",
                HashKey                 = _settings.OrderCloudSettings.WebhookHashKey,
                ConfigData              = new
                {
                    ExcludePOProductsFromShipping = false,
                    ExcludePOProductsFromTax      = true,
                }
            };
            await _oc.IntegrationEvents.SaveAsync(localCheckoutEvent.ID, localCheckoutEvent, token);

            await _oc.ApiClients.PatchAsync(localBuyerClientID, new PartialApiClient { OrderCheckoutIntegrationEventID = "HeadStartCheckoutLOCAL" }, token);

            await Throttler.RunAsync(buyerClientIDs, 500, 20, clientID =>
                                     _oc.ApiClients.PatchAsync(clientID, new PartialApiClient {
                OrderCheckoutIntegrationEventID = "HeadStartCheckout"
            }, token));
        }
Пример #15
0
        public async void InvokeAsync_CorrectSerializedMessageIsProvided_NewConsumerInstanceIsCreatedAndUseed()
        {
            //prepare
            var mockConsumer1 = new Mock <IConsumer <BookingCreated> >();
            var mockConsumer2 = new Mock <IConsumer <BookingCreated> >();

            int count = 0;
            Func <IConsumer <BookingCreated> > consumerFactory = () =>
            {
                if (count == 0)
                {
                    count = count + 1;
                    return(mockConsumer1.Object);
                }
                else
                {
                    return(mockConsumer2.Object);
                }
            };

            ISubscription subscription = new Subscription <BookingCreated>(consumerFactory, null);

            IntegrationEvent <BookingCreated> integrationEvent = new IntegrationEvent <BookingCreated>(new BookingCreated {
                BookingName = "bookingName"
            }, "bookingcreatedeventtype");

            string serializedMessage = JsonConvert.SerializeObject(integrationEvent);

            //act
            await subscription.InvokeAsync(serializedMessage);

            await subscription.InvokeAsync(serializedMessage);

            //check
            var expected = integrationEvent.AsSource().OfLikeness <IntegrationEvent <BookingCreated> >()
                           .With(a => a.Content)
                           .EqualsWhen((p, m) => { return(m.Content.BookingName == p.Content.BookingName); }).CreateProxy();

            mockConsumer1.Verify(x => x.ConsumeAsync(expected), Times.Once);
            mockConsumer2.Verify(x => x.ConsumeAsync(expected), Times.Once);
        }
Пример #16
0
        public void Publish(IntegrationEvent @event)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }

            var policy = RetryPolicy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                _logger.LogWarning(ex.ToString());
            });

            using (var channel = _persistentConnection.CreateModel())
            {
                var eventName = @event.GetType()
                                .Name;

                _logger.LogDebug($"Publishing event {eventName}");
                channel.ExchangeDeclare(exchange: BROKER_NAME,
                                        type: "direct");

                var message = JsonConvert.SerializeObject(@event);
                var body    = Encoding.UTF8.GetBytes(message);

                policy.Execute(() =>
                {
                    var properties          = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2; // persistent

                    channel.BasicPublish(exchange: BROKER_NAME,
                                         routingKey: eventName,
                                         mandatory: true,
                                         basicProperties: properties,
                                         body: body);

                    _logger.LogDebug($"Event {eventName} published. \nMessage: {message}");
                });
            }
        }
Пример #17
0
        public async Task Remove(CharityContext db, IIntegrationEventQueue queue)
        {
            if (!Id.HasValue)
            {
                throw new Exception("Please ensure that Id field has been populated before removing.");
            }
            var charity = await db.Charities.FilterDeletedItems().SingleOrDefaultAsync(x => x.Id == Id);

            if (charity == null)
            {
                throw new ArgumentException($"Donor with ID '{Id}' does not exist.", nameof(Id));
            }

            charity.IsDeleted = true;
            MapFromEntity(charity);
            await db.SaveChangesAsync();

            var integrationEvent = new IntegrationEvent <CharityEvent>(ServiceNames.CharityService.ToString(), EventNames.RemoveCharity.ToString(), ToCharityEvent());

            queue.Post(integrationEvent);
        }
        public Task SaveEventAsync(IntegrationEvent integrationEvent, IDbContextTransaction transaction)
        {
            try
            {
                if (transaction == null)
                {
                    throw new ArgumentNullException(nameof(transaction));
                }

                var eventLogEntry = new IntegrationEventLogEntry(integrationEvent, transaction.TransactionId);

                _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction());
                _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);

                return(_integrationEventLogContext.SaveChangesAsync());
            }
            catch (Exception ex)
            {
                throw;
            }
        }
Пример #19
0
        public async Task SaveEventAndChangesAsync(IntegrationEvent evt)
        {
            _logger.LogInformation("----- POSIntegrationEventService - Saving changes and integrationEvent: {IntegrationEventId}", evt.Id);
            await ResilientTransaction.New(_posContext, _logger).ExecuteAsync(async() =>
            {
                // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction
                try
                {
                    if (await _posContext.SaveChangesAsync() <= 0)
                    {
                        _logger.LogError("----- POSIntegrationEventService {0}", "Not can saved in Db");
                    }
                }
                catch (DbUpdateException e)
                {
                    _logger.LogError("***** Error In SaveChangesAsync Process {0}", e.Message);
                }

                await _eventLogService.SaveEventAsync(@event: evt, transaction: Guid.NewGuid());
            });
        }
        public async Task HandleAsync(OrderStatusChangedToAwaitingValidationIntegrationEvent @event)
        {
            var confirmedOrderStockItems = new List <ConfirmedOrderStockItem>();

            foreach (var orderStockItem in @event.OrderStockItems)
            {
                var catalogItem            = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
                var hasStock               = catalogItem.AvailableStock >= orderStockItem.Units;
                var confiredOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id, hasStock);

                confirmedOrderStockItems.Add(confiredOrderStockItem);
            }

            IntegrationEvent confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => c.HasStock)
                ? new OrderStockConfirmedIntegrationEvent(@event.OrderId) as IntegrationEvent
                : new OrderStockRejectedIntegrationEvent(@event.OrderId, confirmedOrderStockItems) as IntegrationEvent;

            await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent);

            await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent);
        }
        public async Task Remove(DonorContext db, IIntegrationEventQueue queue)
        {
            if (!Id.HasValue)
            {
                throw new Exception("Please ensure that Id field has been populated before removing.");
            }
            var transactionSource = await db.TransactionSources.FilterDeletedItems().SingleOrDefaultAsync(x => x.Id == Id);

            if (transactionSource == null)
            {
                throw new ArgumentException($"Transaction Source with ID '{Id}' does not exist.", nameof(Id));
            }

            transactionSource.IsDeleted = true;
            MapFromEntity(transactionSource);
            await db.SaveChangesAsync();

            var integrationEvent = new IntegrationEvent <DonorTransactionSourceEvent>(ServiceNames.DonorService.ToString(), EventNames.RemoveDonorTransactionSource.ToString(), ToDonorTransactionSourceEvent());

            queue.Post(integrationEvent);
        }
Пример #22
0
        public void Publish(IntegrationEvent @event)
        {
            var eventName = @event.GetType().Name;
            var factory   = new ConnectionFactory()
            {
                HostName = "localhost"
            };

            using (var connection = factory.CreateConnection())
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: BROKER_NAME,
                                            type: "direct");
                    string message = JsonConvert.SerializeObject(@event);
                    var    body    = Encoding.UTF8.GetBytes(message);
                    channel.BasicPublish(exchange: BROKER_NAME,
                                         routingKey: eventName,
                                         basicProperties: null,
                                         body: body);
                }
        }
Пример #23
0
        public async Task PublishThroughEventBusAsync(IntegrationEvent evt)
        {
            try
            {
                _logger.LogInformation(
                    "----- Publishing integration event: {IntegrationEventId_published} from {AppName} - ({@IntegrationEvent})",
                    evt.Id, evt.ProgramName, evt);

                await _eventLogService.MarkEventAsInProgressAsync(evt.Id);

                _eventBus.Publish(evt);
                await _eventLogService.MarkEventAsPublishedAsync(evt.Id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                                 "ERROR Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})",
                                 evt.Id, evt.ProgramName, evt);
                await _eventLogService.MarkEventAsFailedAsync(evt.Id);
            }
        }
Пример #24
0
        public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event)
        {
            //Check item stocks.
            List <ConfirmedStockItem> confirmedItems = new List <ConfirmedStockItem>();

            foreach (var item in @event.StockItems)
            {
                var product = await _catalogContext.CatalogItems.FindAsync(item.ProductId);

                confirmedItems.Add(
                    new ConfirmedStockItem
                {
                    ProductId = item.ProductId, HasStock = product.AvailableStock >= item.Units
                });
            }
            //If they are available publish an event accepting the order, if not reject the order

            //var resultEvent=confirmedItems.Any(c=>!c.HasStock) ?
            //  (IntegrationEvent)  new OrderStockRejectedIntegrationEvent(@event.OrderId) : new OrderStockConfirmedIntegrationEvent(@event.OrderId);

            IntegrationEvent resultEvent = null;

            if (confirmedItems.Any(c => !c.HasStock))
            {
                resultEvent = new OrderStockRejectedIntegrationEvent(@event.OrderId);
            }
            else
            {
                resultEvent = new OrderStockConfirmedIntegrationEvent(@event.OrderId);
                foreach (var item in @event.StockItems)
                {
                    var product = _catalogContext.CatalogItems.Find(item.ProductId);
                    product.AvailableStock -= item.Units;
                    _catalogContext.SaveChanges();
                }
            }
            //TODO: save event to eventLog
            //Thread.Sleep(2000);
            _eventBus.Publish(resultEvent);
        }
Пример #25
0
        private void Subscribe()
        {
            Task.Run(async() =>
            {
                var subscription = _client.DB().SubscribeStream(_stream, _cursor + 1);

                var retryPolicy = Policy
                                  .Handle <Exception>()
                                  .WaitAndRetryForeverAsync(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

                do
                {
                    await subscription.MoveNext().ConfigureAwait(false);

                    await retryPolicy.ExecuteAsync(async() =>
                    {
                        var eventJson    = Encoding.UTF8.GetString(subscription.Current.Value);
                        var metadataJson = Encoding.UTF8.GetString(subscription.Current.Header);
                        var metadata     = JsonConvert.DeserializeObject <Metadata>(metadataJson);

                        var integrationEvent = new IntegrationEvent(eventJson, metadata);

                        await DispatchToSubscribersAsync(integrationEvent);

                        // update cursor. This only works when the commands are idempotent
                        // eg. use ISourceId, or an Idempotent Producer
                        var cursorsMessageInput = new MessageInput
                        {
                            ID    = Guid.NewGuid().ToString(),
                            Type  = "cursors",
                            Value = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(_cursor))
                        };

                        await _client.DB().AppendStream(_cursorsStream, cursorsMessageInput);

                        _cursor = subscription.Current.Position;
                    });
                }while (true);
            });
        }
Пример #26
0
        protected override void Publish(Type eventType, IntegrationEvent eventDate)
        {
            var exceptions = new List <Exception>();
            var eventName  = EventNameAttribute.GetNameOrDefault(eventType);

            if (_subsManager.IncludeEventTypeForEventName(eventName))
            {
                var eventHandleTypes = _subsManager.TryGetEventHandlerTypes(eventName);
                foreach (var eventHandleType in eventHandleTypes)
                {
                    try
                    {
                        var handlerInstance = _eventHandlerFactory.GetHandler(eventHandleType);
                        var concreteType    = typeof(IIntegrationEventHandler <>).MakeGenericType(eventType);
                        var method          = concreteType.GetMethod("Handle");
                        if (method != null)
                        {
                            ((Task)method.Invoke(handlerInstance, new object[] { eventDate })).GetAwaiter().GetResult();
                        }
                    }
                    catch (TargetInvocationException ex)
                    {
                        exceptions.Add(ex.InnerException);
                    }
                    catch (Exception ex)
                    {
                        exceptions.Add(ex);
                    }
                }
            }
            else
            {
                _logger.LogWarning("No subscription for local memory event: {eventName}", eventName);
            }
            if (exceptions.Any())
            {
                throw new AggregateException(
                          "More than one error has occurred while triggering the event: " + eventType, exceptions);
            }
        }
        public async Task DeleteEventAndModuloContextChangesAsync(IntegrationEvent evt)
        {
            var strategy = _moduloContext.Database.CreateExecutionStrategy();
            await strategy.ExecuteAsync(async() => {
                using (var transaction = _moduloContext.Database.BeginTransaction())

                {
                    try
                    {
                        await _moduloContext.SaveChangesAsync();
                        await _eventLogService.SaveEventAsync(evt, _moduloContext.Database.CurrentTransaction.GetDbTransaction());
                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        var sqlException = ex.InnerException as System.Data.SqlClient.SqlException;
                        throw new Exception(sqlException.Number + "::" + sqlException.Message);
                    }
                }
            });
        }
Пример #28
0
        public void Publish(IntegrationEvent @event)
        {
            if (!_producerConnection.IsConnected)
            {
                _producerConnection.TryConnect();
            }
            var eventName = @event.GetType()
                            .Name;
            var body   = JsonConvert.SerializeObject(@event);
            var policy = RetryPolicy.Handle <KafkaException>()
                         .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                _logger.LogWarning(ex.ToString());
            });

            var conn = _producerConnection.CreateConnect() as Producer <Null, string>;

            policy.Execute(() =>
            {
                conn.ProduceAsync(eventName, null, body).GetAwaiter().GetResult();
            });
        }
Пример #29
0
        public void Publish(IntegrationEvent @event)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }

            var policy = Policy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                                       (ex, time) =>
            {
                Debug.WriteLine("Could not publish event");
            });

            var eventName = @event.GetType().Name;

            using (var channel = _persistentConnection.CreateModel())
            {
                channel.ExchangeDeclare(BROKER_NAME, "direct");

                var message = JsonConvert.SerializeObject(@event);

                var body = Encoding.UTF8.GetBytes(message);

                policy.Execute(() =>
                {
                    var properties          = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2;

                    channel.BasicPublish(
                        BROKER_NAME,
                        eventName,
                        true,
                        properties,
                        body);
                });
            }
        }
Пример #30
0
        public async Task SaveAsync(IntegrationEvent @event, string eventState)
        {
            var requestModel = new SaveEventApiRequestModel
            {
                EventId        = @event.Id,
                EventState     = eventState,
                EventName      = @event.EventName,
                Content        = JsonConvert.SerializeObject(@event),
                Username       = @event.Username,
                OrganisationId = @event.OrganisationId,
                Source         = @event.Source,
                IpAddress      = @event.IpAddress
            };

            var apiRequest = new ApiRequest <SaveEventApiRequestModel>
            {
                Data            = requestModel,
                EndpointAddress = $"{this.configuration["EventLoggingUrl"]}{ApiConstants.EventLoggingApiEndpoint}"
            };

            await this.apiClientService.PostAsync <ApiRequest <SaveEventApiRequestModel>, SaveEventApiRequestModel, BaseResponseModel>(apiRequest);
        }