fix(admin): env filter and honest count on DLQ replay (alt to #76)#85
fix(admin): env filter and honest count on DLQ replay (alt to #76)#85ravidsrk wants to merge 2 commits into
Conversation
dlq::replay collapsed the moved-row count to a bool, hiding how many rows an unscoped id match actually moved. Callers now see the count.
POST /admin/api/dlq/{job_id}/replay accepts an optional
?environment=<slug> filter mirroring the CLI's --env. The same job id
can be parked in more than one environment under the (environment_id,
id) key, and the unscoped handler replayed every copy while reporting
a hardcoded replayed: 1. Unfiltered replay keeps the documented
cross-environment reach but now reports the real moved count. Unknown
slugs 404 before any row moves.
Closes dodopayments#56
|
| Filename | Overview |
|---|---|
| server/src/api/admin.rs | Adds optional ?environment query param to replay_dead_letter; resolves slug to UUID before any DB mutation (correct fail-before-move order); returns real row count instead of hardcoded 1. |
| server/src/dlq.rs | Signature of replay changed from anyhow::Result to anyhow::Result, eliminating the moved > 0 collapse and exposing the real count. SQL CTE logic is unchanged. |
| server/src/main.rs | CLI updated to compare dlq::replay result against > 0 instead of treating it as a bool; clean one-line adaptation. |
| server/tests/redteam_dlq_env_scope.rs | Three new HTTP integration tests added over real Postgres covering scoped replay, unscoped multi-row count, and unknown-slug 404-before-move. |
| docs/openapi/chimely.yaml | Generated via pnpm generate; adds the optional environment query param and updates the 404 description. |
| packages/client/src/generated/api.d.ts | Generated TypeScript types updated to reflect the optional environment query parameter and revised 404 description. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client
participant Handler as replay_dead_letter
participant DB as Postgres
Client->>Handler: "POST /admin/api/dlq/{job_id}/replay?environment=slug"
Handler->>Handler: parse_typeid(job_id) - 404 on bad format
alt environment param present
Handler->>DB: "SELECT id FROM environments WHERE slug = $1"
DB-->>Handler: Some(env_uuid) or None
alt slug not found
Handler-->>Client: 404 no such environment
end
end
Handler->>DB: WITH revived AS DELETE FROM dead_letters INSERT INTO jobs
DB-->>Handler: rows_affected u64
alt "rows_affected == 0"
Handler-->>Client: 404 no such parked job
else
Handler-->>Client: 200 replayed count
end
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Client
participant Handler as replay_dead_letter
participant DB as Postgres
Client->>Handler: "POST /admin/api/dlq/{job_id}/replay?environment=slug"
Handler->>Handler: parse_typeid(job_id) - 404 on bad format
alt environment param present
Handler->>DB: "SELECT id FROM environments WHERE slug = $1"
DB-->>Handler: Some(env_uuid) or None
alt slug not found
Handler-->>Client: 404 no such environment
end
end
Handler->>DB: WITH revived AS DELETE FROM dead_letters INSERT INTO jobs
DB-->>Handler: rows_affected u64
alt "rows_affected == 0"
Handler-->>Client: 404 no such parked job
else
Handler-->>Client: 200 replayed count
end
Comments Outside Diff (1)
-
server/src/api/admin.rs, line 1298-1303 (link)404 example covers only one of the two cases
The description now says "No such parked job, or no such environment," but the
examplefield still only shows the"no such parked job"message. A caller consulting the generated docs or the TypeScript types has no example of what the"no such environment"404 looks like, even though the two cases produce distinct messages. Adding a second example (viaexamples) or updating the single one to something generic would align the annotation with the extended description.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (1): Last reviewed commit: "feat(admin): env filter on DLQ replay en..." | Re-trigger Greptile
This PR is an alternative implementation of #56, opened alongside #76 (thanks @soufian3hm).
POST /admin/api/dlq/{job_id}/replaygains an optional?environment=<slug>filter (404 on an unknown slug before any row moves, mirroring the CLI--env), and the response reports the real moved count instead of a hardcoded1—dlq::replayreturns the count and the CLI is adapted. Three failing-first HTTP tests over testcontainers cover it (red at baseline, green at head, negative control confirmed).One note from reviewing #76: its hand-edited OpenAPI YAML adds
nullable: true, which utoipa does not emit forOptionIntoParamsquery fields — regenerating dirties the artifacts the PR asks to keep byte-identical. This PR regenerates them viapnpm generate.