syndicate_utils/src/syndesizer/cache_actor.nim

59 lines
2.1 KiB
Nim

# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/times
import preserves, syndicate,
syndicate/durings,
syndicate/drivers/timers
import ../schema/config
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 =
spawnActor(turn, "cache_actor") do (turn: var Turn):
during(turn, root, ?:CacheArguments) 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:
import syndicate/relays
runActor("main") do (turn: var Turn):
resolveEnvironment(turn) do (turn: var Turn; ds: Cap):
discard spawnTimerDriver(turn, ds)
discard spawnCacheActor(turn, ds)