Skip to content

fix(automations): deduplicationId separator for us-east-1 QStash#3591

Merged
saddlepaddle merged 1 commit intomainfrom
qstash-dedup-separator
Apr 20, 2026
Merged

fix(automations): deduplicationId separator for us-east-1 QStash#3591
saddlepaddle merged 1 commit intomainfrom
qstash-dedup-separator

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Apr 20, 2026

Summary

Our prod QStash project (us-east-1) rejects `:` in `deduplicationId`:
`{"error":"DeduplicationId cannot contain ':'"}` — 400 from batchJSON.

Swap the separator to `` and switch from ISO8601 to epoch ms so the whole key is `[a-zA-Z0-9-]`. Idempotency semantics (minute-bucket uniqueness per automation) are unchanged.

Test plan

  • Deploy goes green
  • Evaluator fires without the DeduplicationId error; downstream dispatch messages appear in Upstash
  • Idempotency still holds — force a double-evaluator-tick and verify only one `automation_runs` row per `(automation_id, scheduled_for)`

Summary by cubic

Fixes QStash 400s in us-east-1 by changing the deduplicationId from ${automation.id}:${scheduledFor.toISOString()} to ${automation.id}_${scheduledFor.getTime()}. Uses _ and epoch ms so the key is alphanumeric/_/- only; idempotency is unchanged.

Written for commit 937f56a. Summary will update on new commits.

Summary by CodeRabbit

  • Chores
    • Updated internal deduplication mechanism for automation dispatches to improve processing efficiency.

QStash rejects ":" in deduplicationId ("DeduplicationId cannot contain
':'"). Swap the separator to "_" and drop the ISO8601 string for the
epoch ms so the whole key is [a-zA-Z0-9_-], which QStash accepts.

Same idempotency semantics — minute-bucket uniqueness per automation.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0eb094bc-684a-434e-90c4-5c6f977da985

📥 Commits

Reviewing files that changed from the base of the PR and between b2278b1 and 937f56a.

📒 Files selected for processing (1)
  • apps/api/src/app/api/automations/evaluate/route.ts

📝 Walkthrough

Walkthrough

The deduplication identifier format for QStash automation dispatch enqueueing has been modified. The key construction changed from ISO timestamp serialization with a colon delimiter to millisecond epoch time with an underscore delimiter.

Changes

Cohort / File(s) Summary
QStash Deduplication Key Format
apps/api/src/app/api/automations/evaluate/route.ts
Updated deduplicationId construction from ${automation.id}:${scheduledFor.toISOString()} to ${automation.id}_${scheduledFor.getTime()}, changing delimiter and timestamp representation format.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 A tick and a tock, the timestamp now springs,
From ISO strings to millisecond wings,
Underscores replace the colon's old song,
Deduplication keys marching strong! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers the problem statement, solution details, and test plan comprehensively, but does not follow the provided template structure with required sections. Restructure the description to follow the template: add explicit 'Type of Change' section (Bug fix), clarify 'Related Issues' if any, and format the test plan as verification steps.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the primary change: fixing QStash deduplicationId separator for us-east-1 region by changing format from colon to underscore.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch qstash-dedup-separator

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR fixes a 400 error from QStash us-east-1 that rejects : characters in deduplicationId. The separator in the deduplication key is changed from : to _, and the timestamp component is switched from ISO 8601 (which contains : in its time portion) to epoch milliseconds. The result is a key formatted as [uuid]_[epochMs] using only [a-zA-Z0-9_-] characters.

Key observations:

  • automation.id is a UUID (uuid() in the Drizzle schema), so it only contains hex chars and hyphens — no colons
  • scheduledFor.getTime() returns a plain integer (digits only)
  • _ is the new separator — valid in all QStash regions per the PR description
  • Idempotency semantics are preserved: bucketToMinute still truncates to the minute, so the same (automationId, minute-bucket) pair produces the same deduplicationId across duplicate evaluator ticks
  • The scheduledFor.toISOString() in the dispatch message body is unaffected — the colon restriction applies only to the deduplicationId field, not the request payload

Confidence Score: 5/5

Safe to merge — minimal, targeted fix with no edge cases or regressions.

The change is a single-line fix to the deduplicationId format. The new format uuid_epochMs is strictly within the [a-zA-Z0-9_-] character set that QStash us-east-1 accepts. Idempotency semantics are unchanged since bucketToMinute still produces the same minute-bucketed timestamp. The dispatch body ISO 8601 scheduledFor field is unaffected. No logic, security, or compatibility concerns.

No files require special attention.

Important Files Changed

Filename Overview
apps/api/src/app/api/automations/evaluate/route.ts Replaces colon separator and ISO 8601 timestamp with underscore separator and epoch ms in the QStash deduplicationId, resolving a 400 error from the us-east-1 region. Logic is correct and idempotency is preserved.

Sequence Diagram

sequenceDiagram
    participant Scheduler as QStash Scheduler
    participant Evaluate as evaluate route
    participant DB as Database
    participant QStash as QStash batchJSON

    Scheduler->>Evaluate: POST signed request
    Evaluate->>Evaluate: verify signature
    Evaluate->>DB: SELECT due automations
    DB-->>Evaluate: automation rows

    loop per automation
        Evaluate->>Evaluate: bucketToMinute → scheduledFor
        Evaluate->>Evaluate: deduplicationId = id_epochMs
    end

    Evaluate->>QStash: batchJSON with safe deduplicationId
    QStash-->>Evaluate: 200 OK

    Evaluate->>DB: advance nextRunAt or disable
    Evaluate-->>Scheduler: enqueued count
Loading

Reviews (1): Last reviewed commit: "fix(automations): use _ and epoch ms in ..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app

Thank you for your contribution! 🎉

@saddlepaddle saddlepaddle merged commit 6e204ba into main Apr 20, 2026
14 of 15 checks passed
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