Commit cebe8a3
authored
fix(mothership): settle chat runs no controller owns (#8457)
* fix(mothership): settle Chat runs no controller will finish
A run whose process died before finalize, whose controller was superseded
with no successor, or that was stopped while no controller existed stayed
unfinished forever: its chat marker kept pointing at it, so the chat read
as busy and a reconnect polled a run nothing would ever end.
- Stop now settles the run as cancelled once no controller of its stream
holds the chat lock, including after it force-releases a controller that
did not exit in time.
- The stale-execution cron settles leased runs whose stream holds no chat
lock, has no replay buffer left, and has been idle past the orchestration
budget (so a reconnect has nothing left to resume), and runs without a
lease once idle for 24 hours. A run Stop already closed settles as
cancelled, any other as error; its chat marker is released.
- Each settle is one conditional update on the run row that requires it to
be unfinished, idle, and still naming the controller that was observed,
so a finalizing controller or a successor's claim wins or loses against
it atomically and the run settles exactly once.
* fix(mothership): lock chats before runs when settling orphans, and label them precisely
- Settling now locks the affected chat rows first, in id order, as a
controller's claim does. Locking the run and then the chat deadlocked
against a concurrent reconnect claim.
- Each sweep batch fails on its own, the chat markers of a batch clear in
one statement, and a sweep settles at most 5k rows with a short pause
between full batches.
- A run settles as cancelled only when its user pressed Stop. A newer turn
also closes tool admission on older runs, and those now settle as errors.
- Runs without a controller lease keep their last write as their
completion and retention time and read "never finalized (no controller
lease)".
- The leased-run grace no longer derives from the orchestration deadline.
Liveness comes only from the heartbeat-renewed chat lock; the grace and
the replay TTL only bound how long a reconnect can resume a dead run.
* fix(mothership): never sweep a current headless run
A headless turn has no chat lease and no heartbeat, so its age says nothing
about whether it is still running once runs have no deadline. The sweep's
lease-less rule now applies only to runs admitted before the current
tool-execution protocol: every run the current code admits records the
current version, so after a deploy no such row can be live. A current
headless run is left to its own lifecycle, which always settles it.
The protocol version moves beside the other async-run constants so the
sweep can read it without importing the repository.
* refactor(mothership): require the recorded Stop inside the stopped-run settle
- Settling a stopped run now passes the Stop-row check as the update's own
guard, so it cannot cancel a run nobody stopped; the separate stopped
branch is gone and every settle derives cancelled from the Stop row.
- Chat lock ownership is read through getChatStreamLockOwners and trusted
only when verified, instead of a second Redis read of the same keys.
- Settle transactions use the shared DbTransaction type.
* fix(mothership): fence orphan settlement on the chat lock and resume sweeps where they stopped
- The sweep takes each unowned leased run's chat lock under the run's own
stream before settling it and releases it after the commit, so a
reconnect can no longer lock the chat between the ownership check and
the settle and then lose its claim; a reconnect that meets the fence
retries.
- A sweep examines at most 10k candidates and settles at most about 5k,
resuming from a cursor saved in Redis and wrapping to the first run, so
runs that cannot be settled yet never starve the ones after them.
- Every settled run whose chat marker was released is announced, legacy
runs included, so an open client stops showing the chat as busy.
* fix(knowledge): record a terminal status for every Slack Assistant run
The Slack Assistant admits its own run row and only ever marked it as an
error, so every completed or stopped Slack turn stayed active. It now
records the terminal status once, after the turn ends, through the shared
run-status update: complete on success, cancelled when its user stopped
it (in Slack or in Sim), and error otherwise.
Every other run-creating path already settles its run: interactive turns
through their controller's finalize, and headless turns that admit their
own run in the lifecycle's own finally.
* fix(knowledge): record the Slack run's status after its turn is saved
- The Slack Assistant now writes its run's one terminal status after its
outcome and response are persisted, from the final outcome, so a failed
save ends the run as an error instead of complete.
- A Stop lookup that fails no longer skips that write: the turn is treated
as not stopped, logged, and settled as an error.
- The orphaned-run suite deletes the sweep cursor before each test and in
teardown, so no later suite starts from its leftover position.1 parent e09970a commit cebe8a3
9 files changed
Lines changed: 1338 additions & 4 deletions
File tree
- apps/sim
- app/api/cron/cleanup-stale-executions
- lib
- knowledge/application/slack-search
- mothership
- async-runs
- request
- application
- session
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
738 | 739 | | |
739 | 740 | | |
740 | 741 | | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
741 | 756 | | |
742 | 757 | | |
743 | 758 | | |
| |||
768 | 783 | | |
769 | 784 | | |
770 | 785 | | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
771 | 789 | | |
772 | 790 | | |
773 | 791 | | |
| |||
Lines changed: 287 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
Lines changed: 27 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
52 | 53 | | |
53 | 54 | | |
54 | 55 | | |
| |||
303 | 304 | | |
304 | 305 | | |
305 | 306 | | |
306 | | - | |
307 | 307 | | |
308 | 308 | | |
309 | 309 | | |
| |||
378 | 378 | | |
379 | 379 | | |
380 | 380 | | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
381 | 406 | | |
382 | 407 | | |
383 | 408 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
7 | 10 | | |
8 | 11 | | |
9 | 12 | | |
| |||
0 commit comments