public void TestCreateNoRecordsToProcess() { // Given A.CallTo(() => outboundSynchDataService.GetCreatedEntityCacheToProcess(entityName, batchSize)).Returns(new List <EntityCache>()); // When outboundSynchService.ProcessEntityCacheOperation(Operation.Create); // Then A.CallTo(() => logger.LogInformation($"Processing {Enum.GetName(typeof(EntityCacheMessageStatusReason), Operation.Create)} EntityCache for entity: {entityName}")).MustHaveHappened(); A.CallTo(() => logger.LogInformation($"Integration layer endpoint: {createServiceUrl}")).MustHaveHappened(); A.CallTo(() => logger.LogInformation($"Retrieving entity cache records to process with maximum batch size: {batchSize}")).MustHaveHappened(); A.CallTo(() => logger.LogInformation($"Found 0 records to be processed")).MustHaveHappened(); }
public void GetCreatedEntityCacheToProcessTest() { var expectedResult = 5; crmService = new TestCrmService(crmServiceHelper.GetCreatedCacheEntities); outboundSynchronisationDataService = new OutboundSynchronisationDataService(this.logger, this.crmService); var actualResult = outboundSynchronisationDataService.GetCreatedEntityCacheToProcess("contact", expectedResult); Assert.IsNotNull(actualResult); Assert.AreEqual(expectedResult, actualResult.Count); }
private void ProcessCreateEntityCache() { List <EntityCache> entityCacheCollection = outboundSynchronisationDataService.GetCreatedEntityCacheToProcess(configurationService.EntityName, configurationService.BatchSize); if (entityCacheCollection == null) { return; } var token = jwtService.CreateJwtToken(outboundSynchronisationDataService.GetSecretKey(), CreateTokenPayload()); var serviceUrl = configurationService.CreateServiceUrl; foreach (EntityCache entityCache in entityCacheCollection) { var entityCacheMessage = new EntityCacheMessage(); entityCacheMessage.Id = Guid.NewGuid(); entityCacheMessage.EntityCacheId = entityCache.Id; entityCacheMessage.Name = entityCacheMessage.Id.ToString(); var entityCacheMessageId = CreateEntityCacheMessage(entityCacheMessage); UpdateEntityCacheStatus(entityCache.Id, Status.Active, EntityCacheStatusReason.InProgress); try { var entityModel = JsonConvert.DeserializeObject <EntityModel>(entityCache.Data); var requestPayload = requestPayloadCreator.GetPayload(entityModel); var response = jwtService.SendHttpRequest(HttpMethod.Post, serviceUrl, token, requestPayload, entityCacheMessageId.ToString()); if (IsResponseSuccessful(response.StatusCode)) { UpdateEntityCacheMessageStatus(entityCacheMessageId, Status.Inactive, EntityCacheMessageStatusReason.SuccessfullySentToIL); } else { var notes = AppendNote(entityCacheMessage.Notes, response.StatusCode, response.Content); UpdateEntityCacheMessageStatus(entityCacheMessageId, Status.Inactive, EntityCacheMessageStatusReason.Failed, notes); } } catch (Exception e) { logger.LogError(e.ToString()); var notes = AppendNote(entityCacheMessage.Notes, HttpStatusCode.InternalServerError, "Internal server error."); UpdateEntityCacheMessageStatus(entityCacheMessageId, Status.Inactive, EntityCacheMessageStatusReason.Failed, notes); } } }
public void ProcessEntityCacheOperation(Operation operation) { // base initialize var entityName = configurationService.EntityName; var batchSize = configurationService.BatchSize; var serviceUrl = operation == Operation.Create ? configurationService.CreateServiceUrl : configurationService.UpdateServiceUrl; HttpMethod httpMethod = operation == Operation.Create ? HttpMethod.Post : HttpMethod.Patch; IRequestPayloadCreator payloadCreator = operation == Operation.Create ? createRequestPayloadCreator : updateRequestPayloadCreator; logger.LogInformation($"Processing {Enum.GetName(typeof(EntityCacheMessageStatusReason), operation)} EntityCache for entity: {entityName}"); logger.LogInformation($"Integration layer endpoint: {serviceUrl}"); logger.LogInformation($"Retrieving entity cache records to process with maximum batch size: {batchSize}"); // retrieve records var entityCacheCollection = operation == Operation.Create ? outboundSynchronisationDataService.GetCreatedEntityCacheToProcess(entityName, batchSize) : outboundSynchronisationDataService.GetUpdatedEntityCacheToProcess(entityName, batchSize); logger.LogInformation($"Found {entityCacheCollection?.Count} records to be processed"); if (entityCacheCollection == null || entityCacheCollection.Count == 0) { return; } // prepare jwt token var token = jwtService.CreateJwtToken(outboundSynchronisationDataService.GetSecretKey(), CreateTokenPayload()); foreach (EntityCache entityCache in entityCacheCollection) { // don't do call if succeeded max retries (ex if request from integration layer to CRM failed and it was max retried) if (entityCache.StatusReason == EntityCacheStatusReason.InProgress && entityCache.RequestsCount > MaxRetries) { logger.LogInformation($"EntityCache record: {entityCache.Name} reached maximum retries {MaxRetries} of calls to integration layer and will be failed"); outboundSynchronisationDataService.UpdateEntityCacheStatus(entityCache.Id, Status.Inactive, EntityCacheStatusReason.Failed); continue; } // create entity cache message var entityCacheMessage = new EntityCacheMessage { EntityCacheId = entityCache.Id, Name = string.Format(EntityCacheMessageName, entityCache.RecordId, entityCache.Id) }; var entityCacheMessageId = outboundSynchronisationDataService.CreateEntityCacheMessage(entityCacheMessage); logger.LogInformation($"Processing EntityCache/EntityCacheMessage : {entityCache.Name}/{entityCacheMessage.Name}"); // update entity cache outboundSynchronisationDataService.UpdateEntityCacheStatus(entityCache.Id, Status.Active, EntityCacheStatusReason.InProgress); // calculate next retry time in case if failure var eligibleRetryTime = GetEligibleRetryTime(RetrySchedule, entityCache.RequestsCount); string note = null; var statusReason = EntityCacheMessageStatusReason.Failed; var success = false; try { var entityModel = entityModelDeserializer.Deserialize(entityCache.Data); var requestPayload = payloadCreator.GetPayload(entityModel); var url = operation == Operation.Update ? GetUpdateUrl(serviceUrl, entityCache.SourceSystemId) : serviceUrl; var response = jwtService.SendHttpRequest(httpMethod, url, token, requestPayload, entityCacheMessageId.ToString()); success = IsResponseSuccessful(response.StatusCode); statusReason = success ? EntityCacheMessageStatusReason.SuccessfullySentToIL : EntityCacheMessageStatusReason.Failed; note = success ? null : AppendNote(entityCacheMessage.Notes, response.StatusCode, response.Content); logger.LogInformation($"Executed call to integration layer. EntityCacheMessage Status Reason: {Enum.GetName(typeof(EntityCacheMessageStatusReason), statusReason)}"); } catch (Exception e) { note = AppendNote(entityCacheMessage.Notes, HttpStatusCode.InternalServerError, "Internal server error."); logger.LogError(e.ToString()); logger.LogInformation($"Exception thrown while executing call to service layer. EntityCacheMessage Status Reason: {Enum.GetName(typeof(EntityCacheMessageStatusReason), statusReason)}"); } finally { // do crash in case of connectivity problems to CRM outboundSynchronisationDataService.UpdateEntityCacheSendToIntegrationLayerStatus(entityCache.Id, success, success ? (DateTime?)null : eligibleRetryTime); outboundSynchronisationDataService.UpdateEntityCacheMessageStatus(entityCacheMessageId, Status.Inactive, statusReason, success ? null : note); } } }