@adonis-agora/durable 0.41.0 → 0.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @adonis-agora/durable
2
2
 
3
+ ## 0.41.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#202](https://github.com/DavideCarvalho/adonis-agora-durable/pull/202) [`573a198`](https://github.com/DavideCarvalho/adonis-agora-durable/commit/573a198ae5e1e69503f3a37d3b9817da07b038c4) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - A run is no longer counted, dead-lettered or executed twice when its turn settles while the orphan sweep is looking at it.
8
+
9
+ Port of the same race fixed in the NestJS core (nestjs-durable#331), seen there as intermittently hung durable chat turns where an in-process worker answers a dispatched step in a couple of milliseconds:
10
+
11
+ - **A turn releases its lease only after its settled state is written.** `runExecution` returned `this.settleRun(...)` (and `this.parkBlocked(...)`) without awaiting it inside `try … finally { releaseRunLock }`, so the `finally` ran first: a first turn that completed, failed or parked `blocked` sat unlocked while its row still read `running`, which is what `listOrphanedRuns` returns for a crashed turn. Every settle in that block is now `return await`ed. (The suspend settle was already awaited.)
12
+ - **`recoverIncomplete` decides on the run it locked, not the one it listed.** It trusted the listed `running` status: a run that settled between the listing and `tryLockRun` got a recovery attempt counted and, past `maxRecoveryAttempts`, an unconditional `dead` written over a completed or suspended run. It now re-reads the run under the lease and releases it again unless it still reads `running`. The dead-letter write is also conditional on `running`, so a lease-free `cancel()` landing after that re-read is not overwritten with `dead`.
13
+ - **A replay re-reads a `pending` remote step before acting on it.** With `remoteRedispatchMs` set, a replay that found its step pending in its start-of-execution snapshot stamped the lease by writing `{ ...snapshot, wakeAt }` back, overwriting a result that had landed since with `pending` and parking the run on a lease an hour out. The step is now re-read from the store first; a result that has landed is replayed instead.
14
+
3
15
  ## 0.41.0
4
16
 
5
17
  ### Minor Changes