Skip to content

Commit 2d0c23b

Browse files
committed
refactor: trim job framework comments
1 parent 1b489ae commit 2d0c23b

9 files changed

Lines changed: 32 additions & 68 deletions

File tree

core/src/structs/job.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ use crate::errors::ConversionError;
1111
use crate::structs::invert_timestamp_ms;
1212
use crate::types::{Key, UserId};
1313

14-
/// Version prefix inside the `jobs` keyspace. A single decode chokepoint plus this
15-
/// prefix keep the record wrappable in a version envelope later (#286) as a
16-
/// one-site change.
14+
/// Version prefix keeping the record wrappable in a version envelope later (#286).
1715
pub const JOB_RECORD_KEY_PREFIX: &[u8] = b"jobs-v1/";
1816

1917
pub const JOB_DUE_INDEX_PREFIX: &[u8] = b"due/";
@@ -107,10 +105,8 @@ impl JobState {
107105
/// `DocumentSyncOutboxEvent`. Additive-only until a version envelope lands (#286).
108106
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
109107
pub enum JobPayload {
110-
/// Test-only executor exercising the substrate before #256 ships a real
111-
/// payload. Idempotency key: the `cleanup_marker` file path — a re-driven or
112-
/// cancelled Probe removes that file, so partial state is always reconciled by
113-
/// re-running from scratch.
108+
/// Test-only executor. Idempotency key: the `cleanup_marker` file, which a
109+
/// re-driven or cancelled Probe removes so re-running from scratch is safe.
114110
Probe {
115111
steps: u32,
116112
step_sleep_ms: u64,
@@ -212,8 +208,7 @@ impl JobProgress {
212208
}
213209
}
214210

215-
/// Lease held by the executor currently owning the job. `claim_token` fences
216-
/// zombie executors: every executor-side write requires it to match.
211+
/// Lease on the job; `claim_token` fences zombie executors on every write.
217212
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
218213
pub struct JobClaim {
219214
pub holder_node_id: NodeId,

operations/src/jobs/drain.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ pub struct JobDrainResult {
2727
pub next_due_after: Option<Duration>,
2828
}
2929

30-
/// Claim up to `capacity` due jobs and re-queue expired leases. Never runs a job
31-
/// inline: claimed records are returned for the caller to hand to the runtime.
30+
/// Claim up to `capacity` due jobs and re-queue expired leases; claimed records are returned.
3231
pub async fn process_job_queue_batch(
3332
storage: &StorageHandle,
3433
holder_node_id: NodeId,
@@ -77,8 +76,7 @@ pub async fn process_job_queue_batch(
7776
Ok(result)
7877
}
7978

80-
/// Earliest `due/` or `lease/` head as a delay from now; `ZERO` when work is
81-
/// already due.
79+
/// Earliest `due/`/`lease/` head as a delay from now; `ZERO` when work is due.
8280
pub async fn next_job_drain_timer_after(
8381
storage: &StorageHandle,
8482
) -> Result<Option<Duration>, String> {
@@ -94,8 +92,7 @@ pub async fn next_job_drain_timer_after(
9492
Ok(next.map(|ts| Duration::from_millis(ts.saturating_sub(now_ms))))
9593
}
9694

97-
/// ShortenTimer restore run at startup and inside the durable-queue re-arm loop, so
98-
/// it must never push an existing deadline later.
95+
/// ShortenTimer restore (startup + re-arm loop); never pushes a deadline later.
9996
pub async fn restore_job_queue_timer(storage: &StorageHandle, task_handle: &TaskHandle) {
10097
let after = match next_job_drain_timer_after(storage).await {
10198
Ok(Some(after)) => after,

operations/src/jobs/mod.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,15 @@ pub mod service;
88
pub mod store;
99
pub mod submit;
1010

11-
/// Lease held by a claiming executor. A claim is fenced by its `claim_token`; a
12-
/// zombie executor whose lease lapsed and whose job was re-claimed has every write
13-
/// rejected.
11+
/// Claim lease; fenced by `claim_token` so a lapsed holder's writes are rejected.
1412
pub const JOB_LEASE_MS: u64 = 60_000;
15-
/// Executor heartbeat interval. Each renew piggybacks a progress flush; must stay
16-
/// well under `JOB_LEASE_MS`.
13+
/// Heartbeat interval (renew + progress flush); must stay well under the lease.
1714
pub const JOB_HEARTBEAT_MS: u64 = 20_000;
1815
/// Maximum jobs executing locally at once; excess stays queued.
1916
pub const JOB_CONCURRENCY_CAP: usize = 8;
20-
/// Attempts (inclusive) before a retryable failure becomes terminal `Failed`.
17+
/// Attempts before a retryable failure becomes terminal `Failed`.
2118
pub const JOB_MAX_ATTEMPTS: u32 = 5;
22-
/// Uniform terminal-state retention before a job record is pruned.
19+
/// Uniform terminal-state retention before pruning.
2320
pub const JOB_RETENTION_MS: u64 = 7 * 24 * 60 * 60 * 1000;
2421
/// Minimum spacing between throttled progress flushes.
2522
pub const JOB_PROGRESS_FLUSH_INTERVAL_MS: u64 = 500;

operations/src/jobs/prune.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ pub(crate) async fn process_job_prune_batch_with_page_size(
9595
})
9696
}
9797

98-
/// ShortenTimer restore keyed off the earliest `prune/` entry, run at startup and
99-
/// in the durable-queue re-arm loop.
98+
/// ShortenTimer restore keyed off the earliest `prune/` entry.
10099
pub async fn restore_job_prune_timer(storage: &StorageHandle, task_handle: &TaskHandle) {
101100
let after = match first_schedule_entry(storage, JOB_PRUNE_INDEX_PREFIX).await {
102101
Ok(Some((expiry_ms, _))) => {

operations/src/jobs/runtime.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ struct RunningJob {
3636
completion: watch::Sender<bool>,
3737
}
3838

39-
/// Registry of locally executing jobs: the cancellation tokens, the completion
40-
/// signals backing `wait_for_terminal`, and the concurrency cap.
39+
/// Registry of locally executing jobs, their cancellation tokens, and the concurrency cap.
4140
pub struct JobsRuntime {
4241
running: Mutex<HashMap<JobId, RunningJob>>,
4342
cap: usize,
@@ -72,8 +71,7 @@ impl JobsRuntime {
7271
self.cap.saturating_sub(self.running_count())
7372
}
7473

75-
/// Poke a locally running job's cancellation token. Returns `false` if the job
76-
/// is not running here; the persisted `cancel_requested` flag then drives it.
74+
/// Poke a locally running job's cancel token; `false` if it is not running here.
7775
pub fn request_cancel(&self, job_id: JobId) -> bool {
7876
match self
7977
.running
@@ -124,8 +122,7 @@ impl JobsRuntime {
124122
}
125123
}
126124

127-
/// Block until the job is terminal or `timeout` elapses. Uses the local
128-
/// completion signal when the job runs here, else polls storage every 250ms.
125+
/// Block until the job is terminal or `timeout` elapses (local signal, else 250ms poll).
129126
pub async fn wait_for_terminal(
130127
&self,
131128
storage: &StorageHandle,
@@ -159,8 +156,7 @@ impl JobsRuntime {
159156
}
160157
}
161158

162-
/// Fjall is single-process, so at startup every claimed/running job's holder is
163-
/// definitionally dead: re-queue them all immediately.
159+
/// At startup every claimed/running holder is definitionally dead: re-queue them all.
164160
pub async fn recover_stale_jobs(&self, storage: &StorageHandle) -> Result<usize, String> {
165161
let now_ms = unix_timestamp_millis();
166162
let mut job_ids = Vec::new();
@@ -462,8 +458,7 @@ mod tests {
462458
std::fs::write(&marker, b"partial").unwrap();
463459
let mut record = probe_record(job_id, 5, 0, Some(marker.to_str().unwrap().to_string()));
464460
record.cancel_requested = true;
465-
// A prior attempt means partial state is possible, so the job is claimed and
466-
// its cleanup hook runs (unlike a never-attempted fresh cancel).
461+
// A prior attempt means it is claimed (not fresh-cancelled) so cleanup runs.
467462
record.attempts = 1;
468463
let claimed = claim(&storage, record).await;
469464

operations/src/jobs/service.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ use super::store::{
1313
use super::submit::schedule_job_drain_effect;
1414
use crate::driver::DriverContext;
1515

16-
/// API-facing helpers so REST handlers never orchestrate storage or task effects
17-
/// directly (enforced by the api effect-boundary guard).
16+
/// API-facing helpers so REST handlers never orchestrate storage/task effects directly.
1817
pub async fn list_owned_jobs(
1918
context: &DriverContext,
2019
user_id: UserId,

operations/src/jobs/store.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ use crate::queue_backoff::queue_retry_after_ms;
2323
type JobWrites = Vec<(KeySpace, Key, Value)>;
2424
type JobDeletes = Vec<(KeySpace, Key)>;
2525

26-
/// Single decode chokepoint for persisted job records. Wrapping the record in a
27-
/// version envelope later (#286) is a one-site change here.
26+
/// Single decode chokepoint; wrappable in a version envelope later (#286).
2827
pub fn decode_job_record(bytes: &[u8]) -> Result<JobRecord, ConversionError> {
2928
JobRecord::from_bytes(bytes)
3029
}
@@ -41,8 +40,7 @@ pub enum JobMutationError {
4140
Storage(String),
4241
}
4342

44-
/// The single schedule-index entry for a record follows its state: queued jobs
45-
/// live under `due/`, claimed/running under `lease/`, terminal under `prune/`.
43+
/// Schedule-index key by state: queued -> due/, claimed/running -> lease/, terminal -> prune/.
4644
fn schedule_index_key_for(record: &JobRecord) -> Key {
4745
match record.state {
4846
JobState::Queued => job_due_index_key(record.due_at_ms, record.job_id),
@@ -65,9 +63,7 @@ fn empty_value() -> Value {
6563
ByteView::from(Vec::new())
6664
}
6765

68-
/// Storage writes for creating a fresh job: record + schedule index + owner index
69-
/// (+ dedup index when a key is set). This is the composable primitive a producer
70-
/// can splice into its own transaction; the ≤4 writes of the submit budget.
66+
/// Writes creating a fresh job (<=4 keys); composable into a producer transaction.
7167
pub fn job_insert_entries(record: &JobRecord) -> Result<JobWrites, ConversionError> {
7268
let mut writes = vec![
7369
(
@@ -96,8 +92,7 @@ pub fn job_insert_entries(record: &JobRecord) -> Result<JobWrites, ConversionErr
9692
Ok(writes)
9793
}
9894

99-
/// Record + owner index + prune index deletes for a pruned terminal job. The
100-
/// dedup entry was already removed when the job first went terminal.
95+
/// Deletes for a pruned terminal job (its dedup entry is already gone).
10196
pub fn job_prune_delete_entries(record: &JobRecord) -> JobDeletes {
10297
vec![
10398
(JOB_KEYSPACE.to_string(), job_record_key(record.job_id)),
@@ -160,9 +155,7 @@ fn guard_token(record: &JobRecord, token: Ulid) -> Result<(), JobMutationError>
160155
}
161156
}
162157

163-
/// Read a job under a write transaction, apply `mutate`, and persist the record
164-
/// plus its index deltas atomically. State changes are validated by the pure
165-
/// transition guard so index and record can never disagree.
158+
/// Read, mutate, and persist a job with its index deltas in one transaction.
166159
pub async fn mutate_job<F>(
167160
storage: &StorageHandle,
168161
job_id: JobId,
@@ -249,8 +242,7 @@ pub enum ClaimOutcome {
249242
NotEligible,
250243
}
251244

252-
/// Claim a queued job for `holder_node_id`, or move a never-attempted
253-
/// cancel-requested job straight to `Cancelled`.
245+
/// Claim a queued job, or cancel it directly if it was never-attempted and cancel-requested.
254246
pub async fn claim_job(
255247
storage: &StorageHandle,
256248
job_id: JobId,
@@ -414,10 +406,8 @@ pub enum RequeueOutcome {
414406
Skipped,
415407
}
416408

417-
/// Return a claimed/running job to the queue with `queue_retry_after_ms` backoff, or
418-
/// move it to `Failed` once it has exhausted `JOB_MAX_ATTEMPTS`. `token` is `None`
419-
/// for the lease-expiry sweep and startup recovery, which reclaim whatever holder is
420-
/// recorded.
409+
/// Re-queue with backoff, or fail once `JOB_MAX_ATTEMPTS` is spent. `token` is `None`
410+
/// for the lease sweep and startup recovery.
421411
pub async fn requeue_job(
422412
storage: &StorageHandle,
423413
job_id: JobId,
@@ -461,8 +451,7 @@ pub enum CancelRequestOutcome {
461451
AlreadyTerminal(JobRecord),
462452
}
463453

464-
/// Set `cancel_requested` without changing state. Idempotent; a terminal job is a
465-
/// no-op returning the current record.
454+
/// Idempotently set `cancel_requested`; a terminal job is a no-op.
466455
pub async fn set_cancel_requested(
467456
storage: &StorageHandle,
468457
job_id: JobId,
@@ -485,8 +474,7 @@ pub async fn set_cancel_requested(
485474
})
486475
}
487476

488-
/// Owner-scoped listing, newest first, with an opaque 24-byte cursor and an
489-
/// optional server-side state filter applied per page.
477+
/// Owner-scoped listing, newest first, with an opaque cursor and optional state filter.
490478
pub async fn list_jobs_for_user(
491479
storage: &StorageHandle,
492480
user_id: UserId,
@@ -578,8 +566,7 @@ pub async fn iter_prefix_page(
578566
}
579567
}
580568

581-
/// Head of a schedule-index prefix, i.e. the earliest `(timestamp, job_id)` still
582-
/// enqueued under `due/`, `lease/`, or `prune/`.
569+
/// Earliest `(timestamp, job_id)` under a schedule-index prefix.
583570
pub async fn first_schedule_entry(
584571
storage: &StorageHandle,
585572
prefix: &[u8],

operations/src/jobs/submit.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ use tracing::warn;
1515

1616
use super::store::job_insert_entries;
1717

18-
/// Kick the drain so a freshly submitted job is claimed without waiting for the
19-
/// next poll. `DrainJobQueue` is re-armed from its own keyspace, so this timer is
20-
/// never persisted.
18+
/// Kick the drain so a submitted job is claimed promptly; this timer is never persisted.
2119
pub fn schedule_job_drain_effect() -> Effect {
2220
Effect::Task(TaskEffect::ResetTimer {
2321
key: TaskKey::DrainJobQueue,
@@ -61,9 +59,7 @@ enum SubmitState {
6159
Error,
6260
}
6361

64-
/// Effect-driven submit. Dedup follows the identity-key idempotency of
65-
/// `QueueBlobReplicationOperation`: a live job's presence in `job_dedup_index`
66-
/// (entries are removed on terminal transition) short-circuits to the existing id.
62+
/// Effect-driven submit; a live `job_dedup_index` entry short-circuits to the existing id.
6763
#[derive(Debug, PartialEq)]
6864
pub struct SubmitJobOperation {
6965
record: JobRecord,

operations/src/task_incoming.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,8 +1059,7 @@ impl OperationsTaskHandler {
10591059
self.jobs_runtime.spawn(self.context.clone(), record);
10601060
}
10611061

1062-
// When work is due but every slot is taken, wait for a completion kick
1063-
// rather than hot-looping on a ZERO re-arm.
1062+
// At capacity with work due, wait for a completion kick, not a ZERO hot-loop.
10641063
match result.next_due_after {
10651064
Some(after) if after.is_zero() && self.jobs_runtime.available_slots() == 0 => {
10661065
self.reschedule_timer(TaskKey::DrainJobQueue, JOB_DRAIN_RETRY_AFTER)

0 commit comments

Comments
 (0)