qubit_progress/reporter/impls/json_writer_progress_reporter.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::{
11 io::Write,
12 sync::{
13 Arc,
14 Mutex,
15 },
16};
17
18use qubit_function::ArcConsumer;
19
20use super::json_progress_reporter::JsonProgressReporter;
21use crate::{
22 model::ProgressEvent,
23 reporter::ProgressReporter,
24};
25
26/// Progress reporter that writes JSON metric snapshots to a writer.
27///
28/// One input event can produce multiple JSON lines: one line for each metric
29/// counter carried by the event.
30pub struct JsonWriterProgressReporter<W> {
31 /// Shared writer receiving JSON lines.
32 writer: Arc<Mutex<W>>,
33 /// JSON reporter that consumes formatted strings.
34 inner: JsonProgressReporter,
35}
36
37impl<W> JsonWriterProgressReporter<W> {
38 /// Returns the shared writer used by this reporter.
39 ///
40 /// # Returns
41 ///
42 /// A shared reference to the writer mutex.
43 #[inline]
44 pub const fn writer(&self) -> &Arc<Mutex<W>> {
45 &self.writer
46 }
47}
48
49impl<W> JsonWriterProgressReporter<W>
50where
51 W: Write + Send + 'static,
52{
53 /// Creates a reporter from a shared writer.
54 ///
55 /// # Parameters
56 ///
57 /// * `writer` - Shared writer receiving JSON progress output.
58 ///
59 /// # Returns
60 ///
61 /// A JSON writer-backed progress reporter.
62 pub fn new(writer: Arc<Mutex<W>>) -> Self {
63 let consumer_writer = Arc::clone(&writer);
64 let consumer = ArcConsumer::new(move |line: &String| {
65 let mut writer = consumer_writer
66 .lock()
67 .unwrap_or_else(std::sync::PoisonError::into_inner);
68 writeln!(writer, "{line}").expect("JSON progress reporter should write event");
69 });
70 Self {
71 writer,
72 inner: JsonProgressReporter::new(consumer),
73 }
74 }
75
76 /// Creates a reporter from an owned writer.
77 ///
78 /// # Parameters
79 ///
80 /// * `writer` - Owned writer receiving JSON progress output.
81 ///
82 /// # Returns
83 ///
84 /// A JSON writer-backed progress reporter.
85 #[inline]
86 pub fn from_writer(writer: W) -> Self {
87 Self::new(Arc::new(Mutex::new(writer)))
88 }
89}
90
91impl<W> ProgressReporter for JsonWriterProgressReporter<W>
92where
93 W: Write + Send + 'static,
94{
95 /// Writes one JSON line for every metric snapshot in the event.
96 ///
97 /// # Parameters
98 ///
99 /// * `event` - Progress event to format and write.
100 ///
101 /// # Panics
102 ///
103 /// Recovers the inner writer when the writer mutex is poisoned, and panics
104 /// only when writing to the configured writer fails.
105 #[inline]
106 fn report(&self, event: &ProgressEvent) {
107 self.inner.report(event);
108 }
109}