Skip to main content

origin_events/
platform.rs

1//! Events every Origin application shares.
2//!
3//! Products add their own enums (`GitHubEvent`, `AnalyticsEvent`, ...) and publish
4//! them on the same bus.
5
6use crate::bus::Event;
7use origin_domain::{AccountId, Alert, AlertId, ConnectorId, ErrorKind, JobId, JobStatus, SyncId};
8use serde::{Deserialize, Serialize};
9use time::OffsetDateTime;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
13pub struct SyncCompleted {
14    pub sync: SyncId,
15    pub connector: ConnectorId,
16    pub account: AccountId,
17    /// How many records changed. `0` means the service reported no change.
18    pub changed: u64,
19    #[serde(with = "time::serde::rfc3339")]
20    #[cfg_attr(feature = "ts", ts(type = "string"))]
21    pub at: OffsetDateTime,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
26pub struct SyncFailed {
27    pub sync: SyncId,
28    pub connector: ConnectorId,
29    pub account: AccountId,
30    pub kind: ErrorKind,
31    pub message: String,
32    /// When the platform intends to try again, if it does.
33    #[serde(with = "time::serde::rfc3339::option")]
34    #[cfg_attr(feature = "ts", ts(type = "string | null"))]
35    pub retry_at: Option<OffsetDateTime>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
40pub struct AlertRaised {
41    pub alert: Alert,
42    /// `true` when an alert with the same fingerprint was already active, so
43    /// notification sinks can stay quiet.
44    pub deduplicated: bool,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
49pub struct AlertResolved {
50    pub alert: AlertId,
51    #[serde(with = "time::serde::rfc3339")]
52    #[cfg_attr(feature = "ts", ts(type = "string"))]
53    pub at: OffsetDateTime,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
58pub struct AccountExpired {
59    pub account: AccountId,
60    pub connector: ConnectorId,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
65pub struct JobStarted {
66    pub job: JobId,
67    pub kind: String,
68}
69
70/// Progress of a running job.
71///
72/// Deliberately throttled by the job registry: a job that reports every one of ten
73/// thousand steps would flood the bus and make slow subscribers lag, losing the
74/// *finished* event they actually care about.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
77pub struct JobProgress {
78    pub job: JobId,
79    pub current: u64,
80    pub total: Option<u64>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
85pub struct JobFinished {
86    pub job: JobId,
87    pub kind: String,
88    pub status: JobStatus,
89    pub error: Option<String>,
90}
91
92/// The platform-level event enum.
93///
94/// Adding a variant is a breaking change for exhaustive subscribers — deliberately so.
95#[derive(Debug, Clone, Serialize, Deserialize)]
96#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
97#[serde(tag = "type", rename_all = "snake_case")]
98pub enum PlatformEvent {
99    SyncCompleted(SyncCompleted),
100    SyncFailed(SyncFailed),
101    AlertRaised(AlertRaised),
102    AlertResolved(AlertResolved),
103    AccountExpired(AccountExpired),
104    JobStarted(JobStarted),
105    JobProgress(JobProgress),
106    JobFinished(JobFinished),
107}
108
109impl Event for PlatformEvent {
110    fn name(&self) -> &'static str {
111        match self {
112            Self::SyncCompleted(_) => "platform.sync.completed",
113            Self::SyncFailed(_) => "platform.sync.failed",
114            Self::AlertRaised(_) => "platform.alert.raised",
115            Self::AlertResolved(_) => "platform.alert.resolved",
116            Self::AccountExpired(_) => "platform.account.expired",
117            Self::JobStarted(_) => "platform.job.started",
118            Self::JobProgress(_) => "platform.job.progress",
119            Self::JobFinished(_) => "platform.job.finished",
120        }
121    }
122}