Skip to content

feat: implement sibling task spawning with automatic parent-ID inheritance#89

Merged
deepjoy merged 2 commits into
mainfrom
spawn_sibling
Mar 25, 2026
Merged

feat: implement sibling task spawning with automatic parent-ID inheritance#89
deepjoy merged 2 commits into
mainfrom
spawn_sibling

Conversation

@deepjoy
Copy link
Copy Markdown
Owner

@deepjoy deepjoy commented Mar 25, 2026

Summary

  • Add DomainTaskContext::spawn_sibling_with() and spawn_siblings_with() so child tasks can spawn peer tasks under the same parent without manually threading the orchestrator's task ID
  • Add DomainSubmitBuilder::sibling_of() for cross-domain sibling spawning
  • Add ModuleHandle::submit_batch() for single-transaction batch submissions, and wire spawn_children_with through it as a perf improvement
  • Add TaskRecord::remaining_ttl() for correct TTL inheritance from parent records
  • Re-export SiblingSpawnBuilder from crate root
  • Add quick-start docs section covering sibling spawning patterns

Closes #87

Motivation

When child executors need to spawn peer tasks (e.g. BFS directory scans), they previously had to manually extract parent_id from the context record and pass it to submit_with().parent(id). This was error-prone and verbose. The new spawn_sibling_with() API mirrors the existing spawn_child_with() ergonomics and returns StoreError::InvalidState if called from a root task, preventing silent creation of unparented tasks.

Changes

File Change
src/registry/domain_context.rs SiblingSpawnBuilder, spawn_sibling_with(), spawn_siblings_with()
src/domain.rs DomainSubmitBuilder::sibling_of() for cross-domain siblings
src/module.rs ModuleHandle::submit_batch() for single-transaction batch path
src/registry/context.rs Wire spawn_children_with through submit_batch
src/task/mod.rs TaskRecord::remaining_ttl() helper
src/task/submit_builder.rs SubmitBuilder::resolve_only() (crate-internal)
src/lib.rs Re-export SiblingSpawnBuilder, update module docs
docs/quick-start.md Sibling tasks section with examples and parent-relationship table
examples/test_sibling.rs Runnable example demonstrating orc → child → sibling flow
tests/integration/sibling_spawn.rs 685-line integration test suite covering inheritance, error cases, batch, cross-domain, priority aging, TTL, tags, dedup, and finalize paths

