Skip to content

feat: casehub-work multi-instance WorkItem spawning — lineage, context, and casehub-work-adapter integration #212

@mdproctor

Description

@mdproctor

Summary

quarkus-work (quarkiverse/quarkus-work Epic #106) added multi-instance WorkItem spawning: a parent `WorkItem` atomically spawns N child `WorkItem` instances via `MultiInstanceSpawnService`, tracked by a `WorkItemSpawnGroup` with an M-of-N completion policy. This creates parent-child `WorkItem` hierarchies that need integration with casehub's lineage, context propagation, and completion tracking.

What quarkus-work added

  • `parentId` field on `WorkItem` — parent-child hierarchy (threaded inbox)
  • `WorkItemSpawnGroup` — tracks M-of-N completion policy for a spawned group
  • `MultiInstanceSpawnService` — creates parent + N children + spawn group atomically
  • `MultiInstanceCoordinator` — observes child completions, fires parent transition at threshold

Intersection with ADR-0007 epics

Lineage (#205)

When a casehub worker dispatches a `WorkItem` (via `WorkOrchestrator`) and that WorkItem spawns N children:

casehub WORKER_SCHEDULED entry
  → causedByEntryId → parent WorkItem ledger entry (WORKITEM_CREATED)
      → causedByEntryId → child[0] WorkItem ledger entry
      → causedByEntryId → child[1] WorkItem ledger entry
      → causedByEntryId → child[N] WorkItem ledger entry

Currently `casehub-work-adapter` sees parent WorkItem lifecycle events but not child WorkItem lifecycle events. It must be extended to:

  • Emit a ledger node per child WorkItem on spawn
  • Track M-of-N completion: when the `MultiInstanceCoordinator` fires parent completion, emit `WORKITEM_GROUP_COMPLETED` with `causedByEntryId` pointing to the parent's ledger entry

Context propagation (#204)

When a parent WorkItem spawns N children, each child may need a different context slice. Current `MultiInstanceSpawnService` handles assignment (`InstanceAssignmentStrategy`) but not context distribution. Options:

  • Broadcast: all children get the same context slice (the parent's inputMapping result)
  • Partitioned: each child gets a different key from the parent's context (e.g. child[i] gets `items[i]` from an array in CaseContext)
  • Template-driven: the `MultiInstanceConfig` declares an `inputMappingTemplate` JQ expression evaluated once per child with an index variable

The `ContextBridge` (to be defined in casehub-work) needs to support all three distribution strategies.

Cancellation and M-of-N completion (#210)

  • Parent casehub case cancelled → parent WorkItem cancelled → `MultiInstanceCoordinator` cancels all children
  • M-of-N children complete → coordinator fires parent transition → `casehub-work-adapter` fires casehub worker completion
  • If fewer than M children complete before a deadline → configurable policy (fault parent, or accept partial)

Changes required

casehub-work-adapter

  • Handle `WorkItemSpawnGroupCreatedEvent` (new) — emit parent ledger node with list of child IDs
  • Handle `WorkItemChildCreatedEvent` (new, to be added to quarkus-work-api) — emit child ledger node per child
  • Handle `WorkItemGroupCompletedEvent` (new) — integrate with M-of-N completion to fire casehub worker completion

quarkus-work-api (coordinate with quarkus-work)

  • `WorkItemSpawnGroupCreatedEvent` — fired when a multi-instance group is spawned
  • `WorkItemChildCompletedEvent` — fired when a child completes (carries parent context, M-of-N counter)

ContextBridge

  • Define in new `casehub-work-bridge` module (or extend casehub-work-adapter)
  • `initialise()`: create child WorkItem context from parent slice (one of: broadcast, partitioned, template-driven)
  • `complete()`: route child output back to correct context level (parent WorkItem's context, not root CaseContext)

Part of

#201 (adaptive execution epic, specifically epics #204 #205 #210)

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions