📝 clarify library async wrapper docs

This commit is contained in:
Nanaloveyuki
2026-06-14 01:06:15 +08:00
parent 79529d748f
commit 3d88ac87a1
3 changed files with 60 additions and 11 deletions
@@ -3,7 +3,7 @@ name: async-logger-to-library-async-logger
group: api group: api
category: facade category: facade
update-time: 20260613 update-time: 20260613
description: Convert a full async logger into the narrower library-facing async facade. description: Convert a full async logger into the narrower library-facing async facade without rebuilding the underlying async state.
key-word: key-word:
- async - async
- library - library
@@ -34,8 +34,9 @@ pub fn[S] AsyncLogger::to_library_async_logger(self : AsyncLogger[S]) -> Library
Detailed rules explaining key parameters and behaviors Detailed rules explaining key parameters and behaviors
- This conversion does not rebuild the queue, sink, or runtime state. - This conversion does not rebuild the queue, sink, or runtime state.
- Target, min level, async config, and flush behavior are preserved. - Target, min level, async config, flush behavior, pending counts, and failure state are preserved because the same underlying async logger value is wrapped.
- The returned facade keeps library-facing async operations including `log(...)`, `run()`, and `shutdown(...)`. - The returned facade keeps library-facing async operations including `log(...)`, `run()`, and `shutdown(...)`.
- Async inspection helpers and broader composition APIs remain on the underlying `AsyncLogger[S]` and are intentionally hidden until `to_async_logger()` is used again.
### How to Use ### How to Use
@@ -51,6 +52,17 @@ let public_logger = logger.to_library_async_logger()
In this example, `public_logger` keeps the same async behavior but exposes the library-facing facade. In this example, `public_logger` keeps the same async behavior but exposes the library-facing facade.
#### When Need To Narrow Surface Without Resetting Runtime State
When an already-used async logger should be projected to a library boundary without changing its current state:
```moonbit
let full = build_async_logger(config)
let public_logger = full.to_library_async_logger()
ignore(public_logger.is_enabled(@bitlogger.Level::Info))
```
In this example, the projection changes the exposed type only; it does not rebuild queue or lifecycle state.
### Error Case ### Error Case
e.g.: e.g.:
@@ -58,8 +70,12 @@ e.g.:
- The conversion does not clear pending items or reset runtime state. - The conversion does not clear pending items or reset runtime state.
- If callers later need state helpers such as `pending_count()` or `state()`, they must unwrap again with `to_async_logger()`.
### Notes ### Notes
1. Use this when package boundaries should avoid exposing the full async logger type. 1. Use this when package boundaries should avoid exposing the full async logger type.
2. This is a projection API, not a reconfiguration step. 2. This is a projection API, not a reconfiguration step.
3. Use `build_library_async_logger(...)` or `build_library_async_text_logger(...)` when construction and narrowing should happen together from config.
+23 -6
View File
@@ -3,7 +3,7 @@ name: library-async-logger-new
group: api group: api
category: facade category: facade
update-time: 20260613 update-time: 20260613
description: Create a narrower library-facing async logger facade from any sink implementation. description: Create a narrower library-facing async logger facade by building a regular async logger and wrapping the same underlying state.
key-word: key-word:
- async - async
- library - library
@@ -29,11 +29,11 @@ pub fn[S] LibraryAsyncLogger::new(
#### input #### input
- `sink : S` - Any sink value implementing `@bitlogger.Sink`, such as `@bitlogger.console_sink()` or a composed sink. - `sink : S` - Underlying sink value that should receive drained records, such as `@bitlogger.console_sink()` or a composed sink.
- `config : AsyncLoggerConfig` - Queue size, overflow behavior, batching, linger, and flush policy. - `config : AsyncLoggerConfig` - Queue size, overflow behavior, batching, linger, and flush policy.
- `min_level : Level` - Minimum enabled level. Messages below this threshold are ignored before enqueue. - `min_level : Level` - Minimum enabled level. Messages below this threshold are ignored before enqueue.
- `target : String` - Default target attached to emitted records unless later overridden. - `target : String` - Default target attached to emitted records unless later overridden.
- `flush : (S) -> Int raise` - Flush callback used when async batch or shutdown policy needs explicit flushing. - `flush : (S) -> Int raise` - Flush callback used when async batch or shutdown policy needs explicit flushing, and allowed to raise if flushing fails.
#### output #### output
@@ -43,10 +43,12 @@ pub fn[S] LibraryAsyncLogger::new(
Detailed rules explaining key parameters and behaviors Detailed rules explaining key parameters and behaviors
- This API builds a regular `async_logger(...)` internally and then wraps it as `LibraryAsyncLogger`. - This API builds a regular `async_logger(...)` internally and then wraps that same value as `LibraryAsyncLogger`.
- The returned facade intentionally exposes a smaller method set than the full `AsyncLogger[S]` type. - The returned facade intentionally exposes a smaller method set than the full `AsyncLogger[S]` type.
- Queue settings, flush policy, and runtime state are preserved inside the wrapped async logger. - Queue settings, flush policy, target, minimum level, and runtime state are preserved inside the wrapped async logger.
- Call `to_async_logger()` if later code must recover the full async logger surface. - This constructor does not start background draining by itself; `run()` is still the step that activates queue processing.
- If the supplied flush callback later raises during async drain or shutdown, failure state is still recorded on the wrapped async logger.
- Call `to_async_logger()` if later code must recover the broader async logger surface for state inspection or additional composition helpers.
### How to Use ### How to Use
@@ -77,6 +79,17 @@ let logger = LibraryAsyncLogger::new(
In this example, the facade still keeps the queue-backed async behavior while hiding the full async logger type. In this example, the facade still keeps the queue-backed async behavior while hiding the full async logger type.
#### When Need Full Async State Helpers Later
When library-facing construction should still allow later access to the broader async helper set:
```moonbit
let logger = LibraryAsyncLogger::new(@bitlogger.console_sink(), target="lib.async")
let full = logger.to_async_logger()
ignore(full.pending_count())
```
In this example, construction starts from the narrower facade, but the same underlying async logger can still be recovered later.
### Error Case ### Error Case
e.g.: e.g.:
@@ -84,8 +97,12 @@ e.g.:
- If later code needs methods outside the facade, it must unwrap with `to_async_logger()`. - If later code needs methods outside the facade, it must unwrap with `to_async_logger()`.
- Constructing the facade alone does not drain queued records; callers still need `run()` for active background processing.
### Notes ### Notes
1. This is the direct constructor counterpart to `async_logger(...)` for library-oriented async APIs. 1. This is the direct constructor counterpart to `async_logger(...)` for library-oriented async APIs.
2. Prefer this when public package boundaries should stay narrower than `AsyncLogger[S]`. 2. Prefer this when public package boundaries should stay narrower than `AsyncLogger[S]`.
3. Use `async_logger(...)` directly when the full async lifecycle, state, and composition surface should stay public from the start.
@@ -3,7 +3,7 @@ name: library-async-logger-to-async-logger
group: api group: api
category: facade category: facade
update-time: 20260613 update-time: 20260613
description: Recover the underlying full async logger from the library-facing async facade. description: Recover the underlying full async logger from the library-facing async facade without rebuilding queue or lifecycle state.
key-word: key-word:
- async - async
- library - library
@@ -34,8 +34,9 @@ pub fn[S] LibraryAsyncLogger::to_async_logger(self : LibraryAsyncLogger[S]) -> A
Detailed rules explaining key parameters and behaviors Detailed rules explaining key parameters and behaviors
- This conversion unwraps the existing async logger instead of rebuilding it. - This conversion unwraps the existing async logger instead of rebuilding it.
- Queue state, sink wiring, target, and flush policy remain the same. - Queue state, sink wiring, target, min level, flush policy, and current failure/lifecycle state remain the same.
- Use this when code needs wider async logger APIs outside the library facade. - Use this when code needs wider async logger APIs outside the library facade.
- This is the step required for helpers such as `pending_count()`, `dropped_count()`, `state()`, `wait_idle()`, `has_failed()`, `last_error()`, or broader composition methods that are intentionally hidden by `LibraryAsyncLogger[S]`.
### How to Use ### How to Use
@@ -45,12 +46,23 @@ Here are some specific examples provided.
When a library-facing async logger must be widened for additional async logger composition: When a library-facing async logger must be widened for additional async logger composition:
```moonbit ```moonbit
let library_logger = LibraryAsyncLogger::new(console_sink(), target="lib.async") let library_logger = LibraryAsyncLogger::new(@bitlogger.console_sink(), target="lib.async")
let full_logger = library_logger.to_async_logger().with_timestamp() let full_logger = library_logger.to_async_logger().with_timestamp()
``` ```
In this example, the facade is unwrapped so the caller can access the full async logger API again. In this example, the facade is unwrapped so the caller can access the full async logger API again.
#### When Need Direct Async State Inspection
When library-facing code later needs runtime diagnostics from the wrapped logger:
```moonbit
let full = library_logger.to_async_logger()
ignore(full.pending_count())
ignore(full.state())
```
In this example, unwrapping exposes the broader async inspection helpers on the same underlying logger state.
### Error Case ### Error Case
e.g.: e.g.:
@@ -58,8 +70,12 @@ e.g.:
- Unwrapping does not start or stop the background runtime by itself. - Unwrapping does not start or stop the background runtime by itself.
- Recovering the full async logger does not clear queue contents or reset failure state.
### Notes ### Notes
1. Use this only when the narrower async facade is no longer sufficient. 1. Use this only when the narrower async facade is no longer sufficient.
2. This is the inverse projection of `AsyncLogger::to_library_async_logger()`. 2. This is the inverse projection of `AsyncLogger::to_library_async_logger()`.
3. Use `LibraryAsyncLogger[S]` directly when the narrower package-facing surface is still sufficient.