All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sportradar.unifiedodds.sdk.caching.impl.NamedValueCacheImpl Maven / Gradle / Ivy

/*
 * Copyright (C) Sportradar AG. See LICENSE for full license governing this code
 */

package com.sportradar.unifiedodds.sdk.caching.impl;

import com.google.common.base.Preconditions;
import com.sportradar.unifiedodds.sdk.caching.NamedValueCache;
import com.sportradar.unifiedodds.sdk.caching.ci.NamedValueCI;
import com.sportradar.unifiedodds.sdk.entities.NamedValue;
import com.sportradar.unifiedodds.sdk.exceptions.internal.DataProviderException;
import com.sportradar.unifiedodds.sdk.impl.DataProvider;
import com.sportradar.unifiedodds.sdk.impl.SDKTaskScheduler;
import com.sportradar.unifiedodds.sdk.impl.entities.NamedValueImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * The default implementation of the {@link NamedValueCache} used to cache {@link NamedValue} objects
 */
public class NamedValueCacheImpl implements NamedValueCache {
    /**
     * The {@link Logger} instance used to log {@link NamedValueCache} events
     */
    private static final Logger cacheLog = LoggerFactory.getLogger(NamedValueCacheImpl.class);

    /**
     * The {@link DataProvider} used to retrieve {@link NamedValue} objects
     */
    private final DataProvider dataProvider;

    /**
     * A {@link ConcurrentHashMap} that contains the retrieved {@link NamedValue} instances
     */
    private final ConcurrentHashMap namedValues;

    /**
     * A value indicating whether the data was already fetched
     */
    private boolean dataFetched = false;

    /**
     * Initializes a new instance of {@link NamedValueCacheImpl}
     *
     * @param dataProvider - the {@link DataProvider} which is used to retrieve {@link NamedValue}
     * @param scheduler - the {@link SDKTaskScheduler} used to perform repeating cache tasks
     */
    public NamedValueCacheImpl(DataProvider dataProvider, SDKTaskScheduler scheduler) {
        Preconditions.checkNotNull(dataProvider);

        this.dataProvider = dataProvider;
        this.namedValues = new ConcurrentHashMap<>();

        scheduler.scheduleAtFixedRate("NamedValueRefreshTask", this::onTimerElapsed, 24, 24, TimeUnit.HOURS);
    }


    /**
     * Gets the {@link NamedValue} specified by the provided id
     *
     * @param id - the id of the {@link NamedValue} to retrieve.
     * @return - the {@link NamedValue} specified by the provided id
     */
    @Override
    public NamedValue getNamedValue(int id) {
        if (!dataFetched) {
            dataFetched = fetchAndMerge();
        }

        String description = namedValues.get(id);
        if (description == null) {
            return new NamedValueImpl(id);
        }

        return new NamedValueImpl(id, description);
    }

    /**
     * Determines if the specified id exists in the current cache instance
     *
     * @param id - the id that should be checked
     * @return true if the value is defined; otherwise false
     */
    @Override
    public boolean isValueDefined(int id) {
        if (!dataFetched) {
            dataFetched = fetchAndMerge();
        }

        return namedValues.containsKey(id);
    }

    /**
     * Fetches and merges {@link NamedValue} provided by the {@link this#dataProvider}
     *
     * @return - true if the operation was successful; otherwise false;
     */
    private synchronized boolean fetchAndMerge(){
        Object fetch;
        try {
            fetch = dataProvider.getData();
        } catch (DataProviderException e) {
            cacheLog.warn("There was an error while fetching the namedValue cache list, ex:", e);
            return false;
        }

        List namedValueCIS = NamedValueCI.mapToNamedValuesCI(fetch);
        namedValueCIS.forEach(fetchedVal -> namedValues.put(fetchedVal.getId(), fetchedVal.getDescription()));

        cacheLog.info("{} {} retrieved", namedValueCIS.size(), fetch.getClass().getName());
        return true;
    }

    /**
     * Timer scheduled for every 24h to refresh named values
     */
    private synchronized void onTimerElapsed() {
        try {
            namedValues.clear();
            fetchAndMerge();
        } catch (Exception ex) { // so timer does not die
            cacheLog.warn("An exception occurred while attempting to retrieve named values with the scheduled timer. [{}] Exception was: {}", dataProvider, ex);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy