use onemessagebus::Kind;
use serde::{Deserialize, Serialize};
pub use onemessagebus_agent::event::{
ArtifactRef, Envelope, EventFilter, Labels, Matcher as EventMatcher, Phase, Source,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum EventKind {
SessionOpened,
Fetch,
LockWait,
LockAcquired,
CommitPreserved,
BranchPreserved,
Push,
ChangeOpened,
ChangeDrafted,
DraftLifted,
ChangeDescribed,
ChangeCheck,
ChangeMerged,
MergeQueued,
MergeCompleted,
RecoveryAttested,
SyncConflict,
SessionClosed,
ReleaseProbed,
ReleaseAcknowledged,
ReleaseObserved,
}
impl EventKind {
fn wire(self) -> &'static str {
match self {
EventKind::SessionOpened => "session-opened",
EventKind::Fetch => "fetch",
EventKind::LockWait => "lock-wait",
EventKind::LockAcquired => "lock-acquired",
EventKind::CommitPreserved => "commit-preserved",
EventKind::BranchPreserved => "branch-preserved",
EventKind::Push => "push",
EventKind::ChangeOpened => "change-opened",
EventKind::ChangeDrafted => "change-drafted",
EventKind::DraftLifted => "draft-lifted",
EventKind::ChangeDescribed => "change-described",
EventKind::ChangeCheck => "change-check",
EventKind::ChangeMerged => "change-merged",
EventKind::MergeQueued => "merge-queued",
EventKind::MergeCompleted => "merge-completed",
EventKind::RecoveryAttested => "recovery-attested",
EventKind::SyncConflict => "sync-conflict",
EventKind::SessionClosed => "session-closed",
EventKind::ReleaseProbed => "release-probed",
EventKind::ReleaseAcknowledged => "release-acknowledged",
EventKind::ReleaseObserved => "release-observed",
}
}
fn named(kind: &Kind) -> Option<Self> {
Self::deserialize(
serde::de::value::StrDeserializer::<serde::de::value::Error>::new(kind.as_str()),
)
.ok()
}
}
impl From<EventKind> for Kind {
fn from(kind: EventKind) -> Self {
Kind::from(kind.wire())
}
}
pub trait PhaseOf {
fn of(kind: EventKind) -> Option<Phase>;
}
impl PhaseOf for Phase {
fn of(kind: EventKind) -> Option<Phase> {
Some(match kind {
EventKind::SessionOpened
| EventKind::Fetch
| EventKind::LockWait
| EventKind::LockAcquired
| EventKind::CommitPreserved
| EventKind::BranchPreserved
| EventKind::RecoveryAttested
| EventKind::SessionClosed => Phase::Development,
EventKind::MergeQueued | EventKind::MergeCompleted | EventKind::SyncConflict => {
Phase::Integrate
}
EventKind::ChangeOpened
| EventKind::ChangeDrafted
| EventKind::DraftLifted
| EventKind::ChangeDescribed
| EventKind::ChangeCheck
| EventKind::ChangeMerged => Phase::Review,
EventKind::ReleaseProbed
| EventKind::ReleaseAcknowledged
| EventKind::ReleaseObserved => Phase::Release,
EventKind::Push => return None,
})
}
}
pub(crate) fn phase_of(kind: EventKind) -> Phase {
Phase::of(kind).unwrap_or(Phase::Development)
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ArtifactId(pub String);
pub(crate) enum Line {
Known(Box<Known>),
Unknown(UnknownKind),
}
pub(crate) struct Known {
pub kind: EventKind,
pub envelope: Envelope,
}
pub(crate) struct UnknownKind {
pub v: u32,
pub ts: String,
pub stream: String,
pub kind: Kind,
}
impl Line {
pub(crate) fn read(line: &str) -> serde_json::Result<Self> {
serde_json::from_str(line).map(Self::of)
}
pub(crate) fn of(mut envelope: Envelope) -> Self {
let Some(kind) = EventKind::named(&envelope.kind) else {
return Line::Unknown(UnknownKind {
v: envelope.v,
ts: envelope.ts,
stream: envelope.stream,
kind: envelope.kind,
});
};
envelope
.dimensions
.phase
.get_or_insert_with(|| phase_of(kind));
Line::Known(Box::new(Known { kind, envelope }))
}
pub(crate) fn stream(&self) -> &str {
match self {
Line::Known(known) => &known.envelope.stream,
Line::Unknown(header) => &header.stream,
}
}
}