deepjoy added 2 commits March 24, 2026 18:42
…nce (#87)

Add SiblingSpawnBuilder and DomainTaskContext::spawn_sibling_with() /
spawn_siblings_with() so child tasks can spawn peer tasks under the same
parent without manually threading the orchestrator's task ID.

- SiblingSpawnBuilder routes through ModuleHandle for correct TTL/tag
  inheritance from the orchestrator (not the current task)
- ModuleHandle::submit_batch for single-transaction batch spawns
- DomainSubmitBuilder::sibling_of() for cross-domain sibling spawns
- Wire spawn_children_with through submit_batch (perf fix)
- Re-export SiblingSpawnBuilder from crate root
- Integration tests covering inheritance, error cases, batch, and
  cross-domain paths
@deepjoy deepjoy enabled auto-merge (squash) March 25, 2026 01:49
@deepjoy deepjoy merged commit 99af25b into main Mar 25, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Mar 25, 2026
deepjoy pushed a commit that referenced this pull request Mar 25, 2026
## 🤖 New release

* `taskmill`: 0.7.0 -> 0.7.1 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

## [0.7.1](v0.7.0...v0.7.1)
- 2026-03-25

### Added

- implement sibling task spawning with automatic parent-ID inheritance
([#89](#89))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark Comparison

Click to expand
group                                       main                                    pr
-----                                       ----                                    --
backoff_delay/constant                      1.00     43.5±0.07ns 438.1 MElem/sec    1.02     44.2±0.09ns 431.6 MElem/sec
backoff_delay/exponential                   1.05    196.9±0.64ns 96.9 MElem/sec     1.00    188.4±0.43ns 101.2 MElem/sec
backoff_delay/exponential_jitter            1.00    410.2±5.28ns 46.5 MElem/sec     1.11    454.6±6.40ns 42.0 MElem/sec
backoff_delay/linear                        1.00     75.9±0.17ns 251.2 MElem/sec    1.00     75.9±0.15ns 251.1 MElem/sec
batch_submit/1000                           1.00     32.9±2.46ms 29.7 KElem/sec     1.01     33.2±2.53ms 29.4 KElem/sec
byte_progress/byte_reporting_500            1.00    196.3±3.42ms  2.5 KElem/sec     1.03    202.0±5.48ms  2.4 KElem/sec
byte_progress/noop_500                      1.00    195.8±3.46ms  2.5 KElem/sec     1.03   201.9±10.22ms  2.4 KElem/sec
byte_progress_snapshot/100_tasks            1.00     85.5±2.76ms  1170 Elem/sec     1.02     87.1±2.82ms  1148 Elem/sec
concurrency_scaling/1                       1.00    603.8±8.94ms   828 Elem/sec     1.01    608.8±7.35ms   821 Elem/sec
concurrency_scaling/2                       1.00    383.6±9.11ms  1303 Elem/sec     1.02    392.0±5.89ms  1275 Elem/sec
concurrency_scaling/4                       1.00    233.4±4.11ms  2.1 KElem/sec     1.04    242.0±5.29ms  2.0 KElem/sec
concurrency_scaling/8                       1.00    195.1±3.47ms  2.5 KElem/sec     1.03    200.3±6.67ms  2.4 KElem/sec
count_by_tags/100                           1.00    124.0±2.87µs  7.9 KElem/sec     1.04    128.6±3.09µs  7.6 KElem/sec
count_by_tags/1000                          1.00    214.0±3.40µs  4.6 KElem/sec     1.01    215.4±4.19µs  4.5 KElem/sec
count_by_tags/5000                          1.01    600.3±4.83µs  1665 Elem/sec     1.00    593.3±4.36µs  1685 Elem/sec
dep_chain_dispatch/10                       1.00     15.0±0.31ms   668 Elem/sec     1.04     15.5±0.23ms   644 Elem/sec
dep_chain_dispatch/25                       1.00     36.9±0.62ms   676 Elem/sec     1.02     37.8±0.45ms   661 Elem/sec
dep_chain_dispatch/50                       1.00     73.6±2.24ms   678 Elem/sec     1.04     76.7±1.59ms   652 Elem/sec
dep_chain_submit/10                         1.00      3.0±0.09ms  3.3 KElem/sec     1.03      3.0±0.11ms  3.2 KElem/sec
dep_chain_submit/200                        1.00     75.9±3.02ms  2.6 KElem/sec     1.03     78.3±3.49ms  2.5 KElem/sec
dep_chain_submit/50                         1.00     16.4±0.74ms  3.0 KElem/sec     1.04     17.0±0.85ms  2.9 KElem/sec
dep_fan_in_dispatch/10                      1.00      6.9±0.13ms  1594 Elem/sec     1.04      7.2±0.16ms  1536 Elem/sec
dep_fan_in_dispatch/100                     1.00     42.3±0.83ms  2.3 KElem/sec     1.03     43.5±1.07ms  2.3 KElem/sec
dep_fan_in_dispatch/50                      1.00     22.4±0.58ms  2.2 KElem/sec     1.04     23.3±0.78ms  2.1 KElem/sec
dispatch_and_complete/1000                  1.00    392.9±5.67ms  2.5 KElem/sec     1.03    404.1±7.78ms  2.4 KElem/sec
dispatch_group_scaling/1                    1.00    411.2±9.10ms  1215 Elem/sec     1.05   432.3±19.24ms  1156 Elem/sec
dispatch_group_scaling/10                   1.00    420.1±5.95ms  1190 Elem/sec     1.03   431.5±11.15ms  1158 Elem/sec
dispatch_group_scaling/100                  1.00    418.9±5.42ms  1193 Elem/sec     1.03    431.4±6.96ms  1158 Elem/sec
dispatch_group_scaling/50                   1.00    418.6±5.23ms  1194 Elem/sec     1.03    430.6±7.48ms  1161 Elem/sec
dispatch_no_groups/500                      1.00    195.6±3.39ms  2.5 KElem/sec     1.01    198.5±3.95ms  2.5 KElem/sec
dispatch_one_group/500                      1.00    416.7±7.57ms  1200 Elem/sec     1.02    423.1±9.91ms  1181 Elem/sec
dispatch_permanent_failure/500              1.00    347.0±4.58ms  1440 Elem/sec     1.02    353.2±5.90ms  1415 Elem/sec
history_by_type/100                         1.01    218.8±5.83µs  4.5 KElem/sec     1.00    217.1±5.32µs  4.5 KElem/sec
history_by_type/1000                        1.00   780.8±50.63µs  1280 Elem/sec     1.06   826.9±42.56µs  1209 Elem/sec
history_by_type/5000                        1.00   779.0±37.17µs  1283 Elem/sec     1.01   787.3±48.36µs  1270 Elem/sec
history_query/100                           1.00   428.8±19.34µs  2.3 KElem/sec     1.02   435.7±21.13µs  2.2 KElem/sec
history_query/1000                          1.00   426.7±21.09µs  2.3 KElem/sec     1.03   441.3±23.43µs  2.2 KElem/sec
history_query/5000                          1.00   435.1±25.30µs  2.2 KElem/sec     1.00   433.5±26.09µs  2.3 KElem/sec
history_stats/100                           1.00    124.5±0.73µs  7.8 KElem/sec     1.00    125.0±0.77µs  7.8 KElem/sec
history_stats/1000                          1.00    189.7±0.97µs  5.1 KElem/sec     1.01    190.8±1.00µs  5.1 KElem/sec
history_stats/5000                          1.00    472.3±1.65µs  2.1 KElem/sec     1.00    473.9±1.81µs  2.1 KElem/sec
mixed_priority_dispatch/500                 1.00    235.0±4.07ms  2.1 KElem/sec     1.04   243.5±15.59ms  2.0 KElem/sec
peek_next/100                               1.00    118.3±1.83µs  8.3 KElem/sec     1.01    118.9±2.71µs  8.2 KElem/sec
peek_next/1000                              1.00    117.8±2.72µs  8.3 KElem/sec     1.01    118.7±2.88µs  8.2 KElem/sec
peek_next/5000                              1.00    118.0±2.77µs  8.3 KElem/sec     1.03    121.0±2.79µs  8.1 KElem/sec
query_ids_by_tags/100                       1.00    182.2±3.81µs  5.4 KElem/sec     1.02    185.4±2.98µs  5.3 KElem/sec
query_ids_by_tags/1000                      1.00   815.3±10.91µs  1226 Elem/sec     1.01   824.4±16.79µs  1213 Elem/sec
query_ids_by_tags/5000                      1.00      3.6±0.02ms   279 Elem/sec     1.04      3.7±0.08ms   268 Elem/sec
retryable_dead_letter/constant              1.00    108.7±1.02ms   919 Elem/sec     1.01    109.4±1.49ms   914 Elem/sec
retryable_dead_letter/exponential           1.00    108.2±0.99ms   924 Elem/sec     1.09   117.7±20.29ms   849 Elem/sec
retryable_dead_letter/exponential_jitter    1.00    108.0±0.85ms   925 Elem/sec     1.02    110.2±1.04ms   907 Elem/sec
retryable_dead_letter/linear                1.00    108.7±1.30ms   920 Elem/sec     1.01    109.7±0.90ms   911 Elem/sec
submit_dedup_hit/1000                       1.00    203.0±5.81ms  4.8 KElem/sec     1.02    207.1±6.46ms  4.7 KElem/sec
submit_tasks/1000                           1.00    178.6±5.76ms  5.5 KElem/sec     1.02    181.7±4.79ms  5.4 KElem/sec
submit_with_tags/0                          1.00     88.3±3.21ms  5.5 KElem/sec     1.01     89.5±2.90ms  5.5 KElem/sec
submit_with_tags/10                         1.00   238.3±12.40ms  2.0 KElem/sec     1.01   241.8±12.33ms  2.0 KElem/sec
submit_with_tags/20                         1.00   386.0±19.00ms  1295 Elem/sec     1.02   393.3±20.39ms  1271 Elem/sec
submit_with_tags/5                          1.00    164.1±7.47ms  3.0 KElem/sec     1.02    166.8±7.25ms  2.9 KElem/sec
tag_values/100                              1.00    129.9±3.17µs  7.5 KElem/sec     1.02    132.8±3.48µs  7.4 KElem/sec
tag_values/1000                             1.00    190.6±4.31µs  5.1 KElem/sec     1.01    192.6±3.04µs  5.1 KElem/sec
tag_values/5000                             1.01    455.3±4.83µs  2.1 KElem/sec     1.00    451.0±4.43µs  2.2 KElem/sec

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.

feat: spawn_sibling_with() to auto-inherit parent_id from spawning child

1 participant