Aria 2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Loading...
Searching...
No Matches
async_error_sink.hpp
Go to the documentation of this file.
1#pragma once
2
3// Async-layer error sink — destination for exceptions that escape a
4// fire-and-forget path (AsyncCommand::execute, CoroutineScope::launch,
5// detached Tasks, etc.).
6//
7// Architecture
8// ------------
9// As of the unified callback-boundary work this header is now a thin
10// adapter over `aria::report_callback_failure` (declared in
11// `<aria/callback_boundary.hpp>`). Existing call surfaces are preserved
12// exactly:
13//
14// * `aria::async::set_error_sink(sink)` — installs a per-async sink
15// accepting `std::string_view`. Hosts that already used this surface
16// (notably AsyncCommand consumers and the test suite) keep working
17// unchanged.
18// * `aria::async::report_async_error(msg)` — surfaces a detached-path
19// failure. **Both** the per-async sink (if installed) and the
20// framework-wide core sink (`aria::report_callback_failure`) receive
21// a notification carrying the category `"async"`. This dual-fire
22// design ensures host applications that install ONLY the core sink
23// (the recommended modern path) still observe async failures, while
24// legacy hosts that install ONLY the async sink keep their existing
25// observability.
26// * The async sink is invoked first (legacy ordering); if it throws,
27// the exception is locally swallowed and the core sink still fires.
28//
29// Usage (modern):
30//
31// aria::set_callback_failure_sink(&my_logger_bridge);
32// // — async failures surface as category="async".
33//
34// Usage (legacy / per-component):
35//
36// aria::async::set_error_sink([](std::string_view m) {
37// Logger::error("aria.async", m);
38// });
39
41
42#include <functional>
43#include <string_view>
44#include <utility>
45
46namespace aria::async {
47
48using ErrorSink = std::function<void(std::string_view)>;
49
51 static ErrorSink instance;
52 return instance;
53}
54
55inline void set_error_sink(ErrorSink sink) noexcept {
56 error_sink_() = std::move(sink);
57}
58
59inline void report_async_error(std::string_view msg) noexcept {
60 // Step 1: legacy per-async sink (if installed). Local catch — async
61 // sinks predate the framework-wide noexcept contract and are allowed
62 // to throw.
63 if (auto& s = error_sink_(); s) {
64 try { s(msg); } catch (...) { /* sink must not propagate */ }
65 }
66 // Step 2: framework-wide unified channel. Carries an empty
67 // exception_ptr because the historical async surface is
68 // string-based; the message itself encodes the failure.
69 ::aria::report_callback_failure(std::string_view{"async"}, msg);
70}
71
72} // namespace aria::async
Definition async_command.hpp:118
void report_async_error(std::string_view msg) noexcept
Definition async_error_sink.hpp:59
std::function< void(std::string_view)> ErrorSink
Definition async_error_sink.hpp:48
void set_error_sink(ErrorSink sink) noexcept
Definition async_error_sink.hpp:55
ErrorSink & error_sink_()
Definition async_error_sink.hpp:50
void report_callback_failure(std::string_view category, std::exception_ptr exception, std::string_view message={}) noexcept
Report a callback failure.