| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Free.Agent.Bus.File
Contents
Description
Out-of-process bus helpers: file cursors and an fsnotify-based tail loop. Used by the long-running agent executables that watch the JSONL log directly instead of sharing STM state with the scribe.
Synopsis
- cursorPath :: FilePath -> Name -> FilePath
- readCursor :: FilePath -> Name -> IO PostId
- writeCursor :: FilePath -> Name -> PostId -> IO ()
- data QuiesceConfig = QuiesceConfig {}
- data Flow
- tailLog :: FilePath -> [Name] -> PostId -> Maybe (QuiesceConfig, IO ()) -> (Stamped Text -> IO Flow) -> IO ()
Cursor files
cursorPath :: FilePath -> Name -> FilePath Source #
Path to the cursor file for an agent.
The cursor stores the next postId the agent should process, so restarts
catch up without re-reading the whole log. A missing cursor defaults to 0,
meaning "start from the first post".
readCursor :: FilePath -> Name -> IO PostId Source #
Read the cursor for an agent. If no cursor file exists, defaults to the latest post id + 1 in the bus log so the agent skips history on cold boot. Returns 0 only when the log itself is absent or empty.
writeCursor :: FilePath -> Name -> PostId -> IO () Source #
Persist the cursor for an agent. Writes stamp + 1 so the next wake
starts after the post just processed.
Event-tail loop
data QuiesceConfig Source #
Quiescence configuration for long-running agents.
Constructors
| QuiesceConfig | |
Instances
| Show QuiesceConfig Source # | |
Defined in Free.Agent.Bus.File Methods showsPrec :: Int -> QuiesceConfig -> ShowS # show :: QuiesceConfig -> String # showList :: [QuiesceConfig] -> ShowS # | |
Arguments
| :: FilePath | Path to |
| -> [Name] | Subscribed names. |
| -> PostId | Starting cursor. |
| -> Maybe (QuiesceConfig, IO ()) | Optional quiescence config and action. |
| -> (Stamped Text -> IO Flow) | Callback for each delivered stored post; return |
| -> IO () |
Event-tail a log file and invoke the callback for every new stored post addressed to any of the subscribed names.
On startup the file is scanned from the beginning; posts with stamp
greater than or equal to the supplied cursor and addressed to any subscribed
name are delivered. After catch-up, fsnotify wakes a drain for new lines.
Reading is offset-based: each drain opens the file, reads the complete lines appended since the last offset, and closes the handle before invoking callbacks. A partial trailing line (writer mid-append) is left for the next drain. The handle must be closed before callbacks run because callbacks may append to the log in-process, and GHC locks files per process — a held read handle makes the append fail with "resource busy (file is locked)".
When a quiescence config is supplied, the main loop waits on a signal with a timeout instead of blocking forever. Each timeout without a signal increments an empty-cycle counter; a signal resets it. After the configured number of empty cycles, the provided action is run and the loop exits.
The loop also exits when a callback returns Halt.