Skip to content

Instantly share code, notes, and snippets.

@kakai248
Created February 5, 2018 18:47
Show Gist options
  • Save kakai248/a931e76d594699bfb3d85c55faecd7a6 to your computer and use it in GitHub Desktop.
Save kakai248/a931e76d594699bfb3d85c55faecd7a6 to your computer and use it in GitHub Desktop.
private TimedCacheSource<Discover> discoverObservable = TimedCacheSource.createWithTimeout(30, TimeUnit.SECONDS);
public Single<Discover> getProviders() {
return discoverObservable.switchIfEmpty(fetchProviders().doOnSuccess(discoverObservable));
}
/**
* Maybe that caches a value for an amount of time. Every time it is subscribed it either
* emits the cached value if it isn't expired or just completes.
* <p/>
* Default timeout is 5 minutes.
*
* @param <T> the value type received and emitted by this Maybe subclass
*/
public final class TimedCacheSource<T> extends Maybe<T> implements Consumer<T> {
private static final int DEFAULT_TIMEOUT_MS = 300000; // 5 minutes
private final int timeout;
private final TimeUnit unit;
private final AtomicReference<TimedValue<T>> valueRef = new AtomicReference<>();
public static <T> TimedCacheSource<T> create() {
return new TimedCacheSource<>(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
public static <T> TimedCacheSource<T> createWithTimeout(int timeout, TimeUnit unit) {
return new TimedCacheSource<>(timeout, unit);
}
private TimedCacheSource(int timeout, TimeUnit unit) {
this.timeout = timeout;
this.unit = ObjectHelper.requireNonNull(unit, "unit is null");
}
public void clear() {
valueRef.set(null);
}
@Override
public void accept(T value) {
valueRef.set(new TimedValue<>(value, System.currentTimeMillis()));
}
@Override
protected void subscribeActual(MaybeObserver<? super T> observer) {
TimedValue<T> value = valueRef.get();
if (value != null && insideTimeWindow(value.time)) {
observer.onSuccess(value.value);
} else {
observer.onComplete();
}
}
private boolean insideTimeWindow(long time) {
long now = System.currentTimeMillis();
return now - time < unit.toMillis(timeout);
}
private static class TimedValue<T> {
private final T value;
private final long time;
TimedValue(T value, long time) {
this.value = value;
this.time = time;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment