Skip to content

refactor: migrate all tests/benches from TaskExecutor to TypedExecutor#66

Merged
deepjoy merged 1 commit into
mainfrom
make-tests-typesafe
Mar 21, 2026
Merged

refactor: migrate all tests/benches from TaskExecutor to TypedExecutor#66
deepjoy merged 1 commit into
mainfrom
make-tests-typesafe

Conversation

@deepjoy
Copy link
Copy Markdown
Owner

@deepjoy deepjoy commented Mar 21, 2026

Summary

  • Replace all usages of the untyped TaskExecutor trait with TypedExecutor<T> across every test, benchmark, and example, enforcing compile-time type safety for task payloads
  • Introduce a define_task! macro in integration test helpers to reduce boilerplate when declaring zero-payload TypedTask types
  • Update TaskContext::payload() to fall back to deserializing from JSON null, allowing unit-struct typed tasks (e.g. struct Noop;) submitted via raw TaskSubmission::new(...) to still resolve correctly
  • Migrate scheduler setup in tests from manual Scheduler::new() + TaskTypeRegistry construction to the Scheduler::builder() + Domain::task::<T>() API, matching the recommended public API surface

Changed files

  • src/registry/context.rspayload<T>() now falls back to serde_json::from_value(Null) when no payload blob is stored
  • src/registry/mod.rs — unit tests use Domain::task()into_module() to produce erased executors instead of directly constructing Arc<dyn ErasedExecutor> from TaskExecutor
  • src/module.rs — module-level test updated to use Domain + TypedExecutor
  • src/scheduler/tests.rs — all ~40 scheduler tests rewritten: typed domain/task structs, Scheduler::builder(), fully-qualified task type strings ("test::test", "parent::parent", etc.)
  • tests/integration/common.rsdefine_task! macro + ~20 shared typed task definitions; NoopExecutor, DelayExecutor, CountingExecutor now implement TypedExecutor<T> generically
  • tests/integration/*.rs — all integration tests migrated to typed API
  • benches/*.rs — all benchmarks migrated to typed API
  • examples/profile_dep_chain.rs — migrated to typed API

Eliminate all usage of the untyped `TaskExecutor` + `raw_executor` API
from tests, benchmarks, and examples in preparation for removing the
untyped public API.

- Convert 47 `impl TaskExecutor for` to `impl TypedExecutor<T> for`
- Convert 87 `.raw_executor("name", exec)` to `.task::<T>(exec)`
- Add `define_task!` macro in common.rs for zero-boilerplate task types
- Define ~35 TypedTask unit structs across test/bench files
- Make shared test executors generic: `impl<T: TypedTask> TypedExecutor<T>`
- Handle missing payloads in `TaskContext::payload()` by deserializing
  from JSON null (supports unit-struct tasks submitted without payload)

No public API changes. All 276 tests pass.
@deepjoy deepjoy enabled auto-merge (squash) March 21, 2026 00:04
@deepjoy deepjoy merged commit b14b5b6 into main Mar 21, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Mar 21, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark Comparison

Click to expand
group                                       current
-----                                       -------
backoff_delay/constant                      1.00     44.6±0.65ns        ? ?/sec
backoff_delay/exponential                   1.00    191.1±1.47ns        ? ?/sec
backoff_delay/exponential_jitter            1.00    451.5±6.50ns        ? ?/sec
backoff_delay/linear                        1.00     78.9±0.81ns        ? ?/sec
batch_submit_1000                           1.00     34.0±2.68ms        ? ?/sec
byte_progress/byte_reporting_500            1.00    249.9±9.43ms        ? ?/sec
byte_progress/noop_500                      1.00    246.1±3.86ms        ? ?/sec
byte_progress_snapshot_100_tasks            1.00     82.0±2.06ms        ? ?/sec
concurrency_scaling/1                       1.00    382.3±4.61ms        ? ?/sec
concurrency_scaling/2                       1.00    318.4±3.69ms        ? ?/sec
concurrency_scaling/4                       1.00    274.2±5.25ms        ? ?/sec
concurrency_scaling/8                       1.00    246.8±4.14ms        ? ?/sec
count_by_tags/100                           1.00    127.8±3.13µs        ? ?/sec
count_by_tags/1000                          1.00    216.3±3.64µs        ? ?/sec
count_by_tags/5000                          1.00    608.0±5.25µs        ? ?/sec
dep_chain_dispatch/10                       1.00     11.3±0.17ms        ? ?/sec
dep_chain_dispatch/25                       1.00     27.1±0.49ms        ? ?/sec
dep_chain_dispatch/50                       1.00     53.3±0.64ms        ? ?/sec
dep_chain_submit/10                         1.00      3.4±0.15ms        ? ?/sec
dep_chain_submit/200                        1.00     79.6±4.23ms        ? ?/sec
dep_chain_submit/50                         1.00     17.7±0.94ms        ? ?/sec
dep_fan_in_dispatch/10                      1.00      7.4±0.09ms        ? ?/sec
dep_fan_in_dispatch/100                     1.00     53.2±0.97ms        ? ?/sec
dep_fan_in_dispatch/50                      1.00     27.8±0.60ms        ? ?/sec
dispatch_and_complete_1000                  1.00    494.5±7.05ms        ? ?/sec
dispatch_group_scaling/1                    1.00    407.5±5.49ms        ? ?/sec
dispatch_group_scaling/10                   1.00    416.9±4.61ms        ? ?/sec
dispatch_group_scaling/100                  1.00    417.9±4.48ms        ? ?/sec
dispatch_group_scaling/50                   1.00    417.7±5.51ms        ? ?/sec
dispatch_no_groups_500                      1.00    244.0±4.05ms        ? ?/sec
dispatch_one_group_500                      1.00    411.9±7.92ms        ? ?/sec
dispatch_permanent_failure_500              1.00    367.3±4.72ms        ? ?/sec
history_by_type/100                         1.00   896.1±19.62µs        ? ?/sec
history_by_type/1000                        1.00   908.5±23.60µs        ? ?/sec
history_by_type/5000                        1.00   920.4±31.71µs        ? ?/sec
history_query/100                           1.00    540.8±8.91µs        ? ?/sec
history_query/1000                          1.00    548.3±9.13µs        ? ?/sec
history_query/5000                          1.00   558.9±14.83µs        ? ?/sec
history_stats/100                           1.00    149.1±1.12µs        ? ?/sec
history_stats/1000                          1.00    380.2±1.22µs        ? ?/sec
history_stats/5000                          1.00   1350.3±8.07µs        ? ?/sec
mixed_priority_dispatch_500                 1.00    273.6±4.59ms        ? ?/sec
peek_next/100                               1.00    121.7±2.48µs        ? ?/sec
peek_next/1000                              1.00    122.5±2.57µs        ? ?/sec
peek_next/5000                              1.00    125.2±2.67µs        ? ?/sec
query_by_tags/100                           1.00  1245.7±163.80µs        ? ?/sec
query_by_tags/1000                          1.00     10.6±1.47ms        ? ?/sec
query_by_tags/5000                          1.00     55.8±5.69ms        ? ?/sec
retryable_dead_letter/constant              1.00    149.4±2.02ms        ? ?/sec
retryable_dead_letter/exponential           1.00    149.7±2.58ms        ? ?/sec
retryable_dead_letter/exponential_jitter    1.00    149.6±2.00ms        ? ?/sec
retryable_dead_letter/linear                1.00    149.1±1.99ms        ? ?/sec
submit_1000_tasks                           1.00    184.4±4.87ms        ? ?/sec
submit_dedup_hit_1000                       1.00    242.4±8.69ms        ? ?/sec
submit_with_tags/0                          1.00     91.1±3.06ms        ? ?/sec
submit_with_tags/10                         1.00    241.7±8.60ms        ? ?/sec
submit_with_tags/20                         1.00   397.1±18.18ms        ? ?/sec
submit_with_tags/5                          1.00    169.3±7.92ms        ? ?/sec
tag_values/100                              1.00    136.4±3.85µs        ? ?/sec
tag_values/1000                             1.00    197.0±4.31µs        ? ?/sec
tag_values/5000                             1.00    457.6±6.21µs        ? ?/sec

deepjoy pushed a commit that referenced this pull request Mar 21, 2026
## 🤖 New release

* `taskmill`: 0.5.3 -> 0.6.0 (⚠ API breaking changes)

### ⚠ `taskmill` breaking changes

```text
--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/inherent_method_missing.ron

Failed in:
  DomainHandle::submit_raw, previously in file /tmp/.tmpZpSjOB/taskmill/src/domain.rs:502
  DomainHandle::submit_raw, previously in file /tmp/.tmpZpSjOB/taskmill/src/domain.rs:502
  Domain::raw_executor, previously in file /tmp/.tmpZpSjOB/taskmill/src/domain.rs:349
  Domain::raw_executor, previously in file /tmp/.tmpZpSjOB/taskmill/src/domain.rs:349
  TaskTypeRegistry::register, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/mod.rs:170
  TaskTypeRegistry::register_with_ttl, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/mod.rs:179
  TaskTypeRegistry::register_with_retry_policy, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/mod.rs:190

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/struct_missing.ron

Failed in:
  struct taskmill::registry::TaskContext, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/context.rs:29
  struct taskmill::TaskContext, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/context.rs:29

--- failure trait_missing: pub trait removed or renamed ---

Description:
A publicly-visible trait cannot be imported by its prior path. A `pub use` may have been removed, or the trait itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/trait_missing.ron

Failed in:
  trait taskmill::registry::TaskExecutor, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/mod.rs:56
  trait taskmill::TaskExecutor, previously in file /tmp/.tmpZpSjOB/taskmill/src/registry/mod.rs:56
```

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

<blockquote>

## [0.6.0](v0.5.3...v0.6.0)
- 2026-03-21

### Added

- [**breaking**] replace `&TaskContext` with `DomainTaskContext<D>` for
type-safe child spawning
([#68](#68))

### Other

- migrate all tests/benches from TaskExecutor to TypedExecutor
([#66](#66))
</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>
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