feat(dashboard): add ad-hoc job invocation#36
Conversation
WalkthroughThe PR adds one-off job invocation to the Jobs tab. Users can now select eligible jobs and invoke them immediately or schedule them for later execution. A new form component handles validation, JSON input parsing, datetime normalization, and API submission with idempotency deduplication. ChangesInvoke Job UI Feature
Sequence DiagramsequenceDiagram
participant User
participant InvokeJobForm
participant API
participant JobsTable
User->>InvokeJobForm: Select mode (IMMEDIATE/SCHEDULED)
InvokeJobForm->>InvokeJobForm: Validate run_at (if SCHEDULED)
InvokeJobForm->>InvokeJobForm: Normalize run_at to UTC
InvokeJobForm->>InvokeJobForm: Generate idempotency key
InvokeJobForm->>API: create_job(endpoint, input, run_at, idempotency_key)
API-->>InvokeJobForm: Success or Error
InvokeJobForm->>JobsTable: Refresh job list
InvokeJobForm->>User: Close modal
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/dashboard/src/pages/workspace_detail.rs (1)
2287-2296: 💤 Low valueMinor edge case: negative timezone offsets produce invalid output.
If a value with a negative offset (e.g.,
2024-01-01T12:00-05:00) is pasted, the function produces2024-01-01T12:00-05:00Zwhich is invalid RFC 3339. Thecontains('+')check catches positive offsets but not negative ones.This is unlikely from normal
datetime-localinput usage (which never includes timezone info), but could occur if users paste timestamps.🔧 Suggested fix to handle negative offsets
fn normalize_run_at(s: &str) -> String { let s = s.trim(); - if s.ends_with('Z') || s.contains('+') { + // Already has timezone info (Z, +HH:MM, or -HH:MM suffix) + if s.ends_with('Z') || s.contains('+') || s.rfind('-').map_or(false, |i| i > 10) { s.to_string() } else if s.len() == 16 { format!("{s}:00Z") } else { format!("{s}Z") } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/dashboard/src/pages/workspace_detail.rs` around lines 2287 - 2296, normalize_run_at currently treats strings with '+' timezone offsets correctly but misses negative offsets, producing invalid RFC3339 like "...-05:00Z"; update normalize_run_at to detect timezone offsets with either '+' or '-' in the timezone portion (e.g., match a timezone offset pattern like /[+-]\d{2}:\d{2}$/ or check for '+' or '-' in the final 6 characters) and treat those as already having timezone info (return s.to_string()); keep the existing checks for ends_with('Z') and the 16-char "no-seconds" case (format "{s}:00Z") otherwise append "Z".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/dashboard/src/pages/workspace_detail.rs`:
- Around line 2287-2296: normalize_run_at currently treats strings with '+'
timezone offsets correctly but misses negative offsets, producing invalid
RFC3339 like "...-05:00Z"; update normalize_run_at to detect timezone offsets
with either '+' or '-' in the timezone portion (e.g., match a timezone offset
pattern like /[+-]\d{2}:\d{2}$/ or check for '+' or '-' in the final 6
characters) and treat those as already having timezone info (return
s.to_string()); keep the existing checks for ends_with('Z') and the 16-char
"no-seconds" case (format "{s}:00Z") otherwise append "Z".
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f6ebb1d7-313e-4322-9a62-fd6134fc165d
📒 Files selected for processing (1)
crates/dashboard/src/pages/workspace_detail.rs
Adds an "Invoke" action to each active job in the workspace dashboard, letting users fire a one-off run of an existing job either immediately or at a scheduled time. The action reuses the existing POST /v1/jobs API: it builds a fresh IMMEDIATE (or DELAYED, for scheduled) job from the selected job's endpoint and input, with the input optionally overridden for the run. Scheduled invokes derive a stable idempotency key from the source job and target time so a double-submit is naturally deduped. Internal (kronos-managed) jobs are excluded since the API rejects user-created jobs against internal endpoints.
f342fc5 to
0a00bcc
Compare
Summary
This PR adds the ability to invoke jobs on-demand from the workspace dashboard. Users can now trigger one-off executions of active jobs with optional input overrides and scheduling options.
Key Changes
POST /v1/jobsAPI endpoint to create ad-hoc jobs with:IMMEDIATEtrigger for instant executionDELAYEDtrigger for scheduled execution with auto-generated idempotency keysnormalize_run_at()utility to convert HTML5 datetime-local input to RFC 3339 UTC formatImplementation Details
adhoc-{job_id}-{timestamp}) to prevent duplicate submissionshttps://claude.ai/code/session_017VK45VyxzgMyBFJ2LG2D4L
Summary by CodeRabbit