Repository navigation
Description
At the moment, the order of operations in Worker.close is somewhat random and does not appear intentionally structured.
It reads roughly as follows:
- Update
self.statustoStatus.closing- Inform scheduler of status change
- Handle
PauseEventto prevent further tasks from being executed/gathered
- Stop
self.periodic_callbacks self.stop()- Purge workspace
- Close monitor
- Stop sync listeners
- Abort handshaking comms
- Stop async listeners in the background
- Run
BaseWorker.close(timeout=...)- Cancel
self.async_instructions - Wait for them to finish (with timeout)
- Cancel
- Teardown preloads
- Close extensions
- Maybe tell nanny to
close_gracefully - Teardown plugins
- Close worker-initialized clients
- Close scheduler RPC
- Stop services
- Wait a bit in case we’re using UCX
- Close batched stream by first sending
close-stream, then closing with a timeout - Shutdown executors (maybe wait with timeout)
- Close RPC
- Update status to
Status.closed ServerNode.close()- stop periodic_callbacks (again)
- stop monitor (again)
- stop listeners (again)
- Abort handshaking comms (again)
- Stop async listeners (again but blocking this time)
- Stop background_tasks
- close RPC (again)
- Close comms
- Remove
local_directoryfromsys.path
- Unwind
exit_stack
There are multiple issues with this:
- The workspace gets purged before plugins get torn down, which may remove data of an in-progress P2P shuffle and cause exceptions.
- It's generally hard to understand what state a worker is in at any given point in time
- Just to add to the confusion, some stuff is stopped multiple times.
As an alternative, I suggest the following rough order of operations:
- Inform the cluster that the worker is closing
- Inform scheduler
- Inform nanny
- Set
self.status = Status.closing
- Tear down any running "add-ins" while resources are still working
- plugins
- extensions
- services
- preloads
- Prevent new communications from being established
- Close existing comms
- Close local resources and clean up internal state
In particular, add-ins such as plugins should be torn down while the worker is still functional to allow them to take arbitrary actions such as informing the scheduler or initiating communications with other workers.
Note:
Timeouts are also a problem but should be tackled in a dedicated PR (see #7318, #7320).
Metadata
Metadata
Assignees
Labels
No labels
Activity
hendrikmakait commentedon Aug 2, 2023
An alternative to this would be to remove the worker from the scheduler ASAP, mimicking the case where a worker dies. Any necessary cluster-wide coordination would then be left to
SchedulerPlugins, andWorkerPlugins would be scoped to local teardown.hendrikmakait commentedon Aug 2, 2023
Fun fact: By stopping
periodic_callbacksin step 2, we also stop heartbeats and keep-alives. If closing the worker takes too long, its TTL will expire and the scheduler will triggerremove_workerregardless of how far along the worker is in its shutdown.fjetter commentedon Aug 3, 2023
+1
this is done by setting the status. I don't think we should do anything else at this stage.
overall the proposed ordering makes sense to me. I think the PCs have to be stopped between 2 and 3. PCs do need comms and we should stop them before closing them.