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

org.dstadler.audio.fm4.FM4Cache Maven / Gradle / Ivy

package org.dstadler.audio.fm4;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.dstadler.commons.logging.jdk.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Simple cache for FM4 shows to avoid delays when switching
 * between shows.
 *
 * Automatically refreshes itself in the background.
 *
 * The cache-data is not held in static members, so keep the instance
 * available where it is used.
 *
 * The cache is refreshed automatically every 5 minutes.
 */
public class FM4Cache implements AutoCloseable {
    private final static Logger log = LoggerFactory.make();

    // cache-implementation configured
    private final Cache> fm4Cache = CacheBuilder.newBuilder()
            // refreshing is done via a scheduled task
            .concurrencyLevel(2)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();

    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
            new BasicThreadFactory.Builder()
                    .daemon(true)
                    .namingPattern("FM4Cache-")
                    .uncaughtExceptionHandler((t, e) ->
                            log.log(Level.WARNING, "Had unexpected exception", e))
                    .build());

    public FM4Cache() {
        executor.scheduleAtFixedRate(this::refresh, 0, 5, TimeUnit.MINUTES);
    }

    public List get(String programKey) {
        return fm4Cache.getIfPresent(programKey);
    }

    public long size() {
        return fm4Cache.size();
    }

    public Collection allStreams() {
        List streams = new ArrayList<>();
        for (List list : fm4Cache.asMap().values()) {
            streams.addAll(list);
        }
        return streams;
    }

    public void refresh() {
        FM4 fm4 = new FM4();

        try {
            // first get all streams by programKey
            Multimap streams = ArrayListMultimap.create();
            for (FM4Stream stream : fm4.fetchStreams()) {
                streams.put(stream.getProgramKey(), stream);
            }

            // then store a lis tof items per programKey in the cache
            for (String programKey : streams.keySet()) {
                fm4Cache.put(programKey, new ArrayList<>(streams.get(programKey)));
            }
        } catch (IOException e) {
            log.log(Level.WARNING, "Failed to read FM4 streams", e);
        }
    }

    @Override
    public void close() {
        executor.shutdown();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy