package com.genpt.nsight; import com.datastax.driver.core.Session; import com.genpt.nsight.v1.model.ProductKit; import com.genpt.nsight.v1.model.dto.SiteDTO; import com.genpt.nsight.v4.model.StoreHours; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; @Component @Getter @Setter public class NSightCache { private static final Logger LOGGER = LoggerFactory.getLogger(NSightCache.class); @Autowired Session session; /* @Autowired DataSource dataSource;*/ @Autowired NSightCacheLoader nSightCacheLoader; private ScheduledExecutorService scheduler; ExecutorService executor = Executors.newFixedThreadPool(10); private AtomicBoolean scheduled = new AtomicBoolean(false); private Map aliasToSiteIdMap; private Map InactiveAliasToSiteIdMap; private Map siteIdToSiteMap; private Map> supplierLocationMap; private Set dcSet; private Set supplierIdSet; private Set combinedFriendSet; //virtual kits data map Map productKitMapUS; Map productKitMapCA; Map storeIPMap; private Map buyerIDMap; private Set dontCallStoreSet; private Set combinedDCSet; private Map UAPDCMap = new HashMap<>(); private Map> supplierHQMap = new HashMap<>(); private Map displayNameMap = new HashMap<>(); private Map> storeHoursList = new HashMap<>(); int vkRecordCount = 0; Semaphore loadControl = new Semaphore(1); boolean error = false; private String invDataSvcPilotStores; private String deliveryDataSvcPilotStores; private String nonNapaStores; Map countryCodeMap; LoadingCache deliveryCutOffTimeStore = CacheBuilder.newBuilder().build(new CacheLoader() { @Override public String load(Long deliveryCutOffTime) throws Exception { long hours = TimeUnit.MILLISECONDS.toHours(deliveryCutOffTime); long minutes = TimeUnit.MILLISECONDS.toMinutes(deliveryCutOffTime); long seconds = (TimeUnit.MILLISECONDS.toSeconds(deliveryCutOffTime) - minutes * 60); minutes = minutes - hours * 60; return String.format("%02d", hours) + ":" + String.format("%02d", minutes) + ":" + String.format("%02d", seconds); } }); @PostConstruct private void init() { scheduler = Executors.newSingleThreadScheduledExecutor(); try { loadControl.tryAcquire(2,TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } nSightCacheLoader.loadAll(); this. aliasToSiteIdMap = nSightCacheLoader.getAliasToSiteIdMap(); this. InactiveAliasToSiteIdMap = nSightCacheLoader.getInactiveAliasToSiteIdMap(); this.siteIdToSiteMap = nSightCacheLoader.getSiteIdToSiteMap(); this.supplierLocationMap = nSightCacheLoader.getSupplierLocationMap(); this.dcSet = nSightCacheLoader.getDcSet(); this.supplierIdSet = nSightCacheLoader.getSupplierIdSet(); this.productKitMapUS = nSightCacheLoader.getProductKitMapUS(); this.productKitMapCA = nSightCacheLoader.getProductKitMapCA(); this.storeIPMap= nSightCacheLoader.getStoreIPMap(); this.combinedFriendSet=nSightCacheLoader.getCombinedFriendSet(); this.buyerIDMap=nSightCacheLoader.getBuyerIDToSiteMap(); this.dontCallStoreSet=nSightCacheLoader.getDontCallStoreSet(); this.combinedDCSet=nSightCacheLoader.getCombinedDCSet(); this.UAPDCMap=nSightCacheLoader.getUAPDCMap(); this.displayNameMap=nSightCacheLoader.getDisplayNameMap(); this.storeHoursList=nSightCacheLoader.getStoreHoursList(); this.invDataSvcPilotStores=nSightCacheLoader.getInvDataSvcPilotStores(); this.deliveryDataSvcPilotStores=nSightCacheLoader.getDeliveryDataSvcPilotStores(); this.nonNapaStores=nSightCacheLoader.getNonNapaStores(); this.countryCodeMap=nSightCacheLoader.getCountryCodeMap(); nSightCacheLoader.reset(); loadControl.release(); } public String getAlpha2CountryCode(String nineDigitAlias){ String alpha2 = null; String siteId = getAliasToSiteIdMap().get("9 Digit Store Number|"+nineDigitAlias); if(siteId!=null){ SiteDTO siteDTO = getSiteIdToSiteMap().get(siteId); if(siteDTO!=null){ alpha2 = countryCodeMap.get(siteDTO.getCountry()); if (alpha2==null) alpha2 = "US"; //default to US } } return alpha2; } public void processSiteChanges() { try { loadControl.tryAcquire(2,TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } nSightCacheLoader.processSiteChanges(); this. aliasToSiteIdMap = nSightCacheLoader.getAliasToSiteIdMap(); this. InactiveAliasToSiteIdMap = nSightCacheLoader.getInactiveAliasToSiteIdMap(); this.siteIdToSiteMap = nSightCacheLoader.getSiteIdToSiteMap(); this.supplierLocationMap = nSightCacheLoader.getSupplierLocationMap(); this.dcSet = nSightCacheLoader.getDcSet(); this.supplierIdSet = nSightCacheLoader.getSupplierIdSet(); this.combinedFriendSet=nSightCacheLoader.getCombinedFriendSet(); this.buyerIDMap=nSightCacheLoader.getBuyerIDToSiteMap(); //update of store ip needs some threshhold logic float existingCount = this.storeIPMap.size(); if (existingCount > 0) { float percentageCount = ( nSightCacheLoader.getStoreIPMap().size() / existingCount) * 100; if (percentageCount > 90) { this.storeIPMap = nSightCacheLoader.getStoreIPMap(); LOGGER.info("Threshold met while loading StoreIps , Existing Count : {}, Current Count: {} , Percentage: {} ", existingCount, nSightCacheLoader.getStoreIPMap().size(), percentageCount); } else LOGGER.error("Threshold not met while loading StoreIps , Existing Count : {}, Current Count: {}, Percentage: {} ", existingCount, nSightCacheLoader.getStoreIPMap().size(), percentageCount); } //this.storeIPMap= nSightCacheLoader.getStoreIPMap(); this.dontCallStoreSet=nSightCacheLoader.getDontCallStoreSet(); this.combinedDCSet=nSightCacheLoader.getCombinedDCSet(); this.UAPDCMap=nSightCacheLoader.getUAPDCMap(); this.displayNameMap=nSightCacheLoader.getDisplayNameMap(); this.storeHoursList=nSightCacheLoader.getStoreHoursList(); this.invDataSvcPilotStores=nSightCacheLoader.getInvDataSvcPilotStores(); this.deliveryDataSvcPilotStores=nSightCacheLoader.getDeliveryDataSvcPilotStores(); this.nonNapaStores=nSightCacheLoader.getNonNapaStores(); this.countryCodeMap=nSightCacheLoader.getCountryCodeMap(); nSightCacheLoader.reset(); loadControl.release(); } @Scheduled(cron = "${nsight.loadingSchedule}") private void loadOnSchedule() { LOGGER.info("Application: NSight , Loading VirtualKit on Schedule"); if(siteIdToSiteMap != null && siteIdToSiteMap.size() > 0) { //If for some reason the engine is started around the same time as cron job. nSightCacheLoader.reloadHQLineAbbrev(siteIdToSiteMap); this.productKitMapUS = nSightCacheLoader.getProductKitMapUS(); this.productKitMapCA = nSightCacheLoader.getProductKitMapCA(); //update of store ip needs some threshhold logic int existingCount = this.storeIPMap.size(); if (existingCount > 0) { int percentageCount = ( nSightCacheLoader.getStoreIPMap().size() / existingCount) * 100; if (percentageCount > 90) this.storeIPMap = nSightCacheLoader.getStoreIPMap(); else LOGGER.error("Threshold not met while loading StoreIps , Existing Count : {}, Current Count: {} ", existingCount, nSightCacheLoader.getStoreIPMap().size()); } //this.storeIPMap=nSightCacheLoader.getStoreIPMap(); } } public void load(int delay) { error=false; if(scheduled.compareAndSet(false,true)) { Runnable task = new Runnable() { //@Autowired //NSightCache nSightCache; public void run() { try { LOGGER.info("Application: NSight , JMS Listener Scheduled Cache Load Start. "); processSiteChanges(); getScheduled().set(false); LOGGER.info("Application: NSight , JMS Listener Scheduled Cache Load Finish. "); } catch (Exception ex) { LOGGER.error("Application ID: NSight , Error while Cache Refresh from Cassandra Message : {}, StackTrace: {} ", ex.getMessage(), ex.getStackTrace()); }finally { error=true; getScheduled().set(false); LOGGER.info("Application: NSight , Setting Scheduled to FALSE. "); } } }; scheduler.schedule(task,delay,TimeUnit.MINUTES); //go ahead and load the data once for now if (!error) processSiteChanges(); LOGGER.info("Application: NSight, Scheduled cache Load after {} minutes.", delay); } else LOGGER.info("Application: NSight, Ignoring Message. Load already scheduled."); } }