Skip to content

Commit

Permalink
Treat EmptyCacheException from linker as a sort of reactive blocking …
Browse files Browse the repository at this point in the history
…when evaluating cache stability
  • Loading branch information
robertvazan committed Jan 21, 2024
1 parent 07383de commit 28ea0a2
Showing 1 changed file with 71 additions and 66 deletions.
137 changes: 71 additions & 66 deletions src/main/java/com/machinezoo/foxcache/CacheStability.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,70 +10,75 @@
* Cache stability is intended to guide dependent computations, especially refreshes of dependent caches.
*/
public enum CacheStability {
READY,
/*
* Includes instability in any of the dependencies.
*/
UNSTABLE,
/*
* Includes failure in any of the dependencies.
*/
FAILING;
static CacheStability evaluate(CacheOwner owner) {
ReactiveValue<CacheInput> input;
/*
* Do not propagate blocking or exceptions from CacheInput
* Just fall back to unstable status when input is not available.
*/
try (var nonblocking = ReactiveScope.nonblocking()) {
input = ReactiveValue.capture(() -> owner.input.get());
}
/*
* Blocking linker.
*/
if (input.blocking())
return UNSTABLE;
/*
* Failing linker.
*/
if (input.result() == null)
return FAILING;
/*
* Unstable or failing children.
*/
var children = input.result().stability();
if (children != READY)
return children;
var snapshot = owner.snapshot.get();
/*
* Empty cache.
*/
if (snapshot == null)
return UNSTABLE;
/*
* Stale cache, regardless of whether the cache holds a value or an exception.
*/
if (!input.result().hash().equals(snapshot.input()))
return UNSTABLE;
/*
* Expired cache. When the application launches after a long break,
* periodically refreshed caches may be extremely outdated. It is important to wait for their refresh.
*/
var policy = owner.cache.caching();
if (policy.period() != null && ReactiveInstant.now().isAfter(snapshot.refreshed().plus(policy.period())))
return UNSTABLE;
/*
* Currently refreshing cache. Even up-to-date cache can be manually forced to refresh.
* We assume the cache is being forced to refresh because it is suspected to be out of date.
*/
var worker = owner.worker;
if (worker.progress() != null)
return UNSTABLE;
/*
* Failing or cancelled cache, regardless of whether there is an older value available.
*/
if (snapshot.hash() == null || snapshot.exception() != null || snapshot.cancelled())
return FAILING;
return READY;
}
READY,
/*
* Includes instability in any of the dependencies.
*/
UNSTABLE,
/*
* Includes failure in any of the dependencies.
*/
FAILING;
static CacheStability evaluate(CacheOwner owner) {
ReactiveValue<CacheInput> input;
/*
* Do not propagate blocking or exceptions from CacheInput
* Just fall back to unstable status when input is not available.
*/
try (var nonblocking = ReactiveScope.nonblocking()) {
input = ReactiveValue.capture(() -> owner.input.get());
}
/*
* Blocking linker.
*/
if (input.blocking())
return UNSTABLE;
/*
* Treat EmptyCacheException from linker as a sort of reactive blocking.
*/
if (input.exception() != null && EmptyCacheException.caused(input.exception()))
return UNSTABLE;
/*
* Failing linker.
*/
if (input.result() == null)
return FAILING;
/*
* Unstable or failing children.
*/
var children = input.result().stability();
if (children != READY)
return children;
var snapshot = owner.snapshot.get();
/*
* Empty cache.
*/
if (snapshot == null)
return UNSTABLE;
/*
* Stale cache, regardless of whether the cache holds a value or an exception.
*/
if (!input.result().hash().equals(snapshot.input()))
return UNSTABLE;
/*
* Expired cache. When the application launches after a long break,
* periodically refreshed caches may be extremely outdated. It is important to wait for their refresh.
*/
var policy = owner.cache.caching();
if (policy.period() != null && ReactiveInstant.now().isAfter(snapshot.refreshed().plus(policy.period())))
return UNSTABLE;
/*
* Currently refreshing cache. Even up-to-date cache can be manually forced to refresh.
* We assume the cache is being forced to refresh because it is suspected to be out of date.
*/
var worker = owner.worker;
if (worker.progress() != null)
return UNSTABLE;
/*
* Failing or cancelled cache, regardless of whether there is an older value available.
*/
if (snapshot.hash() == null || snapshot.exception() != null || snapshot.cancelled())
return FAILING;
return READY;
}
}

0 comments on commit 28ea0a2

Please sign in to comment.