public void TestInitialize() { logger = A.Fake <ILogger>(); jwtService = A.Fake <IJwtService>(); outboundSynchDataService = A.Fake <IOutboundSynchronisationDataService>(); createRequestPayloadCreator = A.Fake <IRequestPayloadCreator>(); updateRequestPayloadCreator = A.Fake <IRequestPayloadCreator>(); outboundSyncConfigurationService = A.Fake <IOutboundSyncConfigurationService>(); entityModelDeserializer = A.Fake <IEntityModelDeserializer>(); A.CallTo(() => outboundSyncConfigurationService.BatchSize).Returns(batchSize); A.CallTo(() => outboundSyncConfigurationService.EntityName).Returns(entityName); A.CallTo(() => outboundSynchDataService.GetSecretKey()).Returns(secretKey); A.CallTo(() => outboundSynchDataService.GetRetries()).Returns(retries); A.CallTo(() => outboundSyncConfigurationService.CreateServiceUrl).Returns(createServiceUrl); A.CallTo(() => outboundSyncConfigurationService.UpdateServiceUrl).Returns(updateServiceUrl); A.CallTo(() => entityModelDeserializer.Deserialize(A <string> ._)).Returns( new Crm.Common.IntegrationLayer.Model.EntityModel { Fields = new List <Crm.Common.IntegrationLayer.Model.Field> { new Crm.Common.IntegrationLayer.Model.Field { Name = Tc.Crm.Common.Constants.Attributes.Customer.FirstName, Type = Crm.Common.IntegrationLayer.Model.FieldType.String, Value = "Name" } } }); outboundSynchService = new OutboundSynchronisationService( logger, outboundSynchDataService, jwtService, createRequestPayloadCreator, updateRequestPayloadCreator, outboundSyncConfigurationService, entityModelDeserializer); }
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); } } }