fix(cron): skip loadClaimedJob for manual runs

Allow manual job runs even when job is disabled by checking job ID before
claiming. Prevents skipping manually triggered executions.
This commit is contained in:
viettranx committed 2026-04-02 08:23:07 +07:00
1 parent c48639369b
commit b663d92fa4
2 files changed
+18 -10

No files matched your search

+4 -2
View File
@@ -47,8 +47,10 @@ func (s *PGCronStore) RunJob(ctx context.Context, jobID string, force bool) (boo
s.emitEvent(store.CronEvent{Action: "running", JobID: job.ID, JobName: job.Name, UserID: job.UserID})
// Use executeOneJob for proper state updates, run logging, and retry
s.executeOneJob(*job, handler)
// Run directly without reload — job already loaded and claimed above.
// reloadClaimed=false skips loadClaimedJob (which requires enabled=true),
// allowing manual runs on disabled jobs.
s.executeOneJob(*job, handler, false)
s.mu.Lock()
s.cacheLoaded = false
s.mu.Unlock()
+14 -8
View File
@@ -176,7 +176,7 @@ func (s *PGCronStore) checkAndRunDueJobs() {
wg.Add(1)
go func(job store.CronJob) {
defer wg.Done()
s.executeOneJob(job, handler)
s.executeOneJob(job, handler, true)
}(job)
}
wg.Wait()
@@ -188,14 +188,20 @@ func (s *PGCronStore) checkAndRunDueJobs() {
}
// executeOneJob runs a single cron job with retry, logs the result, and updates next_run_at.
func (s *PGCronStore) executeOneJob(job store.CronJob, handler func(job *store.CronJob) (*store.CronJobResult, error)) {
if id, parseErr := uuid.Parse(job.ID); parseErr == nil {
freshJob, ok := s.loadClaimedJob(id)
if !ok {
slog.Info("cron job skipped after claim state changed", "id", job.ID)
return
// executeOneJob runs a claimed job. When reloadClaimed is true (scheduler path),
// it re-reads the job from DB to verify claim invariants (enabled + next_run_at IS NULL).
// When false (manual RunJob path), it uses the already-loaded job directly —
// skipping the reload avoids the enabled=true filter that would reject disabled jobs.
func (s *PGCronStore) executeOneJob(job store.CronJob, handler func(job *store.CronJob) (*store.CronJobResult, error), reloadClaimed bool) {
if reloadClaimed {
if id, parseErr := uuid.Parse(job.ID); parseErr == nil {
freshJob, ok := s.loadClaimedJob(id)
if !ok {
slog.Info("cron job skipped after claim state changed", "id", job.ID)
return
}
job = *freshJob
}
job = *freshJob
}
startTime := time.Now()