Skip to content

fix!: 3.0 pre-release fixes for the core library (#130) - #132

Merged
CodingAnarchy merged 2 commits into
masterfrom
fix/130-prerelease-core
Oct 12, 2026
Merged

CodingAnarchy merged 2 commits into
masterfrom
fix/130-prerelease-core

Conversation

@CodingAnarchy

Copy link
Copy Markdown
Owner

Closes #130. Part of #122.

Pre-release fixes for the core library: six bugs and the cleanups listed in the issue.

Fixes

  1. Worker events without webhooks. Worker::with_event_manager, the event_manager field and the publish path in record_event were gated on webhooks. They now compile in every build, because the events module always does. Streaming-only builds and plain EventManager subscribers now get worker events. The worker event tests in worker_config_tests and payload_encryption_tests no longer need webhooks.
  2. Config sections of gated features. webhooks, streaming, alerting and metrics on HammerworkConfig are now #[serde(default)]. When a feature is off, a private Option<serde::de::IgnoredAny> placeholder (skip_serializing) detects the section. from_file then returns HammerworkError::Config("[alerting] is set but hammerwork was built without the alerting feature"). from_env reads no sections, so it needs no check. Tests cover a file saved without the sections loading in any build, and the rejection message for each compiled-out feature.
  3. TestQueue::set_throttle_config calls ThrottleConfig::validate. The shared throttle_configuration scenario now asserts the rejection on PG, MySQL and TestQueue.
  4. config::SimpleEventFilter is deleted, along with its mentions in the CHANGELOG and the upgrade guide.
  5. MySQL session-local time.
    • The key manager's MySQL SQL uses UTC_TIMESTAMP(6) instead of NOW(6) (12 sites).
    • Migration 021 now gives CURRENT_TIMESTAMP columns the expression default (UTC_TIMESTAMP(6)) (MySQL 8.0.13+, now documented). It drops ON UPDATE on hammerwork_queue_pause.updated_at; every library write to that table (pause_queue's insert and upsert) already set it explicitly, as 2.5.0 did.
    • The 021 guards also fire on a current_timestamp default or an on update extra, so a schema converted by the old 021 converges.
    • migration_datetime_tests now checks:
      • defaults are UTC from a +05:00 session;
      • updated_at is not auto-touched, and pause writes it;
      • a schema with the old defaults converges;
      • a re-run changes nothing.
  6. WorkerConfig::validate rejects batch_size 0 or above MAX_DEQUEUE_BATCH_SIZE, and batch_concurrency 0. Worker::with_hammerwork_config now runs config.worker.validate() too.

Cleanups

  • backend::dispatch_dequeue holds the 0/1/N dispatch and the MAX_DEQUEUE_BATCH_SIZE cap; PG, MySQL and TestQueue all use it. The caps inside claim_many are gone.
  • On PG and MySQL, a single weighted claim goes through fill_weighted_batch with room 1. MySQL's dequeue_with_priority_weights_inner is removed, and a runnable_levels helper replaces the duplicated levels query. The behaviour is the same:
    • same candidates and seeds (weighted_seed(queue, attempt));
    • the same move to the next level when a level comes back empty;
    • the same error propagation, since with room 1 nothing is ever claimed before an error.
  • Dead cfg(not(feature)) fallbacks are deleted, together with the always-true cfg(feature) attributes in those modules:
    • alerting.rs: the webhook and Slack stubs;
    • metrics.rs: the no-op collector and its test;
    • encryption/engine.rs: the "feature not enabled" branch;
    • webhooks.rs: the redundant attributes only.
  • WebhookManager::new and new_default return Result, and try_new is removed.
  • RateLimit::with_burst_limit returns Result and rejects 0. Worker::with_attempt_cap returns Result and rejects values below 1. Both follow the fallible style 3.0: remove legacy compatibility paths #90 used for RateLimit.

Not done

  • TestQueue does not use weighted_seed. It seeds from its mock clock, which keeps its picks deterministic under a frozen clock. The backends' weighted_seed hashes wall-clock nanoseconds and the thread id, so switching would make TestQueue picks non-deterministic. That is not provably the same behaviour, so it was left as is.
  • Other MySQL NOW(). It remains only in cargo-hammerwork/src/integration_tests/sql_query.rs:149,169 (MySQL test queries using DATE_SUB(NOW(), ...)). These were left for 3.0 pre-release: __private, requeue-stale scope, health lease rule, docs #131. hammerwork-web has no MySQL NOW().

Docs

  • CHANGELOG [Unreleased]: the breaking changes and fixes, plus an updated 021 Database entry.
  • Upgrade guide:
    • a new "Configuration sections and worker events" subsection under Feature flags;
    • notes under Batch mode, with_attempt_cap, MySQL 021 defaults and Zero rates (burst limit);
    • a new "WebhookManager::new returns a Result" subsection.
  • ? added to doc examples in docs/*.md for the now-fallible builders.

Testing

  • cargo fmt --all --check, cargo clippy --workspace --all-features --all-targets -D warnings, cargo check --examples --all-features and cargo doc --workspace --all-features --no-deps (with -D warnings) are all clean.
  • cargo clippy -p hammerwork --lib --tests --no-default-features -D warnings is clean for every one of these feature sets: "", postgres, mysql, streaming, kafka, kinesis, google-pubsub, alerting, metrics, webhooks, full, test-queue, postgres,streaming, encryption and mysql,webhooks.
  • PG suite: 2114 passed, 1 failed. MySQL suite: 233 passed, 1 failed. In both, the failure is queue_names_include_archived_queues, caused by leftover hunt_* / hunt3_q queues in the shared local databases. The database collation orders hunt_... before hunt3_q, while Rust byte order does the opposite. No code here touches that query.
  • The shared local MySQL DB was re-migrated: the 021_mysql_datetime row was deleted and migrations rerun. All DATETIME defaults now read utc_timestamp(6), and no ON UPDATE remains.

🤖 Generated with Claude Code

CodingAnarchy and others added 2 commits October 11, 2026 19:49
- Workers publish lifecycle events (Worker::with_event_manager) in every
  build, not only with `webhooks`.
- [webhooks], [streaming], [alerting] and [metrics] are optional config
  sections; in a build without the feature, from_file rejects the section
  with HammerworkError::Config naming the feature.
- TestQueue::set_throttle_config validates like the database backends.
- Remove config::SimpleEventFilter.
- MySQL key manager uses UTC_TIMESTAMP(6); migration 021 gives DATETIME
  columns (UTC_TIMESTAMP(6)) expression defaults, drops the ON UPDATE
  clause of hammerwork_queue_pause.updated_at, and converges schemas
  converted by its pre-release version.
- WorkerConfig::validate rejects batch_size 0 / above
  MAX_DEQUEUE_BATCH_SIZE and batch_concurrency 0;
  Worker::with_hammerwork_config validates the worker section.
- RateLimit::with_burst_limit(0), Worker::with_attempt_cap(<1) and
  WebhookManager::new (no panic; try_new removed) are fallible.
- Share the dequeue 0/1/N dispatch and cap across backends; single
  weighted claims reuse fill_weighted_batch; drop dead
  cfg(not(feature)) fallbacks in alerting, metrics and encryption.

Closes #130

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kend (#130)

PostgreSQL and MySQL sorted queue names by the database collation, so the
order differed between backends (and from TestQueue) and the regression test
depended on other data in the database. Sort and deduplicate in Rust.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CodingAnarchy
CodingAnarchy merged commit 64a49b9 into master Oct 12, 2026
21 checks passed
@CodingAnarchy
CodingAnarchy deleted the fix/130-prerelease-core branch October 12, 2026 00:07
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.

3.0 pre-release: events without webhooks, config sections, MySQL UTC, validation

1 participant