# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/times import preserves, syndicate, syndicate/relays, syndicate/durings, syndicate/actors/timers type BootArgs {.preservesDictionary.} = object dataspace: Cap lifetime: float64 proc afterTimeout(n: float64): LaterThan = ## Get a `LaterThan` record for `n` seconds in the future. result.seconds = getTime().toUnixFloat() + n type CacheEntity {.final.} = ref object of Entity timeouts, target: Cap # dataspaces for observing timeouts and publishing values pattern: Pattern lifetime: float64 method publish(cache: CacheEntity; turn: var Turn; ass: AssertionRef; h: Handle) = ## Re-assert pattern captures in a sub-facet. discard inFacet(turn) do (turn: var Turn): # TODO: a seperate facet for every assertion, too much? var ass = depattern(cache.pattern, ass.value.sequence) # Build an assertion with what he have of the pattern and capture. discard publish(turn, cache.target, ass) let timeout = afterTimeout(cache.lifetime) onPublish(turn, cache.timeouts, ?timeout) do: stop(turn) # end this facet proc isObserve(pat: Pattern): bool = pat.orKind == PatternKind.DCompound and pat.dcompound.orKind == DCompoundKind.rec and pat.dcompound.rec.label.isSymbol"Observe" proc spawnCacheActor*(turn: var Turn; root: Cap): Actor = spawn("cache_actor", turn) do (turn: var Turn): during(turn, root, ?:BootArgs) do (ds: Cap, lifetime: float64): onPublish(turn, ds, ?:Observe) do (pat: Pattern, obs: Cap): var cache: CacheEntity if obs.relay != turn.facet and not(pat.isObserve): # Watch pattern if the observer is not us # and if the pattern isn't a recursive observe cache = CacheEntity( timeouts: root, target: ds, pattern: pat, lifetime: lifetime, ) discard observe(turn, ds, pat, cache) when isMainModule: runActor("cache_actor") do (turn: var Turn; root: Cap): spawnTimers(turn, root) connectStdio(turn, root) discard spawnCacheActor(turn, root)