1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! The workflow-timeout sweep, which records the timeout of workflows nobody is running.
//!
//! Every executor of an application runs this loop. Each pass cancels the application's unsettled
//! workflows whose deadline has passed, whoever owns them and whichever unsettled status they are
//! in, so a workflow nobody is running still times out: an `ENQUEUED` or `DELAYED` child that
//! inherited its parent's deadline, or a `PENDING` workflow whose executor died. See
//! [`cancel_timed_out_workflows`](crate::sysdb::SystemDatabase::cancel_timed_out_workflows).
//!
//! A workflow running in this process usually doesn't wait for the sweep: its own timer ends the
//! body at the deadline, and the execution records the timeout itself once the database's clock
//! agrees it has passed. Only when that clock hasn't yet does the execution wait for the sweep. See
//! `run_until_deadline` and `time_out` in the workflow module.
use Arc;
use ;
use Duration;
use Instrument;
use crateExecutor;
use crate;
/// The most workflows one pass cancels. A full batch means more may be waiting, so the next pass
/// runs at once rather than after the interval.
const BATCH: i64 = 1000;
/// How long the sweep waits after a pass that didn't fill its batch.
const DEFAULT_INTERVAL: Duration = from_secs;
/// The interval [`set_interval`] chose, in milliseconds, or 0 for [`DEFAULT_INTERVAL`].
static INTERVAL_MS: AtomicU64 = new;
/// Sets how long every sweep started from now on waits between passes, in this process. For
/// tests, which would otherwise wait up to a second for each timeout they check; zero restores the
/// default. Not public API: reached through `dbos::__private`.
/// The interval a sweep started now waits between passes.
/// Starts the sweep, as a [`Role::Monitor`]: shutdown aborts it once the workflows have drained.
///
/// After the drain rather than with the producers, because a workflow still running may be waiting
/// on the sweep to record its timeout. Its own task rather than a step of the dequeue supervisor's
/// tick: back-to-back full batches would otherwise hold up queue reconciliation. Aborting the task
/// stops the loop; a statement the server already has may still commit, which cancels only rows
/// that had expired anyway. The next launch starts a fresh sweep.
pub
/// Runs passes until the task is aborted.
///
/// A failed pass is logged and the loop goes on: the next pass finds the same rows, and stopping
/// would leave every later deadline unenforced for the life of the executor.
async