refactor(decorators): move _wrap_task into mixin#148
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Moves
_wrap_task(the closure that wraps task functions with hooks, middleware, proxies, and resource injection) and_get_middleware_chainfromQueueinpy_src/taskito/app.pytoQueueDecoratorMixininpy_src/taskito/mixins/decorators.py._wrap_taskwas already invoked fromQueueDecoratorMixin.task()(the@queue.taskdecorator); co-locating it removes the# type: ignore[attr-defined]on that call site and bringsapp.pyfrom 691 → 577 LOC. The mixin grows by ~140 lines.The audit recommended
mixins/lifecycle.py, but that mixin owns worker startup, banner, and heartbeat — orthogonal concerns. The decorator mixin is the actual consumer of_wrap_task, so it belongs there.Addresses recommendation 8 from the 2026-05-08 audit (
.claude/reports/audit-2026-05-08.md).Implementation notes
_emit_eventis provided byQueueEventsMixin. The decorator mixin gets a class-level callable annotation (_emit_event: Callable[..., None]) — not a stub method — so type checkers see it without overriding the real implementation through MRO. (An earlier draft used a stub method that silently shadowed the events-mixin implementation and broke workflow event delivery; the regression was caught locally.)Queueattributes that_wrap_taskreads (_interceptor,_proxy_registry,_proxy_metrics,_resource_runtime,_test_mode_active,_recipe_signing_key,_max_reconstruction_timeout,_global_middleware) are now declared as class-level annotations onQueueDecoratorMixin.app.pydrops six imports that were only used by_wrap_task(functools,run_maybe_async,_clear_context,current_job,reconstruct_args,cleanup_proxies,reconstruct_proxies). Those move to the decorator mixin.Test plan
cargo test --workspace— clean.cargo clippy --workspace— clean.uv run python -m pytest tests/python/— 506 passed, 9 skipped (no regressions).uv run mypy py_src/taskito/ tests/python/ --no-incremental— clean.uv run ruff check py_src/ tests/— clean.