diff --git a/lang/src/main/java/com/qwlabs/lang/RuntimeExpiringMemoizingSupplier.java b/lang/src/main/java/com/qwlabs/lang/RuntimeExpiringMemoizingSupplier.java new file mode 100644 index 0000000..f2f3004 --- /dev/null +++ b/lang/src/main/java/com/qwlabs/lang/RuntimeExpiringMemoizingSupplier.java @@ -0,0 +1,46 @@ +package com.qwlabs.lang; + +import com.google.common.base.Supplier; + +import javax.annotation.CheckForNull; + +public class RuntimeExpiringMemoizingSupplier implements Supplier { + private final Supplier> delegate; + @CheckForNull + private transient volatile T value; + private transient volatile long expirationNanos; + + public RuntimeExpiringMemoizingSupplier(Supplier> delegate) { + this.delegate = delegate; + } + + @Override + public T get() { + if (expirationNanos == 0) { + synchronized (this) { + if (expirationNanos == 0) { + realLoad(); + } + } + } + long now = System.nanoTime(); + if (now > expirationNanos) { + return this.value; + } + synchronized (this) { + realLoad(); + } + return value; + } + + private void realLoad() { + try { + var withExpiring = delegate.get(); + this.value = withExpiring.getData(); + this.expirationNanos = System.nanoTime() + withExpiring.getExpiresInNanos(); + } catch (Exception e) { + this.value = null; + this.expirationNanos = 0; + } + } +} diff --git a/lang/src/main/java/com/qwlabs/lang/WithExpiring.java b/lang/src/main/java/com/qwlabs/lang/WithExpiring.java new file mode 100644 index 0000000..08d8c34 --- /dev/null +++ b/lang/src/main/java/com/qwlabs/lang/WithExpiring.java @@ -0,0 +1,24 @@ +package com.qwlabs.lang; + +import lombok.Getter; + +import java.util.concurrent.TimeUnit; + +@Getter +public class WithExpiring { + private final T data; + private final long expiresInNanos; + + private WithExpiring(T data, long expiresInNanos) { + this.data = data; + this.expiresInNanos = expiresInNanos; + } + + public static WithExpiring of(T data, long expiresIn, TimeUnit timeUnit) { + return new WithExpiring<>(data, timeUnit.toNanos(expiresIn)); + } + + public static WithExpiring of(T data, long expiresInNanos) { + return new WithExpiring<>(data, expiresInNanos); + } +}