Exemple #1
0
        private static void PublishEvent(ILogger logger, ISupportNotifier supportNotifier, IAsyncCollector <Message> messageAsyncCollector, Event eventModel)
        {
            var eventId = StaticSettings.EventId(MethodEventBase, (int)EventType.ChangeFeed);

            try
            {
                messageAsyncCollector.AddAsync(eventModel.ToMessage());
                logger.LogInformation(eventId, StaticSettings.Template, EventTrigger, eventModel.CorrelationId,
                                      EntityType, eventModel.EventId, PublishMessage.PublishedApplicationEvent.ToString());
            }
            catch (Exception ex)
            {
                logger.LogError(eventId, ex, StaticSettings.Template, EventTrigger, eventModel.CorrelationId,
                                EntityType, eventModel.EventId, ex.Message);
                // notify support of unknown exception
                supportNotifier.Notify($"WJ Unhandled Exception. Operation: {OperationName}, body: {JsonConvert.SerializeObject(eventModel)}, Message: {ex.Message}");
            }
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, Method, Route = Route)] HttpRequestMessage request,
            [CosmosDBTrigger(StaticSettings.Db, StaticSettings.Collection,
                             ConnectionStringSetting = StaticSettings.DbConnectionStringSetting)] IDocumentClient documentClient,
            ISupportNotifier supportNotifier,
            ILogger logger)
        {
            // get the correlation identifier
            request.Headers.TryGetValues(CorrelationIdHeaderKey, out var headerValues);
            var correlationId = headerValues == null?Guid.NewGuid().ToString() : headerValues.First();

            // ProcessStep.Deserialize - deserialize request content
            EventRequest eventRequest;
            string       payload = null;
            var          eventId = StaticSettings.EventId(MethodLevelEventId, (int)ProcessStep.Deserialize, ProcessStep.Deserialize.ToString());

            try
            {
                payload = await request.Content.ReadAsStringAsync();

                eventRequest = JsonConvert.DeserializeObject <EventRequest>(payload);
                logger.LogInformation(eventId, StaticSettings.Template, OperationName, correlationId);
            }
            catch (ArgumentNullException ex)
            {
                return(BadRequest(logger, eventId, correlationId, ex.Message));
            }
            catch (ArgumentException ex)
            {
                return(BadRequest(logger, eventId, correlationId, ex.Message));
            }
            catch (Exception e)
            {
                return(BadRequest(logger, supportNotifier, eventId, correlationId, e, payload));
            }

            // ProcessStep.Validation - validate the event request
            eventId = StaticSettings.EventId(MethodLevelEventId, (int)ProcessStep.Validation, ProcessStep.Validation.ToString());
            try
            {
                Validator.ValidateObject(eventRequest, new ValidationContext(eventRequest));
                logger.LogInformation(eventId, StaticSettings.Template, OperationName, correlationId);
            }
            catch (ValidationException)
            {
                return(BadRequest(logger, eventId, correlationId, "Invalid request content"));
            }
            catch (Exception e)
            {
                return(BadRequest(logger, supportNotifier, eventId, correlationId, e, payload));
            }


            var docUri = UriFactory.CreateDocumentCollectionUri(StaticSettings.Db, StaticSettings.Collection);

            // check for valid event sequence of the event in our event store
            // This may result in a stale sequence number, but we catch that in the "create document" step
            if (eventRequest.EventPurpose != EventPurpose.CreateAggregate)
            {
                eventId = StaticSettings.EventId(MethodLevelEventId, (int)ProcessStep.SequenceValidation);
                var sequenceValidated = true;
                try
                {
                    Policy.Handle <Exception>()
                    .WaitAndRetry(RetryCount, RetryDuration, (ex, c) =>
                                  logger.LogWarning(eventId, StaticSettings.Template, EventTrigger, correlationId, EntityType,
                                                    eventRequest.EventId, $"{ProcessStep.SequenceValidation.ToString()} retryTime: {c}, {ex.Message}"))
                    .Execute(ct =>
                    {
                        sequenceValidated = TryExecuteSequenceValidation(logger, eventId, correlationId,
                                                                         documentClient, docUri, eventRequest);
                    }, CancellationToken.None);
                }
                catch (Exception ex)
                {
                    return(BadRequest(logger, supportNotifier, eventId, correlationId, ProcessStep.SequenceValidation, ex,
                                      payload));
                }

                if (!sequenceValidated)
                {
                    return(BadRequest(logger, eventId, correlationId, ProcessStep.SequenceValidation, payload));
                }
            }

            // Create document
            // todo: implement retry
            eventId = StaticSettings.EventId(MethodLevelEventId, (int)ProcessStep.CreateDocument);
            try
            {
                await documentClient.CreateDocumentAsync(docUri, eventRequest);

                logger.LogInformation(eventId, StaticSettings.Template, EventTrigger, correlationId,
                                      EntityType, eventRequest.EventId, ProcessStep.CreateDocument.ToString());
                return(new OkResult());
            }
            // If either documentsFeedOrDatabaseLink or document is not set.
            catch (ArgumentNullException)
            {
                return(BadRequest(logger, eventId, correlationId, ProcessStep.CreateDocument, CreateDocumentMessage.DocumentNull.ToString()));
            }
            // Represents a consolidation of failures that occured during async processing.
            // Look within InnerExceptions to find the actual exception(s)
            catch (AggregateException)
            {
                // todo: log inner exceptions individually
                return(BadRequest(logger, eventId, correlationId, ProcessStep.CreateDocument, CreateDocumentMessage.Aggregate.ToString()));
            }
            catch (DocumentClientException ex)
            {
                return(BadRequest(logger, supportNotifier, eventId, correlationId, ex, payload));
            }
            catch (Exception ex)
            {
                return(BadRequest(logger, supportNotifier, eventId, correlationId, ProcessStep.CreateDocument, ex, payload));
            }
        }