Skip to content

fix(worker): prevent child tasks from blocking parent execution#1209

Closed
nicoloboschi wants to merge 4 commits into
mainfrom
feat/per-operation-slot-reservations
Closed

fix(worker): prevent child tasks from blocking parent execution#1209
nicoloboschi wants to merge 4 commits into
mainfrom
feat/per-operation-slot-reservations

Conversation

@nicoloboschi

Copy link
Copy Markdown
Collaborator

Summary

  • Workers used SyncTaskBackend which executed child tasks inline — e.g. consolidation triggered by retain would block until consolidation finished, tying up the worker slot for both operations
  • Add WorkerTaskBackend whose submit_task is a no-op: since _submit_async_operation already INSERTs the child row with task_payload, the poller picks it up on the next cycle as an independent task
  • Switch worker from SyncTaskBackend to WorkerTaskBackend

Test plan

  • test_worker_backend_does_not_execute_inline — verifies executor is never called by submit_task
  • test_sync_backend_blocks_parent_on_child_task — reproduces the blocking bug with SyncTaskBackend
  • test_worker_backend_does_not_block_parent_on_child_task — verifies parent completes without running child
  • test_worker_backend_child_task_stays_pending_in_db — e2e: parent completes, child stays pending, claimable on next poll

Add per-operation-type reserved slots so operators can guarantee capacity
for each operation type (retain, consolidation, file_convert_retain,
refresh_mental_model). Remaining slots form a shared pool usable by any
operation type.

New env vars:
- HINDSIGHT_API_WORKER_RETAIN_MAX_SLOTS (default 0)
- HINDSIGHT_API_WORKER_FILE_CONVERT_RETAIN_MAX_SLOTS (default 0)
- HINDSIGHT_API_WORKER_REFRESH_MENTAL_MODEL_MAX_SLOTS (default 0)
- HINDSIGHT_API_WORKER_CONSOLIDATION_MAX_SLOTS (default 2, unchanged)

Sum of reservations must be <= WORKER_MAX_SLOTS. Unreserved slots
(max_slots - sum) form the shared pool, usable by any operation type
on a first-come basis.
…l dict

Replace per-operation-type config fields with a single data-driven dict
(WORKER_SLOT_RESERVATION_TYPES) that maps operation types to their env
var and default. Adding a new operation type now requires only one line
in this dict — from_env(), validation, and the reservations dict are all
derived automatically.

Add test_all_operation_types_have_slot_reservation_config that parses
memory_engine.py and asserts every operation_type is covered, so adding
a new type without the config entry fails CI.
Workers used SyncTaskBackend which executed child tasks inline —
e.g. consolidation triggered by retain would block until consolidation
finished, tying up the worker slot for both operations.

Add WorkerTaskBackend whose submit_task is a no-op: since
_submit_async_operation already INSERTs the child row with task_payload,
the poller picks it up on the next cycle as an independent task.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant