package com.gpc.tams.sync.customer; import java.io.File; import java.sql.Timestamp; import java.util.*; import javax.annotation.PostConstruct; import com.gpc.tams.model.customer.domain.CustomerRecord; import com.gpc.tams.repository.reference.DbRelease; import com.gpc.tams.sync.customer.dataverifier.CustomerDomainDataService; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.CollectionUtils; import com.gpc.tams.config.ServerConfiguration3; import com.gpc.tams.model.customer.domain.CustomerDomainFeedDetails; import com.gpc.tams.repository.common.DataProcessedRegister; import com.gpc.tams.repository.common.DistributionCenter; import com.gpc.tams.repository.common.StoreProfile; import com.gpc.tams.repository.communication.CommunicationUrl; import com.gpc.tams.repository.customer.Customer; import com.gpc.tams.repository.customer.CustomerChangeQueDao; import com.gpc.tams.repository.customer.CustomerChangeQueue; import com.gpc.tams.repository.rowmapper.CustomerChangeMapper; import com.gpc.tams.repository.rowmapper.function.GetNextAvailableQueueId; import com.gpc.tams.sync.AbstractSynchronizer; import com.gpc.tams.sync.azure.monitor.AzureLogger; import com.gpc.tams.sync.azure.monitor.LogType; import com.gpc.tams.sync.customer.databuilder.CustomerDomainDataBuilder; import com.gpc.tams.util.communication.DomainOAuthParameters; import com.gpc.tams.util.sync.SyncUtil; public class CustomerSynchronizer extends AbstractSynchronizer { private static final Logger loggerCustomerDomainFeed = Logger.getLogger(CustomerSynchronizer.class); public static final String CUSTOMER_DOMAIN_FEED_SERVICE_KEY_FILE = "CUSTOMER_DOMAIN_FEED_SERVICE_KEY_FILE"; private static final String CUSTOMER_DOMAIN_FEED_SERVICE_URL = "CUSTOMER_DOMAIN_FEED_SERVICE_URL"; private static final String CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL = "CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL"; private static final String CUSTOMER_DOMAIN_FEED_MAX_TRIES = "CUSTOMER_DOMAIN_FEED_MAX_TRIES"; private static final String CUSTOMER_DOMAIN_FEED_SERVICE_TEST_MODE = "CUSTOMER_DOMAIN_FEED_SERVICE_TEST_MODE"; private static final String CUSTOMER_DOMAIN_FEED_TARGET_AUDIENCE = "CUSTOMER_DOMAIN_FEED_TARGET_AUDIENCE"; private static final String CUSTOMER_DOMAIN_FEED_SCORECARD_URL = "CUSTOMER_DOMAIN_FEED_SCORECARD_URL"; private static final String CUSTOMER_DOMAIN_FEED_SCORECARD_TARGET_AUDIENCE = "CUSTOMER_DOMAIN_FEED_SCORECARD_TARGET_AUDIENCE"; private static final String CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL = "CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL"; private static final Long CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL_DEFAULT = 60000L; private static final int CUSTOMER_DOMAIN_FEED_MAX_TRIES_DEFAULT = 1; private static final Long CUSTOMER_DOMAIN_FEED_RETRY_INTERVAL = 1800000L; // 30 MINUTES private static volatile long nextCustomerDomainFeedRetryTime = 0; private static final Long CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL_DEFAULT = 2100000L; // 35 MINUTES private static volatile long nextCustomerDomainFeedScorecardTime = 0; private static boolean domainFeedFeatureEnabled; private static Boolean domainFeedFeatureEnabledStatusChanged = null; private static String tamsVersion = null; private String storeNumber; private CommunicationUrl customerDomainFeedServerURL; private Long customerDomainFeedWaitInterval; private Integer customerDomainFeedMaxTries; private DomainOAuthParameters domainOAuthParameters; private DomainOAuthParameters domainScoreCardOAuthParameters; private CommunicationUrl customerDomainScoreCardServerURL; private Long customerDomainFeedScorecardInterval; private int location; @Value("${CUSTOMER_SYNC_QUEUE}") private String queue; @Value("${CUSTOMER_SYNC_DELAY}") private String delay; @Value("${CUSTOMER_SYNC_LIMIT}") private String limit; @Autowired private ServerConfiguration3 serverConfig; @Autowired private CustomerDomainDataBuilder customerDomainDataBuilder; @Autowired private CustomerDomainDataService customerDomainDataService; @Autowired protected CustomerChangeQueDao customerChangeQueDao; private StoreProfile storeProfile; private DistributionCenter distributionCenter; /** * Does all the preparatory work. * 1. Load the tableId for queue. *

* If anything goes wrong, we are not allowing server to start so that support get * involved quickly and the problem can be corrected sooner rather than later. */ @PostConstruct public void init() { try { tableId = SyncUtil.getQueueTableId(queue, referenceDAO.loadQueueTables()); storeProfile = storeProfileDAO.find(); distributionCenter = distCenterDAO .findDistributionCenterByNapaAcctDcCode(storeProfile.getNapaAcctDcCode()); if (StringUtils.isEmpty(tamsVersion)) { DbRelease dbRelease = referenceDAO.loadDbRelease(); if (dbRelease != null) { tamsVersion = "DB_RELEASE : " + dbRelease.getReleaseNum(); } } } catch (Exception exception) { context.logError(exception, ""); } } @Override protected long getDelay() { return Long.parseLong(delay); } /* (non-Javadoc) * @see com.gpc.tams.sync.AbstractSynchronizer#getServiceKey() */ @Override protected String getServiceKey() { return "customerFeed"; } /* (non-Javadoc) * @see com.gpc.tams.sync.AbstractSynchronizer#getRetry() */ @Override public int getRetry() { /* * No point of having a retry here. Because this service is going to run very frequently. */ return 0; } /* * (non-Javadoc) * @see com.gpc.tams.sync.AbstractSynchronizer#checkForUpdates(com.gpc.tams.repository.common.DataProcessedRegister) */ @Override protected RecordSynchronizationData checkForUpdates(final DataProcessedRegister processedRegister) { location = storeProfile.getLocation(); storeNumber = storeProfile.getStoreNum(); domainFeedFeatureEnabled = storeProfile.isSendCustomerDomain(); /* * Check if store is allowed to send feed. If not, just return back by printing a debug statement. */ if (!storeProfile.isSendCustomerDomain()) { context.logDebug("SEND_CUSTOMER_DOMAIN feature is disabled. Not sending to customer domain feed."); return null; } final int lastProcessedId = processedRegister == null ? (customerChangeQueueDAO.findMinimumChangeQueueId(tableId, location) - 1) : processedRegister.getLastPointerProcessed(); final int maxChangeQueueId = customerChangeQueueDAO.findMaximumChangeQueueId(tableId, location); int feedSize = Integer.parseInt(limit); if (lastProcessedId == -1 && maxChangeQueueId == 0) { context.logDebug("** No Data found for Customer Feed **"); doRetryCustomerToDomainFeed(); return null; } /* * We got the last processed id. Now we want to get the set from next record onwards. * We add 1 to lastProcessedId and query database. */ List eligibleData = databaseOperationsService.getNextBatchOfCustomers( lastProcessedId + 1, feedSize, location, CustomerChangeMapper.INSTANCE); if (CollectionUtils.isEmpty(eligibleData)) { if (lastProcessedId < maxChangeQueueId) { final int nextAvailableQueueId = databaseOperationsService.getNextAvailableQueueId(tableId, feedSize, GetNextAvailableQueueId.INSTANCE).intValue(); eligibleData = databaseOperationsService.getNextBatchOfCustomers( nextAvailableQueueId, feedSize, location, CustomerChangeMapper.INSTANCE); } if (CollectionUtils.isEmpty(eligibleData)) { context.logDebug("** No Data found for Customer Feed **"); doRetryCustomerToDomainFeed(); return null; } } context.logDebug("*************Customer Data found***************"); /* * We want to control the size of feed from outside. * Query at this point pull 200 records at a time. */ if (feedSize == 0 || feedSize > eligibleData.size()) { feedSize = eligibleData.size(); } /* * Records are ordered by CUSTOMER_CHANGE_QUEUE.ID. We take the first record * as the least and last record as the max. */ final int minQueueId = eligibleData.get(0).getCustomerChangeQueue().getId(); final int maxQueueId = eligibleData.get(feedSize - 1).getCustomerChangeQueue().getId(); context.logDebug("CustomerSynchronizer: minQueueId= " + minQueueId); context.logDebug("CustomerSynchronizer: maxQueueId= " + maxQueueId); /* * Split the records into two sets. One for deleted records and one for the * inserted/updated records. */ final List availableData = new ArrayList(); final List deletedData = new ArrayList(); for (int index = 0; index < feedSize; index++) { final Customer customerData = eligibleData.get(index); if (customerData.getId() != -1) { availableData.add(customerData); } else { deletedData.add(customerData); } } final RecordSynchronizationData recordSynchronizationData = new RecordSynchronizationData(); recordSynchronizationData.setModifiedRecords(availableData); recordSynchronizationData.setDeletedRecords(deletedData); recordSynchronizationData.setFirstPointer(minQueueId); recordSynchronizationData.setLastPointer(maxQueueId); return recordSynchronizationData; } /* * (non-Javadoc) * @see com.gpc.tams.sync.AbstractSynchronizer#sendModifiedRecords(java.util.List, java.sql.Timestamp) */ @Override protected void sendModifiedRecords(List modifiedCustomers, final Timestamp processedDate) { context.logDebug("sendModifiedRecords: processedDate= " + processedDate); storeNumber = storeProfile.getStoreNum(); location = storeProfile.getLocation(); List customerDomainFeedDetailsList = new ArrayList<>(); CustomerDomainFeedDetails customerDomainFeedDetails = null; CustomerChangeQueue customerChangeQueue = null; for (final Customer customerDataRecord : modifiedCustomers) { try { customerChangeQueue = customerDataRecord.getCustomerChangeQueue(); if (customerChangeQueue == null) { // invalid customerChangeQueue context.logError("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Invalid Customer Change Queue : null "); continue; } customerDomainDataBuilder.initialize(customerChangeQueue, storeProfile, distributionCenter); customerDomainFeedDetails = customerDomainDataBuilder .buildCustomerDomainPayloadData(customerDataRecord); customerDomainFeedDetails.setDeletedValue(customerChangeQueue.getDeletedValue()); Attributes attributes = getAttributes(customerChangeQueue, customerDomainFeedDetails); if (attributes != null) { if (attributes.getCustomerDomainEventType().equals(CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT)) { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Invalid CustomerDomainEventType : " + CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT); context.logError("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Invalid CustomerDomainEventType : " + CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT); continue; } customerDomainFeedDetails.setCustomerId(customerChangeQueue.getCustomerId()); customerDomainFeedDetails.setChangeQueueId(customerChangeQueue.getId()); customerDomainFeedDetails.setAction(customerChangeQueue.getAction()); customerDomainFeedDetails.setTriggerSource(customerChangeQueue.getTriggerSource()); customerDomainFeedDetails.setDeletedValue(customerChangeQueue.getDeletedValue()); customerDomainFeedDetails.setAttributes(attributes); customerDomainFeedDetailsList.add(customerDomainFeedDetails); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Invalid Attributes!!"); context.logError("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Invalid Attributes!!"); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Exception!!", exception); context.logError("CustomerSynchronizer::sendModifiedRecords - NOT SENT, Exception!!", exception); } } if (!CollectionUtils.isEmpty(customerDomainFeedDetailsList)) { context.logDebug("CustomerSynchronizer::sendModifiedRecords Number of customers = " + customerDomainFeedDetailsList.size()); /* Send Customer(s) request(s) to customer domain feed */ sendCustomersToDomainFeed(customerDomainFeedDetailsList, storeNumber); } } private Attributes getAttributes(CustomerChangeQueue customerChangeQueue, CustomerDomainFeedDetails customerDomainFeedDetails) { Attributes attributes = null; CustomerDomainEventType customerDomainEventType = null; if (customerChangeQueue != null && customerDomainFeedDetails != null) { String action = customerChangeQueue.getAction().trim(); String triggerSource = customerChangeQueue.getTriggerSource(); Previous previous = customerDomainFeedDetails.getPrevious(); switch (triggerSource.toUpperCase().trim()) { case "CUSTOMER": if ("C".equalsIgnoreCase(action) || "I".equalsIgnoreCase(action)) { customerDomainEventType = CustomerDomainEventType.CUSTOMER_PROFILE_CREATE; break; } case "AR_PROFILE": case "CUSTOMER_AR": case "CUSTOMER_BLANKET_PO": case "CUSTOMER_CONTACT": case "CUSTOMER_DELIVERY": case "CUSTOMER_STATEMENT_ADDRESS": case "COMMUNICATION_DIRECTORY": case "CUSTOMER_CERTIFICATION": case "STORE_PROFILE": { switch (action.toUpperCase()) { case "C": case "D": case "I": case "U": default: if (customerDomainFeedDetails.getMainArStoreNumberChange() != null) { customerDomainEventType = CustomerDomainEventType.MAIN_AR_STORE_NUMBER_CHANGE; if (previous == null) { customerDomainEventType = CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT; loggerCustomerDomainFeed.error("CustomerSynchronizer::getAttributes -Invalid CustomerDomainFeedDetails for MAIN_AR_STORE_NUMBER_CHANGE!!"); context.logError("CustomerSynchronizer::getAttributes - Invalid CustomerDomainFeedDetails for MAIN_AR_STORE_NUMBER_CHANGE!!"); } break; } else if (customerDomainFeedDetails.getStoreNumberChange() != null) { customerDomainEventType = CustomerDomainEventType.STORE_NUMBER_CHANGE; if (previous == null) { customerDomainEventType = CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT; loggerCustomerDomainFeed.error("CustomerSynchronizer::getAttributes -Invalid CustomerDomainFeedDetails for STORE_NUMBER_CHANGE!!"); context.logError("CustomerSynchronizer::getAttributes - Invalid CustomerDomainFeedDetails for STORE_NUMBER_CHANGE!!"); } break; } else if (customerDomainFeedDetails.getDcNumberChange() != null) { customerDomainEventType = CustomerDomainEventType.DC_NUMBER_CHANGE; if (previous == null) { customerDomainEventType = CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT; loggerCustomerDomainFeed.error("CustomerSynchronizer::getAttributes -Invalid CustomerDomainFeedDetails for DC_NUMBER_CHANGE!!"); context.logError("CustomerSynchronizer::getAttributes - Invalid CustomerDomainFeedDetails for DC_NUMBER_CHANGE!!"); } else { Integer napaAcctDCCode = previous.getNapaAcctDCCode(); if (napaAcctDCCode != null) { DistributionCenter thisDistributionCenter = distCenterDAO.findDistributionCenterByNapaAcctDcCode(napaAcctDCCode); if (thisDistributionCenter != null) { previous.setAlphaDCCode(thisDistributionCenter.getAlphaDcCode()); } } } break; } if ((previous != null && previous.getEndDate() != null && previous.getDeleted() == null)) { customerDomainEventType = CustomerDomainEventType.ACCOUNT_RENUMBERING; } else if (previous != null && previous.getDeleted() != null && previous.getDeleted() == Boolean.TRUE) { customerDomainEventType = CustomerDomainEventType.CUSTOMER_PROFILE_DELETE; } else { customerDomainEventType = CustomerDomainEventType.CUSTOMER_PROFILE_UPDATE; } } break; } default: customerDomainEventType = CustomerDomainEventType.UNKNOWN_TRIGGER_ACTION_EVENT; } attributes = new Attributes(customerDomainEventType, triggerSource, action, customerChangeQueue.getRetryCount() ,storeNumber); customerDomainFeedDetails.setScoreCardCount(customerChangeQueue.getScoreCardCount()); customerDomainFeedDetails.setRetryCount(customerChangeQueue.getRetryCount()); customerDomainFeedDetails.setCustomerDomainEventType(customerDomainEventType); return attributes; } if (customerDomainFeedDetails == null) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getAttributes - Missing or invalid CustomerDomainFeedDetails!!"); context.logError("CustomerSynchronizer::getAttributes - Missing or invalid CustomerDomainFeedDetails!!"); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getAttributes - Missing or invalid CustomerChangeQueue!!"); context.logError("CustomerSynchronizer::getAttributes - Missing or invalid CustomerChangeQueue!!"); } return attributes; } /* * (non-Javadoc) * @see com.gpc.tams.sync.AbstractSynchronizer#sendDeletedRecords(java.util.List, java.sql.Timestamp) */ @Override protected void sendDeletedRecords(List deletedData, final Timestamp processedDate) { sendModifiedRecords(deletedData, processedDate); } private void sendCustomersToDomainFeed(List customerDomainFeedDetailsList, String storeNumber) { if (isCustomerDomainFeedFeatureEnabled()) { if (!CollectionUtils.isEmpty(customerDomainFeedDetailsList)) { try { CommunicationUrl communicationUrl = getCustomerDomainFeedUrl(); DomainOAuthParameters domainOAuthParameters = getDomainOAuthParameters(); if (communicationUrl != null && domainOAuthParameters != null) { loggerCustomerDomainFeed.debug("CustomerSynchronizer::sendCustomersToDomainFeed: Sending modified customer(s) to customer domain feed"); Thread thread = new Thread(new CustomerDomainFeedRequestWorker(customerDomainFeedDetailsList, communicationUrl, domainOAuthParameters, getCustomerDomainFeedWaitInterval(), getCustomerDomainFeedMaxTries(), storeNumber, customerChangeQueDao, location)); thread.start(); } else if (communicationUrl == null) { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendCustomersToDomainFeed - Missing or invalid communicationUrl parameters"); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendCustomersToDomainFeed - Missing or invalid domainOAuthParameters parameters"); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendCustomersToDomainFeed - Exception thread creation ", exception); } } else if (CollectionUtils.isEmpty(customerDomainFeedDetailsList)) { loggerCustomerDomainFeed.error("CustomerSynchronizer::sendCustomersToDomainFeed - Invalid or empty CustomerDomainFeedDetails object"); } } } private Long getCustomerDomainFeedWaitInterval() { if (customerDomainFeedWaitInterval == null) { try { String value = serverConfig.getString(CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL); customerDomainFeedWaitInterval = !StringUtils.isEmpty(value) ? Long.valueOf(value) : CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL_DEFAULT; if (customerDomainFeedWaitInterval <= 0) { customerDomainFeedWaitInterval = CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL_DEFAULT; loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedWaitInterval - Invalid value setting to default value " + CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL_DEFAULT); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedWaitInterval - Exception setting to default value " + CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL_DEFAULT, exception); customerDomainFeedWaitInterval = CUSTOMER_DOMAIN_FEED_WAIT_INTERVAL_DEFAULT; } } return customerDomainFeedWaitInterval; } private Integer getCustomerDomainFeedMaxTries() { if (customerDomainFeedMaxTries == null) { try { String value = serverConfig.getString(CUSTOMER_DOMAIN_FEED_MAX_TRIES); customerDomainFeedMaxTries = !StringUtils.isEmpty(value) ? Integer.valueOf(value) : CUSTOMER_DOMAIN_FEED_MAX_TRIES_DEFAULT; if (customerDomainFeedMaxTries <= 0) { customerDomainFeedMaxTries = CUSTOMER_DOMAIN_FEED_MAX_TRIES_DEFAULT; loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedMaxTries - Invalid value setting to default value " + CUSTOMER_DOMAIN_FEED_MAX_TRIES_DEFAULT); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedMaxTries - Exception setting to default value " + CUSTOMER_DOMAIN_FEED_MAX_TRIES_DEFAULT, exception); customerDomainFeedMaxTries = CUSTOMER_DOMAIN_FEED_MAX_TRIES_DEFAULT; } } return customerDomainFeedMaxTries; } private Long getCustomerDomainFeedScorecardInterval() { if (customerDomainFeedScorecardInterval == null) { try { String value = serverConfig.getString(CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL); customerDomainFeedScorecardInterval = !StringUtils.isEmpty(value) ? Long.valueOf(value) : CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL_DEFAULT; if (customerDomainFeedScorecardInterval <= 0) { customerDomainFeedScorecardInterval = CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL_DEFAULT; loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedScorecardInterval - Invalid value setting to default value 30 minutes " + CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL_DEFAULT); } else if (customerDomainFeedScorecardInterval < 300000L) { customerDomainFeedScorecardInterval = 300000L; loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedScorecardInterval - Invalid value setting to minimum value 5 minutes (300000)"); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedWaitInterval - Exception setting to default value " + CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL_DEFAULT, exception); customerDomainFeedScorecardInterval = CUSTOMER_DOMAIN_FEED_SCORECARD_INTERVAL_DEFAULT; } } return customerDomainFeedScorecardInterval; } private CommunicationUrl getCustomerDomainFeedUrl() { if (isCustomerDomainFeedFeatureEnabled() && customerDomainFeedServerURL == null) { try { customerDomainFeedServerURL = communicationURLDAO.find(serverConfig.getString(CUSTOMER_DOMAIN_FEED_SERVICE_URL)); } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedUrl - Missing customer domain feed URL", exception); } } return customerDomainFeedServerURL; } private DomainOAuthParameters getDomainOAuthParameters() { if (domainOAuthParameters == null) { try { CommunicationUrl communicationUrl = getCustomerDomainFeedUrl(); String domainUrl = communicationUrl != null ? communicationUrl.getUrl() : null; String gcpServiceKey = serverConfig.getString(CUSTOMER_DOMAIN_FEED_SERVICE_KEY_FILE); String customerDomainFeedServiceTestMode = serverConfig.getString(CUSTOMER_DOMAIN_FEED_SERVICE_TEST_MODE); String customerDomainFeedServiceAudience = serverConfig.getString(CUSTOMER_DOMAIN_FEED_TARGET_AUDIENCE); boolean testMode = (customerDomainFeedServiceTestMode != null && (customerDomainFeedServiceTestMode.equalsIgnoreCase("true") || customerDomainFeedServiceTestMode.equals("1") || customerDomainFeedServiceTestMode.equalsIgnoreCase("y"))); if (!StringUtils.isEmpty(domainUrl) && !StringUtils.isEmpty(gcpServiceKey) && !StringUtils.isEmpty(customerDomainFeedServiceAudience)) { if (communicationUrl != null) { if (!StringUtils.isEmpty(gcpServiceKey)) { File fileServiceKey = new File(gcpServiceKey); if (fileServiceKey != null && fileServiceKey.exists() && fileServiceKey.isFile() && fileServiceKey.canRead()) { domainOAuthParameters = new DomainOAuthParameters(fileServiceKey); domainOAuthParameters.setTestMode(testMode); domainOAuthParameters.setTargetAudience(customerDomainFeedServiceAudience); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getDomainOAuthParameters - GCP service key missing or invalid permissions!!!"); AzureLogger.write(LogType.Feature.CustomerDomain, storeNumber, LogType.Status.FAILURE, 418, "CustomerSynchronizer.getDomainOAuthParameters - GCP service key missing or invalid permissions", null, null, null); } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getDomainOAuthParameters - GCP service key missing"); AzureLogger.write(LogType.Feature.CustomerDomain, storeNumber, LogType.Status.FAILURE, 418, "CustomerSynchronizer.getDomainOAuthParameters - GCP service key missing", null, null, null); } } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getDomainOAuthParameters - Missing or invalid parameters"); AzureLogger.write(LogType.Feature.CustomerDomain, storeNumber, LogType.Status.FAILURE, 418, "CustomerSynchronizer.getDomainOAuthParameters - Missing or invalid parameters", null, null, null); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getDomainOAuthParameters - Exception - " + exception); } } return domainOAuthParameters; } private DomainOAuthParameters getScoreCardDomainOAuthParameters() { if (domainScoreCardOAuthParameters == null) { try { CommunicationUrl communicationUrl = getCustomerDomainScoreCardUrl(); String scoreCardUrl = communicationUrl != null ? communicationUrl.getUrl() : null; String gcpServiceKey = serverConfig.getString(CUSTOMER_DOMAIN_FEED_SERVICE_KEY_FILE); String customerDomainFeedScorecardTargetAudience = serverConfig.getString(CUSTOMER_DOMAIN_FEED_SCORECARD_TARGET_AUDIENCE); if (!StringUtils.isEmpty(scoreCardUrl) && !StringUtils.isEmpty(gcpServiceKey)) { if (communicationUrl != null) { if (!StringUtils.isEmpty(gcpServiceKey)) { File fileServiceKey = new File(gcpServiceKey); if (fileServiceKey != null && fileServiceKey.exists() && fileServiceKey.isFile() && fileServiceKey.canRead()) { domainScoreCardOAuthParameters = new DomainOAuthParameters(fileServiceKey,customerDomainFeedScorecardTargetAudience); domainScoreCardOAuthParameters.setTestMode(false); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getScoreCardDomainOAuthParameters - GCP service key missing or invalid permissions!!!"); AzureLogger.write(LogType.Feature.CustomerDomainScoreCard, storeNumber, LogType.Status.FAILURE, 418, "CustomerSynchronizer.getScoreCardDomainOAuthParameters - GCP service key missing or invalid permissions", null, null, null); } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getScoreCardDomainOAuthParameters - GCP service key missing"); AzureLogger.write(LogType.Feature.CustomerDomainScoreCard, storeNumber, LogType.Status.FAILURE, 418, "CustomerSynchronizer.getScoreCardDomainOAuthParameters - GCP service key missing", null, null, null); } } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getScoreCardDomainOAuthParameters - Missing or invalid parameters"); AzureLogger.write(LogType.Feature.CustomerDomainScoreCard, storeNumber, LogType.Status.FAILURE, 418, "CustomerSynchronizer.getScoreCardDomainOAuthParameters - Missing or invalid parameters", null, null, null); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getScoreCardDomainOAuthParameters - Exception - " + exception); } } return domainScoreCardOAuthParameters; } private boolean isCustomerDomainFeedFeatureEnabled() { if (domainFeedFeatureEnabledStatusChanged == null || domainFeedFeatureEnabledStatusChanged.booleanValue() != domainFeedFeatureEnabled) { if (!domainFeedFeatureEnabled) { loggerCustomerDomainFeed.warn("Customer Domain feature flag 'SEND_CUSTOMER_DOMAIN' is disabled, NOT sending Customer(s) info to domain!"); AzureLogger.write(LogType.Feature.CustomerDomain, storeNumber, LogType.Status.YELLOW, 418, "Customer Domain feature flag 'SEND_CUSTOMER_DOMAIN' is disabled, NOT sending Customer(s) info to domain!", null, tamsVersion, null); } else { loggerCustomerDomainFeed.info("Customer Domain feature 'SEND_CUSTOMER_DOMAIN' flag is enabled, sending customer(s) info to domain!"); AzureLogger.write(LogType.Feature.CustomerDomain, storeNumber, LogType.Status.GREEN, 200, "Customer Domain feature 'SEND_CUSTOMER_DOMAIN' flag is enabled, sending customer(s) info to domain!", null, tamsVersion, null); } domainFeedFeatureEnabledStatusChanged = Boolean.valueOf(domainFeedFeatureEnabled); } return domainFeedFeatureEnabled; } private synchronized void doRetryCustomerToDomainFeed() { Long currentTime = Long.valueOf(new Date().getTime()); if (isCustomerDomainFeedFeatureEnabled()) { if (currentTime.compareTo(nextCustomerDomainFeedRetryTime) > 0) { nextCustomerDomainFeedRetryTime = Long.sum(currentTime, CUSTOMER_DOMAIN_FEED_RETRY_INTERVAL); Map customerDomainFeedRecords = getCustomerDomainFeedSyncRecordList(); if (!CollectionUtils.isEmpty(customerDomainFeedRecords)) { try { CommunicationUrl communicationUrl = getCustomerDomainFeedUrl(); DomainOAuthParameters domainOAuthParameters = getDomainOAuthParameters(); if (communicationUrl != null && domainOAuthParameters != null) { loggerCustomerDomainFeed.debug("CustomerSynchronizer::doRetryCustomerToDomainFeed - Sending modified customer event(s) to customer domain feed"); Thread thread = new Thread(new CustomerDomainFeedRequestWorker(customerDomainFeedRecords, communicationUrl, domainOAuthParameters, getCustomerDomainFeedWaitInterval(), getCustomerDomainFeedMaxTries(), storeNumber, customerChangeQueDao, location)); thread.start(); AzureLogger.write(LogType.Feature.CustomerDomain, storeNumber, LogType.Status.YELLOW, 418, "CustomerSynchronizer.doRetryCustomerToDomainFeed - Doing retries for failed customer event(s)", null, null, null); } else if (communicationUrl == null) { loggerCustomerDomainFeed.error("CustomerSynchronizer::doRetryCustomerToDomainFeed - Missing or invalid communicationUrl parameters"); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::doRetryCustomerToDomainFeed - Missing or invalid domainOAuthParameters parameters"); } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::doRetryCustomerToDomainFeed - Exception thread creation ", exception); } } } else { if (currentTime.compareTo(nextCustomerDomainFeedScorecardTime) > 0) { nextCustomerDomainFeedScorecardTime = Long.sum(currentTime, getCustomerDomainFeedScorecardInterval()); doCustomerDomainFeedScoreCard(); } } } } private synchronized void doCustomerDomainFeedScoreCard() { try { List sendCustomerIds = getCustomerIdSentLst(); if (!CollectionUtils.isEmpty(sendCustomerIds)) { List customerDomainFeedDetailsList = customerDomainDataService.retrieveCustomerDomainFeedDetailsByCustomerId(sendCustomerIds, location); if (!CollectionUtils.isEmpty(customerDomainFeedDetailsList)) { DomainOAuthParameters scoreCardDomainOAuthParameters = getScoreCardDomainOAuthParameters(); CommunicationUrl communicationScoreCardUrl = getCustomerDomainScoreCardUrl(); if (scoreCardDomainOAuthParameters != null) { Thread threadTest = new Thread(new CustomerDomainRequestScoreCard(customerDomainFeedDetailsList, communicationScoreCardUrl, scoreCardDomainOAuthParameters, storeNumber, customerChangeQueDao, location, getCustomerDomainFeedScorecardInterval())); threadTest.start(); } } } } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::doCustomerDomainFeedScoreCard - Exception ", exception); } } private synchronized Map getCustomerDomainFeedSyncRecordList() { Map fileHashmap = new HashMap(); if (CustomerDomainFeedRequestWorker.isDoingRetries()) { /* currently processing retries */ return fileHashmap; } try { File path = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_PATH); boolean hasPath = path.exists(); if (hasPath) { for (File file : path.listFiles()) { String fileName = StringUtils.EMPTY; boolean isRecordFile = true; File recordFile = null; File processingFile = null; File illegalFile = null; try { if (file.isFile()) { fileName = file.getName().trim(); if (fileName.endsWith(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT) || fileName.endsWith(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT)) { int index = fileName.lastIndexOf(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT); if (index < 0) { // check for the processing file isRecordFile = false; index = fileName.lastIndexOf(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT); } if (index > 0) { String changeQueueId = fileName.substring(0, index); recordFile = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_PATH + "/" + changeQueueId + CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT); processingFile = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_PATH + "/" + changeQueueId + CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT); Integer value = Integer.valueOf(changeQueueId.trim()); if (processingFile.exists()) { if (!recordFile.exists()) { // retry if (processingFile.canWrite()) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Retrying file : " + fileName); fileHashmap.put(changeQueueId, processingFile); } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Record file has invalid permissions!!! : " + processingFile.getName()); } } else { //remove old file CustomerDomainFeedRequestWorker.deleteCustomerDomainFeedRecordFile(processingFile); } } if (recordFile.exists()) { if (recordFile.canWrite()) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Retrying file : " + fileName); if (recordFile.renameTo(processingFile)) { fileHashmap.put(changeQueueId, processingFile); } else { /* rename failed skip for now */ loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Rename failed Will retry later for file : " + recordFile.getName()); } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Record file has invalid permissions!!! : " + recordFile.getName()); } } } } if (fileHashmap.size() >= 5000) { /* limit size to 5000 records at a time */ return fileHashmap; } } }catch (NumberFormatException numberFormatException) { if (isRecordFile) { illegalFile = recordFile; } else { illegalFile = processingFile; } if (illegalFile != null && illegalFile.exists()) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - NumberFormatException illegal file name : " + fileName); if (CustomerDomainFeedRequestWorker.deleteCustomerDomainFeedRecordFile(illegalFile)) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Deleted illegal file name : " + fileName); } } } catch (SecurityException securityException) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - SecurityException ", securityException); } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Exception ", exception); } } } else { /* create path */ if (!path.mkdir()) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Failed creating path : " + path); } } } catch (SecurityException securityException2) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - SecurityException ", securityException2); } catch (Exception exception2) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainFeedSyncRecordList - Exception ", exception2); } return fileHashmap; } private CommunicationUrl getCustomerDomainScoreCardUrl() { if (isCustomerDomainFeedFeatureEnabled() && customerDomainScoreCardServerURL == null) { try { customerDomainScoreCardServerURL = communicationURLDAO.find(serverConfig.getString(CUSTOMER_DOMAIN_FEED_SCORECARD_URL)); } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerDomainScoreCardUrl - Missing customer domain score card URL", exception); } } return customerDomainScoreCardServerURL; } private synchronized List getCustomerIdSentLst() { List customerIdList = new ArrayList<>(); if (hasCustomerDomainFeedSyncRecords() || CustomerDomainRequestScoreCard.isDoingScoreCardCheck()) { /* currently processing retries or validation */ return customerIdList; } try { Long timeNow = new Date().getTime(); File path = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_SUCCESS_PATH); boolean hasPath = path.exists(); if (hasPath) { Long domainEventWait = 1800000L; File[] listOfFiles = path.listFiles(); for (File file : listOfFiles) { String fileName = StringUtils.EMPTY; boolean isRecordFile = true; File recordFile = null; File processingFile = null; File illegalFile = null; try { if (file.isFile()) { fileName = file.getName().trim(); if (fileName.endsWith(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT) || fileName.endsWith(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT)) { int index = fileName.lastIndexOf(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT); if (index < 0) { // check for the processing file isRecordFile = false; index = fileName.lastIndexOf(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT); } if (index > 0) { String changeQueueId = fileName.substring(0, index); recordFile = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_SUCCESS_PATH + "/" + changeQueueId + CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT); processingFile = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_SUCCESS_PATH + "/" + changeQueueId + CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT); Integer integerChangeQueueId = Integer.valueOf(changeQueueId.trim()); if (processingFile.exists()) { if (!recordFile.exists()) { // validate if (processingFile.canWrite()) { CustomerRecord customerRecord = CustomerDomainRequestScoreCard.readCustomerRecord(processingFile); if (customerRecord != null) { customerRecord.setScoreCard(true); customerIdList.add(customerRecord); loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedCustomerSentIdLst - added validation check for changeQueueId : " + changeQueueId + " with customerId : " + customerRecord.getCustomerId()); } else { CustomerDomainFeedRequestWorker.deleteCustomerDomainFeedRecordFile(processingFile); loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - Record file has invalid values!!! : " + processingFile.getName()); } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - Record file has invalid permissions!!! : " + processingFile.getName()); } } else { //remove old file CustomerDomainFeedRequestWorker.deleteCustomerDomainFeedRecordFile(processingFile); } } if (recordFile.exists() && (Long.compare(timeNow, Long.sum(recordFile.lastModified(), domainEventWait)) > 0)) { /* allow domain minimum 30 minutes before trying to verify, scheduler runs every 8 hours */ if (recordFile.canWrite()) { CustomerRecord customerRecord = CustomerDomainRequestScoreCard.readCustomerRecord(recordFile); if (customerRecord != null) { if (recordFile.renameTo(processingFile)) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerDomainFeedCustomerSentIdLst - added validation check for changeQueueId : " + changeQueueId + " with customerId : " + customerRecord.getCustomerId()); customerIdList.add(customerRecord); } else { /* rename failed skip for now */ loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerIdSentLst - Rename failed Will retry later for file : " + recordFile.getName()); } } } else { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - Record file has invalid permissions!!! : " + recordFile.getName()); } } } } if (customerIdList.size() >= 5000) { /* limit size to 5000 records at a time */ return customerIdList; } } } catch (NumberFormatException numberFormatException) { if (isRecordFile) { illegalFile = recordFile; } else { illegalFile = processingFile; } if (illegalFile != null && illegalFile.exists()) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - NumberFormatException illegal file name : " + fileName); if (CustomerDomainFeedRequestWorker.deleteCustomerDomainFeedRecordFile(illegalFile)) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerIdSentLst - Deleted illegal file name : " + fileName); } } } catch (SecurityException securityException) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - SecurityException ", securityException); } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - Exception ", exception); } } } else { /* create path */ if (!path.mkdir()) { loggerCustomerDomainFeed.info("CustomerSynchronizer::getCustomerIdSentLst - Failed creating path : " + path); } } } catch (SecurityException securityException2) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - SecurityException ", securityException2); } catch (Exception exception2) { loggerCustomerDomainFeed.error("CustomerSynchronizer::getCustomerIdSentLst - Exception ", exception2); } return customerIdList; } private synchronized boolean hasCustomerDomainFeedSyncRecords() { if (CustomerDomainFeedRequestWorker.isDoingRetries()) { /* currently processing retries */ return true; } try { File path = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_PATH); boolean hasPath = path.exists(); if (hasPath) { for (File file : path.listFiles()) { String fileName = StringUtils.EMPTY; boolean isRecordFile = true; File recordFile = null; File processingFile = null; File illegalFile = null; try { if (file.isFile()) { fileName = file.getName().trim(); if (fileName.endsWith(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT) || fileName.endsWith(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT)) { int index = fileName.lastIndexOf(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT); if (index < 0) { // check for the processing file isRecordFile = false; index = fileName.lastIndexOf(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT); } if (index > 0) { String changeQueueId = fileName.substring(0, index); recordFile = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_PATH + "/" + changeQueueId + CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORD_EXT); processingFile = new File(CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_RECORDS_PATH + "/" + changeQueueId + CustomerDomainFeedRequestWorker.CUSTOMER_DOMAIN_FILES_PROCESSING_EXT); Integer value = Integer.valueOf(changeQueueId.trim()); if (processingFile.exists() && processingFile.canWrite() || recordFile.exists() && recordFile.canWrite()) { return true; } } } } } catch (NumberFormatException numberFormatException) { if (isRecordFile) { illegalFile = recordFile; } else { illegalFile = processingFile; } if (illegalFile != null && illegalFile.exists()) { loggerCustomerDomainFeed.error("CustomerSynchronizer::hasCustomerDomainFeedSyncRecords - NumberFormatException illegal file name : " + fileName); } } catch (SecurityException securityException) { loggerCustomerDomainFeed.error("CustomerSynchronizer::hasCustomerDomainFeedSyncRecords - SecurityException ", securityException); } catch (Exception exception) { loggerCustomerDomainFeed.error("CustomerSynchronizer::hasCustomerDomainFeedSyncRecords - Exception ", exception); } } } } catch (SecurityException securityException2) { loggerCustomerDomainFeed.error("CustomerSynchronizer::hasCustomerDomainFeedSyncRecords - SecurityException ", securityException2); } catch (Exception exception2) { loggerCustomerDomainFeed.error("CustomerSynchronizer::hasCustomerDomainFeedSyncRecords - Exception ", exception2); } return false; } }