Core: #[doc(hidden)] engine-side constructors for Job, StreamEvent, Schedule, Wake
Task core-engine-value-constructors (wave-3 pre-work). All four value types are #[non_exhaustive] (ADR-017 §3), so downstream engine crates cannot struct-literal-construct them (E0639). Give engines a sanctioned construction path without weakening the consumer posture: pub #[doc(hidden)] full-field constructors (Job::from_row, StreamEvent:: from_row, Schedule::new, Wake::new), each doc-commented as engine- construction-only — not contract surface, not covered by ADR-017's semver-minor field-addition promise; a field addition changes the signature and is a lockstep-duty event (ADR-017 §5). Core tests now construct through the new constructors; no behavior change.
This commit is contained in:
1 parent
1269246faf
commit
5474141f2b
7 files changed
+190
-37
No files matched your search
@@ -80,6 +80,62 @@ pub struct Job {
|
||||
}
|
||||
|
||||
impl Job {
|
||||
/// Engine-construction-only constructor taking the full field set.
|
||||
///
|
||||
/// # Contract posture
|
||||
///
|
||||
/// Not consumer API and not part of the contract surface: engines
|
||||
/// (in-repo, lockstep-updated with core) use it to build [`Job`]
|
||||
/// values from row data, since `#[non_exhaustive]` (ADR-017 §3)
|
||||
/// bans struct-literal construction downstream. Not covered by
|
||||
/// ADR-017's semver-minor field-addition promise — a `Job` field
|
||||
/// addition changes this signature, which is an engine breaking
|
||||
/// change under a core change and a lockstep-duty event
|
||||
/// (ADR-017 §5). Hidden from consumer-facing docs.
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_row(
|
||||
id: i64,
|
||||
queue: String,
|
||||
state: JobState,
|
||||
payload: Vec<u8>,
|
||||
priority: i64,
|
||||
run_at: i64,
|
||||
attempts: i64,
|
||||
max_attempts: i64,
|
||||
worker_id: Option<String>,
|
||||
claimed_at: Option<i64>,
|
||||
claim_expires_at: Option<i64>,
|
||||
created_at: i64,
|
||||
expires_at: Option<i64>,
|
||||
visibility_timeout_s: i64,
|
||||
backoff_base_s: i64,
|
||||
dead_letter_retention_s: Option<i64>,
|
||||
last_error: Option<String>,
|
||||
died_at: Option<i64>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
queue,
|
||||
state,
|
||||
payload,
|
||||
priority,
|
||||
run_at,
|
||||
attempts,
|
||||
max_attempts,
|
||||
worker_id,
|
||||
claimed_at,
|
||||
claim_expires_at,
|
||||
created_at,
|
||||
expires_at,
|
||||
visibility_timeout_s,
|
||||
backoff_base_s,
|
||||
dead_letter_retention_s,
|
||||
last_error,
|
||||
died_at,
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode the stored payload bytes into a concrete target type.
|
||||
///
|
||||
/// The stored bytes are the serde_json serialization of the
|
||||
|
||||
@@ -20,3 +20,27 @@ pub struct Schedule {
|
||||
/// engine defaults at each boundary fire (ADR-020 §3).
|
||||
pub opts: ScheduleOpts,
|
||||
}
|
||||
|
||||
impl Schedule {
|
||||
/// Engine-construction-only constructor taking the full field set.
|
||||
///
|
||||
/// # Contract posture
|
||||
///
|
||||
/// Not consumer API and not part of the contract surface: engines
|
||||
/// (in-repo, lockstep-updated with core) use it to build
|
||||
/// [`Schedule`] values from row data, since `#[non_exhaustive]`
|
||||
/// (ADR-017 §3) bans struct-literal construction downstream. Not
|
||||
/// covered by ADR-017's semver-minor field-addition promise — a
|
||||
/// `Schedule` field addition changes this signature, which is an
|
||||
/// engine breaking change under a core change and a lockstep-duty
|
||||
/// event (ADR-017 §5). Hidden from consumer-facing docs.
|
||||
#[doc(hidden)]
|
||||
pub fn new(name: String, spec: String, queue: String, opts: ScheduleOpts) -> Self {
|
||||
Self {
|
||||
name,
|
||||
spec,
|
||||
queue,
|
||||
opts,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,36 @@ pub struct StreamEvent {
|
||||
}
|
||||
|
||||
impl StreamEvent {
|
||||
/// Engine-construction-only constructor taking the full field set.
|
||||
///
|
||||
/// # Contract posture
|
||||
///
|
||||
/// Not consumer API and not part of the contract surface: engines
|
||||
/// (in-repo, lockstep-updated with core) use it to build
|
||||
/// [`StreamEvent`] values from row data, since
|
||||
/// `#[non_exhaustive]` (ADR-017 §3) bans struct-literal
|
||||
/// construction downstream. Not covered by ADR-017's
|
||||
/// semver-minor field-addition promise — a `StreamEvent` field
|
||||
/// addition changes this signature, which is an engine breaking
|
||||
/// change under a core change and a lockstep-duty event
|
||||
/// (ADR-017 §5). Hidden from consumer-facing docs.
|
||||
#[doc(hidden)]
|
||||
pub fn from_row(
|
||||
offset: i64,
|
||||
stream: String,
|
||||
key: Option<String>,
|
||||
payload: Vec<u8>,
|
||||
created_at: i64,
|
||||
) -> Self {
|
||||
Self {
|
||||
offset,
|
||||
stream,
|
||||
key,
|
||||
payload,
|
||||
created_at,
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode the stored payload bytes into a concrete target type.
|
||||
///
|
||||
/// The stored bytes are the serde_json serialization of the
|
||||
|
||||
@@ -330,12 +330,12 @@ impl Store for ProbeStore {
|
||||
_payload: Value,
|
||||
_opts: ScheduleOpts,
|
||||
) -> BoxedFuture<'a, Result<Schedule>> {
|
||||
Box::pin(std::future::ready(Ok(Schedule {
|
||||
name: "probe".into(),
|
||||
spec: "@every 60s".into(),
|
||||
queue: "q".into(),
|
||||
opts: ScheduleOpts::default(),
|
||||
})))
|
||||
Box::pin(std::future::ready(Ok(Schedule::new(
|
||||
"probe".into(),
|
||||
"@every 60s".into(),
|
||||
"q".into(),
|
||||
ScheduleOpts::default(),
|
||||
))))
|
||||
}
|
||||
fn unschedule<'a>(&'a self, _name: &str) -> BoxedFuture<'a, Result<bool>> {
|
||||
Box::pin(std::future::ready(Ok(false)))
|
||||
|
||||
@@ -51,36 +51,36 @@ fn schedule_opts_default_matches_enqueue_opts_twin_types() {
|
||||
}
|
||||
|
||||
fn sample_job(payload: Vec<u8>) -> Job {
|
||||
Job {
|
||||
id: 42,
|
||||
queue: "orders".to_string(),
|
||||
state: JobState::Dead,
|
||||
Job::from_row(
|
||||
42,
|
||||
"orders".to_string(),
|
||||
JobState::Dead,
|
||||
payload,
|
||||
priority: 7,
|
||||
run_at: 1000,
|
||||
attempts: 3,
|
||||
max_attempts: 3,
|
||||
worker_id: Some("w1".to_string()),
|
||||
claimed_at: Some(999),
|
||||
claim_expires_at: Some(1299),
|
||||
created_at: 900,
|
||||
expires_at: Some(5000),
|
||||
visibility_timeout_s: 300,
|
||||
backoff_base_s: 5,
|
||||
dead_letter_retention_s: None,
|
||||
last_error: Some("max attempts exceeded".to_string()),
|
||||
died_at: Some(1100),
|
||||
}
|
||||
7,
|
||||
1000,
|
||||
3,
|
||||
3,
|
||||
Some("w1".to_string()),
|
||||
Some(999),
|
||||
Some(1299),
|
||||
900,
|
||||
Some(5000),
|
||||
300,
|
||||
5,
|
||||
None,
|
||||
Some("max attempts exceeded".to_string()),
|
||||
Some(1100),
|
||||
)
|
||||
}
|
||||
|
||||
fn sample_event(payload: Vec<u8>) -> StreamEvent {
|
||||
StreamEvent {
|
||||
offset: 17,
|
||||
stream: "events".to_string(),
|
||||
key: Some("k".to_string()),
|
||||
StreamEvent::from_row(
|
||||
17,
|
||||
"events".to_string(),
|
||||
Some("k".to_string()),
|
||||
payload,
|
||||
created_at: 1234,
|
||||
}
|
||||
1234,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -173,9 +173,7 @@ fn stop_token_debug_shows_cancelled_state() {
|
||||
|
||||
#[test]
|
||||
fn wake_carries_only_the_channel() {
|
||||
let w = Wake {
|
||||
channel: "ch-1".to_string(),
|
||||
};
|
||||
let w = Wake::new("ch-1".to_string());
|
||||
assert_eq!(w.channel, "ch-1");
|
||||
assert_eq!(w.clone(), w);
|
||||
}
|
||||
@@ -20,3 +20,23 @@ pub struct Wake {
|
||||
/// The channel the wake was delivered on.
|
||||
pub channel: String,
|
||||
}
|
||||
|
||||
impl Wake {
|
||||
/// Engine-construction-only constructor taking the full field set.
|
||||
///
|
||||
/// # Contract posture
|
||||
///
|
||||
/// Not consumer API and not part of the contract surface: engines
|
||||
/// (in-repo, lockstep-updated with core) use it to build [`Wake`]
|
||||
/// values (including the Postgres engine's synthetic reconnect
|
||||
/// wake), since `#[non_exhaustive]` (ADR-017 §3) bans
|
||||
/// struct-literal construction downstream. Not covered by
|
||||
/// ADR-017's semver-minor field-addition promise — a `Wake` field
|
||||
/// addition changes this signature, which is an engine breaking
|
||||
/// change under a core change and a lockstep-duty event
|
||||
/// (ADR-017 §5). Hidden from consumer-facing docs.
|
||||
#[doc(hidden)]
|
||||
pub fn new(channel: String) -> Self {
|
||||
Self { channel }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user