📝 consolidate logger API and async lifecycle guidance

This commit is contained in:
Nanaloveyuki
2026-06-14 14:00:00 +08:00
parent 4f2ad097af
commit 265cd69ea9
154 changed files with 2419 additions and 396 deletions
+22 -8
View File
@@ -2,8 +2,8 @@
name: async-logger-run
group: api
category: async
update-time: 20260512
description: Start the async logger worker loop so queued records are drained to the underlying sink.
update-time: 20260614
description: Start the async logger worker loop so queued records are drained to the underlying sink while lifecycle and failure state are reset and updated around execution.
key-word:
- async
- logger
@@ -13,7 +13,7 @@ key-word:
## Async-logger-run
Start the async logger worker loop. This is the core runtime API that drains queued records to the underlying sink and updates worker lifecycle state.
Start the async logger worker loop. This is the core runtime API that drains queued records to the underlying sink and updates worker lifecycle state around that drain loop.
### Interface
@@ -33,10 +33,14 @@ pub async fn[S : @bitlogger.Sink] AsyncLogger::run(self : AsyncLogger[S]) -> Uni
Detailed rules explaining key parameters and behaviors
- `run()` sets `is_running` to `true` while the worker loop is active.
- It clears previous failure state before worker execution begins.
- On failure, the logger records `has_failed=true` and stores the error text in `last_error`.
- The worker exits when the queue is closed or when a failure aborts processing.
- `run()` sets `is_running` to `true` before worker execution begins.
- Every invocation clears previous failure state first by setting `has_failed=false` and `last_error()` to an empty string once that `run()` call has actually started executing.
- The method then keeps draining records until `queue.get()` stops with `AsyncLoggerClosed` or a worker error escapes.
- On a normal queue-close exit, `run()` clears `is_running` and returns normally.
- On failure, the logger records `has_failed=true`, stores the error text in `last_error`, clears `is_running`, and then raises the error back out of `run()`.
- A worker failure does not guarantee the async backlog was fully drained first. If the failure happens after some records were already written, later queued records can remain pending when `run()` exits.
- A later `run()` invocation can resume draining that retained backlog, but the stale failure flag and stale `last_error()` value are only cleared after the new worker call actually begins running.
- This helper does not enforce a single-worker guard by itself, so the public contract should be treated as application-controlled worker startup rather than an API that deduplicates repeated `run()` calls.
### How to Use
@@ -68,12 +72,22 @@ In this example, the application decides when the worker begins instead of hidin
### Error Case
e.g.:
- If the worker loop fails, `has_failed()` becomes `true` and `last_error()` stores the error text.
- If the worker loop fails, `has_failed()` becomes `true`, `last_error()` stores the error text, and `run()` raises that failure to the caller.
- After a failed run, `pending_count()` can still be greater than zero until later shutdown or restart logic finishes handling the retained backlog.
- If `run()` is never started, accepted records may remain queued and not reach the sink.
- A later `run()` attempt starts from a fresh failure flag and empty `last_error()` string once that retrying worker has actually started, even if an earlier run failed.
- Starting more than one `run()` task for the same logger is not prevented by this method and can produce application-level worker coordination bugs.
### Notes
1. `async_logger(...)` only constructs the logger; `run()` is what activates queue draining.
2. Pair this API with `shutdown()` for a complete worker lifecycle.
3. Pair it with `has_failed()`, `last_error()`, or `state()` when tests need to inspect how a worker exit affected logger health.
4. Start one deliberate worker task per logger unless your own code is intentionally coordinating a different pattern.