2025-02-10 14:49:30 +01:00
|
|
|
import pkg/chronos
|
2025-02-11 15:33:40 +01:00
|
|
|
import pkg/chronicles
|
2025-02-10 14:49:30 +01:00
|
|
|
import pkg/questionable/results
|
|
|
|
|
|
|
|
|
|
import ./config
|
2025-02-10 15:34:41 +01:00
|
|
|
import ./utils/asyncdataevent
|
|
|
|
|
import ./types
|
2025-02-10 14:49:30 +01:00
|
|
|
|
2025-02-11 15:33:40 +01:00
|
|
|
logScope:
|
|
|
|
|
topics = "state"
|
|
|
|
|
|
2025-02-10 14:49:30 +01:00
|
|
|
type
|
2025-02-11 16:31:23 +01:00
|
|
|
OnStep* = proc(): Future[?!void] {.async: (raises: []), gcsafe.}
|
2025-02-10 15:34:41 +01:00
|
|
|
|
|
|
|
|
DhtNodeCheckEventData* = object
|
|
|
|
|
id*: Nid
|
|
|
|
|
isOk*: bool
|
|
|
|
|
|
|
|
|
|
Events* = ref object
|
|
|
|
|
nodesFound*: AsyncDataEvent[seq[Nid]]
|
|
|
|
|
newNodesDiscovered*: AsyncDataEvent[seq[Nid]]
|
|
|
|
|
dhtNodeCheck*: AsyncDataEvent[DhtNodeCheckEventData]
|
2025-02-13 14:55:45 +01:00
|
|
|
nodesToRevisit*: AsyncDataEvent[seq[Nid]]
|
2025-02-15 10:36:52 +01:00
|
|
|
nodesDeleted*: AsyncDataEvent[seq[Nid]]
|
2025-02-10 15:34:41 +01:00
|
|
|
|
2025-02-11 15:33:40 +01:00
|
|
|
ApplicationStatus* {.pure.} = enum
|
|
|
|
|
Stopped
|
|
|
|
|
Stopping
|
|
|
|
|
Running
|
|
|
|
|
|
2025-02-11 10:54:58 +01:00
|
|
|
State* = ref object of RootObj
|
2025-02-11 15:33:40 +01:00
|
|
|
status*: ApplicationStatus
|
2025-02-10 14:49:30 +01:00
|
|
|
config*: Config
|
2025-02-10 16:24:54 +01:00
|
|
|
events*: Events
|
2025-02-10 14:49:30 +01:00
|
|
|
|
2025-06-02 16:16:41 +02:00
|
|
|
proc delayedWorkerStart(
|
|
|
|
|
s: State, step: OnStep, delay: Duration
|
|
|
|
|
) {.async: (raises: [CancelledError]).} =
|
2025-02-12 14:25:54 +01:00
|
|
|
await sleepAsync(1.seconds)
|
2025-02-12 13:50:12 +01:00
|
|
|
|
2025-06-02 14:30:28 +02:00
|
|
|
proc worker(): Future[void] {.async: (raises: [CancelledError]).} =
|
2025-02-11 15:33:40 +01:00
|
|
|
while s.status == ApplicationStatus.Running:
|
|
|
|
|
if err =? (await step()).errorOption:
|
|
|
|
|
error "Failure-result caught in main loop. Stopping...", err = err.msg
|
|
|
|
|
s.status = ApplicationStatus.Stopping
|
|
|
|
|
await sleepAsync(delay)
|
|
|
|
|
|
|
|
|
|
asyncSpawn worker()
|
2025-02-12 13:50:12 +01:00
|
|
|
|
2025-06-02 16:16:41 +02:00
|
|
|
method whileRunning*(
|
|
|
|
|
s: State, step: OnStep, delay: Duration
|
|
|
|
|
) {.async: (raises: []), base.} =
|
2025-02-12 13:50:12 +01:00
|
|
|
# We use a small delay before starting the workers because 'whileRunning' is likely called from
|
|
|
|
|
# component 'start' methods, which are executed sequentially in arbitrary order (to prevent temporal coupling).
|
|
|
|
|
# Worker steps might start raising events that other components haven't had time to subscribe to yet.
|
|
|
|
|
asyncSpawn s.delayedWorkerStart(step, delay)
|