Skip to content

refactor: fix audit findings — predicate mixin, runtime-config mixin, migration DDL#163

Merged
pratyush618 merged 6 commits into
masterfrom
refactor/health-fixes-2026-05-14
May 13, 2026
Merged

refactor: fix audit findings — predicate mixin, runtime-config mixin, migration DDL#163
pratyush618 merged 6 commits into
masterfrom
refactor/health-fixes-2026-05-14

Conversation

@pratyush618
Copy link
Copy Markdown
Collaborator

@pratyush618 pratyush618 commented May 13, 2026

Summary

  • fix(predicates) — Remove inline imports in AndPredicate/OrPredicate/NotPredicate.evaluate(). The cycle they defended against doesn't exist at runtime (evaluate.py only imports core under TYPE_CHECKING), so the import hoists cleanly to module scope.
  • test(predicates) — Add tests/core/test_predicates.py with 30 focused tests: combinator short-circuit semantics, fail-closed evaluation + metrics, JSON/string-DSL round-trips, built-in recipe behaviour, custom registration, and three queue integration tests.
  • refactor(predicates) — Pull 282 LOC out of app.py (901 -> 619) into a new QueuePredicateMixin. Owns predicate state init, list_predicates/predicate_for/register_predicate, and the enqueue/dispatch gating methods. Repeated _emit_event(...) blocks consolidated into small helpers.
  • refactor(mixins) — Split register_type, set_queue_rate_limit, set_queue_concurrency out of QueueDecoratorMixin (597 -> 533) into a new QueueRuntimeConfigMixin. Decorator surface stays focused; runtime knobs get their own home.
  • refactor(storage) — Share run_migrations() DDL via a new diesel_common/migrations.rs. sqlite/mod.rs drops 502 -> 126 LOC; postgres/mod.rs drops 508 -> 130 LOC. A Dialect struct holds the per-backend type substitutions; per-backend migration_alter retains dialect-specific idempotency.

Net LOC impact

File Before After Delta
py_src/taskito/app.py 901 619 -282
py_src/taskito/mixins/decorators.py 597 533 -64
crates/taskito-core/src/storage/sqlite/mod.rs 502 126 -376
crates/taskito-core/src/storage/postgres/mod.rs 508 130 -378
New mixins/predicates.py 348 +348
New mixins/runtime_config.py 87 +87
New diesel_common/migrations.rs 342 +342
New tests/core/test_predicates.py 390 +390

Net: existing files -1,100 LOC, new well-scoped files +1,167 LOC, with the duplication eliminated and one new test surface added.

Test plan

  • cargo check --workspace (default, +postgres, +redis,workflows,native-async) — all green
  • cargo test --workspace --features workflows — all green
  • cargo test --workspace --features postgres,workflows — all green
  • cargo clippy --workspace --features workflows -- -D warnings — clean
  • cargo fmt --all -- --check — clean
  • uv run maturin develop + uv run python -m pytest tests/ — 592 passed, 9 skipped (no regressions, +30 new predicate tests)
  • uv run ruff check py_src/ tests/ — clean
  • uv run mypy py_src/taskito/ tests/ --no-incremental — clean (201 files)

AndPredicate / OrPredicate / NotPredicate each imported
_resolve_outcome inside the evaluate() method body. The cycle they
were defending against doesn't exist at runtime — evaluate.py only
imports core under TYPE_CHECKING — so hoist the import to module scope.
30 tests covering the boolean combinators (And/Or/Not short-circuit
semantics and Defer/Cancel pass-through), fail-closed evaluation +
metric recording, JSON and string-DSL round-trips, recipe behaviour
(after/before/in_time_window/payload_matches/env_var_truthy), the
callable adapter, custom predicate registration, and three queue
integration tests for enqueue-time cancel/defer.
The predicate state (six instance dicts plus PredicateMetrics) and the
three gating methods (_apply_enqueue_predicate, _apply_dispatch_predicate,
_reenqueue_after_defer) plus the inspection / registration API
(list_predicates, predicate_for, register_predicate) all moved to a new
QueuePredicateMixin. Event-emission boilerplate was lifted into small
helpers on the mixin to remove the four repeated _emit_event(...) blocks.

app.py drops from 901 to 619 LOC; the mixin owns ~280 LOC of cohesive
predicate logic.
register_type, set_queue_rate_limit, and set_queue_concurrency are
runtime configuration knobs, not decorator surface. Moving them to a
dedicated QueueRuntimeConfigMixin pulls 64 LOC out of decorators.py
(597 -> 533) and gives the three queue-tuning APIs a coherent home
adjacent to the existing QueueSettingsMixin (dashboard key/value store).
Pull ~750 LOC of duplicated CREATE TABLE / CREATE INDEX / ALTER TABLE
DDL out of sqlite/mod.rs and postgres/mod.rs into a new shared module
crates/taskito-core/src/storage/diesel_common/migrations.rs.

A Dialect struct holds the per-backend type substitutions (BLOB vs
BYTEA, INTEGER vs BIGINT, REAL vs DOUBLE PRECISION, boolean defaults,
and the IF NOT EXISTS prefix on ALTER). Each backend now exposes a
short driver that walks create_tables / create_indexes /
alter_statements; per-backend migration_alter() retains the dialect-
specific idempotency behaviour (SQLite swallows 'duplicate column',
Postgres uses IF NOT EXISTS).

sqlite/mod.rs: 502 -> 126 LOC; postgres/mod.rs: 508 -> 130 LOC.
All cargo check / clippy / test combinations green; full Python
suite still passes (592 / 9 skipped).
Bumps the four workspace crates (taskito-core, taskito-python,
taskito-workflows, taskito-async), the pyproject.toml project version,
and the importlib.metadata fallback in py_src/taskito/__init__.py.
Adds a 0.12.2 changelog entry summarising the audit-driven refactors
landing in this release: predicate inline-import fix, QueuePredicateMixin
and QueueRuntimeConfigMixin extractions, shared migration DDL via
diesel_common/migrations.rs, and the new tests/core/test_predicates.py
unit + integration suite.
@github-actions github-actions Bot added the docs label May 13, 2026
@pratyush618 pratyush618 merged commit c39db4c into master May 13, 2026
22 checks passed
@pratyush618 pratyush618 deleted the refactor/health-fixes-2026-05-14 branch May 13, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant