diff --git a/src/catchup/ApplyCheckpointWork.h b/src/catchup/ApplyCheckpointWork.h index ed43771dee..a937e27094 100644 --- a/src/catchup/ApplyCheckpointWork.h +++ b/src/catchup/ApplyCheckpointWork.h @@ -30,11 +30,11 @@ struct LedgerHeaderHistoryEntry; * check if ledger hashes are matching. * * In each run it skips or applies transactions from one ledger. Skipping occurs - * when ledger to by applied is older than LCL from local ledger. At LCL - * boundary checks are made - * to confirm that ledgers from files are knot up with LCL. If everything is OK, - * an apply ledger operation is performed. Then another check is made - if new - * local ledger matches corresponding ledger from file. + * when ledger to be applied is older than LCL from local ledger. At LCL + * boundary checks are made to confirm that ledgers from files knit up with + * LCL. If everything is OK, an apply ledger operation is performed. Then + * another check is made - if new local ledger matches corresponding ledger from + * file. * * Contructor of this class takes some important parameters: * * downloadDir - directory containing ledger and transaction files diff --git a/src/work/ConditionalWork.h b/src/work/ConditionalWork.h index d912e7bf3e..b754b466cb 100644 --- a/src/work/ConditionalWork.h +++ b/src/work/ConditionalWork.h @@ -8,8 +8,52 @@ namespace stellar { +// Any function used as a ConditionFn should be monotonic: return false for the +// first 0 or more times it's called, then if ever returns true, always return +// true thereafter. It will be called repeatedly until it returns true, but +// never again (it will actually be deleted once it returns true +// once). ConditionalWork makes its own lifecycle transitions and may call +// ConditionFn repeatedly; ConditionFn should not make any assumptions about the +// number of times or order in which it's called. using ConditionFn = std::function; +// A `ConditionalWork` is a work _gated_ on some arbitrary (and monotonic: see +// above) `ConditionFn`. It will remain in `WORK_WAITING` state polling the +// `ConditionFn` and rescheduling itself at `sleepTime` frequency until the +// `ConditionFn` is true, after which it will delegate to the `conditionedWork`. +// +// This exists to enable adding sequential dependency edges to work that is +// otherwise principally organized into parallel work units. +// +// For example, DownloadApplyTxsWork is _principally_ a BatchWork that runs as +// many of its yielded WorkSequence units in parallel as it can; but those units +// also have a sequential dependency among their second (apply) sub-steps, so +// those are each wrapped in a ConditionalWork, conditioned on the +// previously-yielded WorkSequence. This produces a picture like so: +// +// +// ┌────────────────────────────────┐ +// │DownloadApplyTxsWork : BatchWork│ +// └────────────────────────────────┘ +// │ +// ┌─────────────────┴────────────────┐ +// │ │ +// ▼ ▼ +// ┌───────────────────────────┐ ┌───────────────────────────┐ +// │WorkSequence │ │WorkSequence │ +// │ │ │ │ +// │┌─────────────────────────┐│ │┌─────────────────────────┐│ +// ││GetAndUnzipRemoteFileWork││ ││GetAndUnzipRemoteFileWork││ +// │└─────────────────────────┘│ │└─────────────────────────┘│ +// │┌─────────────────────────┐│◀──┐ │┌─────────────────────────┐│ +// ││ConditionalWork ││ │ ││ConditionalWork ││ +// ││┌───────────────────────┐││ │ ││┌───────────────────────┐││ +// │││ApplyCheckpointWork │││ └──┼┤│ApplyCheckpointWork │││ +// ││└───────────────────────┘││ ││└───────────────────────┘││ +// │└─────────────────────────┘│ │└─────────────────────────┘│ +// └───────────────────────────┘ └───────────────────────────┘ +// + class ConditionalWork : public BasicWork { ConditionFn mCondition;