Skip to main content

cgx_core/messages/
mod.rs

1pub mod build;
2pub mod build_cache;
3pub mod cgx;
4pub mod crate_resolution;
5pub mod git;
6pub mod prebuilt_binary;
7pub mod runner;
8pub mod source;
9
10use std::sync::mpsc;
11
12pub use build::BuildMessage;
13pub use build_cache::BuildCacheMessage;
14pub use cgx::{CgxMessage, Provenance};
15pub use crate_resolution::CrateResolutionMessage;
16pub use git::GitMessage;
17pub use prebuilt_binary::{PrebuiltBinaryMessage, ProviderChangeReason};
18pub use runner::RunnerMessage;
19use serde::{Deserialize, Serialize};
20pub use source::SourceMessage;
21
22// Re-export GitSelector since it's used in GitMessage's public API
23pub use crate::git::GitSelector;
24
25/// Top-level message enum representing all possible diagnostic messages from cgx.
26///
27/// Each variant corresponds to a specific subsystem and wraps that subsystem's message type.
28/// Messages are serialized as tagged JSON with a "type" field indicating the subsystem.
29#[derive(Debug, Clone, Serialize, Deserialize)]
30#[serde(tag = "type", content = "data", rename_all = "snake_case")]
31#[expect(
32    clippy::large_enum_variant,
33    reason = "the target refactor increases the largest variant by only about 40 bytes, just enough to \
34              cross the lint threshold"
35)]
36pub enum Message {
37    CrateResolution(CrateResolutionMessage),
38    PrebuiltBinary(PrebuiltBinaryMessage),
39    Source(SourceMessage),
40    BuildCache(BuildCacheMessage),
41    Git(GitMessage),
42    Build(BuildMessage),
43    Runner(RunnerMessage),
44    Cgx(CgxMessage),
45}
46
47/// A reporter for diagnostic messages.
48///
49/// This type is cheaply cloneable and can be shared across threads. It supports two modes:
50/// - `Null`: Messages are silently discarded (no-op)
51/// - `Channel`: Messages are sent to an mpsc channel for processing
52///
53/// The `report` method takes a closure to avoid allocating or cloning data unless messages
54/// are actually enabled.
55#[derive(Clone, Debug)]
56pub enum MessageReporter {
57    Null,
58    Channel(mpsc::SyncSender<Message>),
59}
60
61impl MessageReporter {
62    /// Create a null reporter that discards all messages.
63    pub fn null() -> Self {
64        Self::Null
65    }
66
67    /// Create a channel reporter that sends messages to the given sender.
68    pub fn channel(sender: mpsc::SyncSender<Message>) -> Self {
69        Self::Channel(sender)
70    }
71
72    /// Report a message by invoking the closure only if messages are enabled.
73    ///
74    /// The closure is called only when a channel is configured, avoiding any allocation
75    /// or cloning overhead when messages are disabled. The closure returns a type that
76    /// implements `Into<Message>`, allowing module-specific message types to be used
77    /// directly.
78    ///
79    /// # Example
80    ///
81    /// ```ignore
82    /// reporter.report(|| ResolutionMessage::cache_miss(&spec));
83    /// ```
84    pub fn report<F, T>(&self, f: F)
85    where
86        F: FnOnce() -> T,
87        T: Into<Message>,
88    {
89        if let Self::Channel(sender) = self {
90            let msg = f().into();
91            let _ = sender.send(msg);
92        }
93    }
94
95    /// Returns true if message reporting is enabled (not null).
96    pub fn is_enabled(&self) -> bool {
97        matches!(self, Self::Channel(_))
98    }
99}