📝 clarify async lifecycle docs

This commit is contained in:
Nanaloveyuki
2026-06-14 02:03:34 +08:00
parent 91b0900b11
commit d9b609d064
4 changed files with 21 additions and 10 deletions
+1
View File
@@ -38,6 +38,7 @@ Detailed rules explaining key parameters and behaviors
- `clear=false` closes the queue without explicitly abandoning pending records in the helper itself.
- `clear=true` counts pending records as dropped and resets `pending_count` to `0` before closing the queue.
- This helper does not itself wait for the worker to finish.
- `close(...)` also does not change `has_failed()` or `last_error()`; it is a closure primitive, not a failure reset API.
- Because this is a low-level close primitive, it does not first run `wait_idle()` or apply the runtime-dependent fallback logic used by `shutdown()`.
### How to Use
+12 -8
View File
@@ -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,12 +33,12 @@ 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.
- It also resets `last_error()` to an empty string before worker execution begins.
- On failure, the logger records `has_failed=true` and stores the error text in `last_error`.
- On failure, `is_running` is cleared before the error is raised back out of `run()`.
- 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.
- 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()`.
- 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
@@ -70,12 +70,14 @@ 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.
- 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, 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.
@@ -83,3 +85,5 @@ e.g.:
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.
+5
View File
@@ -39,6 +39,7 @@ Detailed rules explaining key parameters and behaviors
- `clear=true` immediately closes and abandons pending records.
- In runtimes where shutdown waits for workers, the method then waits until `is_running()` becomes `false` before returning.
- In the current backend split, native-worker runtimes enable both the post-`wait_idle()` clear fallback and the final wait-for-worker phase, while compatibility runtimes skip both extra steps.
- Because `clear=false` delegates to `wait_idle()` first, shutdown can also wait indefinitely when pending records exist but no worker is making progress and no failure flag is raised.
### How to Use
@@ -71,6 +72,8 @@ e.g.:
- In compatibility-style runtimes without background-worker waiting, shutdown still closes the logger but may not perform the extra wait-for-worker phase described for native-worker runtimes.
- If pending work exists but no worker was started, `shutdown(clear=false)` may never reach its later close step because it is still waiting inside `wait_idle()`.
- If callers skip `shutdown()` and only inspect flags manually, it is easier to leave the worker lifecycle in an unclear state.
### Notes
@@ -82,3 +85,5 @@ e.g.:
3. Choose `clear=true` only when loss of queued records is acceptable.
4. Pair it with `state()` or focused counters when tests need to assert whether shutdown drained backlog or converted it into dropped records.
5. Prefer `shutdown(clear=true)` when teardown must not depend on a still-running drain worker.
+3 -2
View File
@@ -34,9 +34,10 @@ pub async fn[S] AsyncLogger::wait_idle(self : AsyncLogger[S]) -> Unit {}
Detailed rules explaining key parameters and behaviors
- The helper keeps yielding while `pending_count() > 0`.
- If `has_failed()` becomes `true`, waiting stops early instead of looping forever.
- If `has_failed()` becomes `true`, waiting stops early instead of continuing to spin.
- This API does not close the logger or stop the worker.
- A return from `wait_idle()` therefore means either backlog reached `0` or failure interrupted normal drain progress.
- If no worker is draining the queue and no failure flag is raised, `wait_idle()` can wait indefinitely.
- It is narrower than `shutdown()` and is useful when the logger should continue to be used later.
### How to Use
@@ -67,7 +68,7 @@ In this example, the wait acts as a barrier between test phases.
e.g.:
- If the worker has failed, `wait_idle()` stops waiting even if pending records remain.
- If the worker was never started, pending records may not drain and callers should not expect idle progress automatically.
- If the worker was never started, or if nothing is making pending records decrease, `wait_idle()` can block indefinitely.
- If callers need backlog cleanup after a failure-short-circuit, they still need a later `close(clear=true)` or `shutdown(...)` path.