Merge pull request 'scheduler' (#19) from jacs/cup:scheduler into develop

Reviewed-on: #19
This commit is contained in:
Zeni Kim 2026-06-23 19:55:42 -04:00
commit d9c956546d
3 changed files with 13 additions and 11 deletions

View file

@ -23,43 +23,44 @@ func SchedulerSample(c *core.Context) *core.Response {
ctx := context.Background() ctx := context.Background()
// ── Enqueue a "send_email" task ───────────────────────────────────────── // ── Enqueue a "send_email" task (runs once, sequential) ────────────────
emailPayload, _ := json.Marshal(map[string]interface{}{ emailPayload, _ := json.Marshal(map[string]interface{}{
"to": "user@example.com", "to": "user@example.com",
"subject": "Hello from the scheduler!", "subject": "Hello from the scheduler!",
}) })
item1, err := store.Enqueue(ctx, "send_email", string(emailPayload), 0) item1, err := store.Enqueue(ctx, "send_email", string(emailPayload), 0, 1, 0)
if err != nil { if err != nil {
c.GetLogger().Error(fmt.Sprintf("failed to enqueue send_email: %v", err)) c.GetLogger().Error(fmt.Sprintf("failed to enqueue send_email: %v", err))
return c.Response.SetStatusCode(500).Json(`{"message": "failed to enqueue send_email"}`) return c.Response.SetStatusCode(500).Json(`{"message": "failed to enqueue send_email"}`)
} }
c.GetLogger().Info(fmt.Sprintf("[scheduler] enqueued send_email task id=%d", item1.ID)) c.GetLogger().Info(fmt.Sprintf("[scheduler] enqueued send_email task id=%d (maxRuns=1, thread=0)", item1.ID))
// ── Enqueue a "flaky_task" (demonstrates error recording) ─────────────── // ── Enqueue a "flaky_task" (runs 3 times, concurrent) ──────────────────
flakyPayload, _ := json.Marshal(map[string]interface{}{ flakyPayload, _ := json.Marshal(map[string]interface{}{
"description": "This task will fail and the error will be recorded", "description": "This task will fail and the error will be recorded",
}) })
item2, err := store.Enqueue(ctx, "flaky_task", string(flakyPayload), 0) item2, err := store.Enqueue(ctx, "flaky_task", string(flakyPayload), 0, 3, 1)
if err != nil { if err != nil {
c.GetLogger().Error(fmt.Sprintf("failed to enqueue flaky_task: %v", err)) c.GetLogger().Error(fmt.Sprintf("failed to enqueue flaky_task: %v", err))
return c.Response.SetStatusCode(500).Json(`{"message": "failed to enqueue flaky_task"}`) return c.Response.SetStatusCode(500).Json(`{"message": "failed to enqueue flaky_task"}`)
} }
c.GetLogger().Info(fmt.Sprintf("[scheduler] enqueued flaky_task id=%d", item2.ID)) c.GetLogger().Info(fmt.Sprintf("[scheduler] enqueued flaky_task id=%d (maxRuns=3, thread=1/concurrent)", item2.ID))
// ── Enqueue a high-priority "send_email" task ─────────────────────────── // ── Enqueue a high-priority "send_email" (repeats indefinitely, sequential) ──
urgentPayload, _ := json.Marshal(map[string]interface{}{ urgentPayload, _ := json.Marshal(map[string]interface{}{
"to": "urgent@example.com", "to": "urgent@example.com",
"subject": "URGENT: Priority message", "subject": "URGENT: Priority message",
}) })
item3, err := store.Enqueue(ctx, "send_email", string(urgentPayload), 10) item3, err := store.Enqueue(ctx, "send_email", string(urgentPayload), 10, -1, 0)
if err != nil { if err != nil {
c.GetLogger().Error(fmt.Sprintf("failed to enqueue urgent send_email: %v", err)) c.GetLogger().Error(fmt.Sprintf("failed to enqueue urgent send_email: %v", err))
return c.Response.SetStatusCode(500).Json(`{"message": "failed to enqueue urgent send_email"}`) return c.Response.SetStatusCode(500).Json(`{"message": "failed to enqueue urgent send_email"}`)
} }
c.GetLogger().Info(fmt.Sprintf("[scheduler] enqueued high-priority send_email task id=%d", item3.ID)) c.GetLogger().Info(fmt.Sprintf("[scheduler] enqueued high-priority send_email id=%d (maxRuns=-1/infinite, thread=0)", item3.ID))
message := fmt.Sprintf(`{"message": "Enqueued 3 scheduler tasks (send_email x2, flaky_task x1)", "tasks": [%d, %d, %d]}`, message := fmt.Sprintf(`{"message": "Enqueued 3 scheduler tasks (send_email, flaky_task)", "tasks": [%d, %d, %d]}`,
item1.ID, item2.ID, item3.ID) item1.ID, item2.ID, item3.ID)
return c.Response.Json(message) return c.Response.Json(message)
} }

View file

@ -28,7 +28,7 @@ func handleSendEmail(ctx context.Context, item *scheduler.QueueItem) error {
return fmt.Errorf("invalid send_email payload: %w", err) return fmt.Errorf("invalid send_email payload: %w", err)
} }
log.Printf("[scheduler] [send_email] → to=%s subject=%q", payload.To, payload.Subject) log.Printf("[scheduler] [send_email] → to=%s subject=%q", payload.To, payload.Subject)
time.Sleep(50 * time.Millisecond) // simulate I/O time.Sleep(2000 * time.Millisecond) // simulate I/O
return nil return nil
} }

View file

@ -30,6 +30,7 @@ func RunAutoMigrations() {
// Simple scheduler (sche) tables — enabled when scheduler is active // Simple scheduler (sche) tables — enabled when scheduler is active
db.AutoMigrate(&scheduler.QueueItem{}) db.AutoMigrate(&scheduler.QueueItem{})
db.AutoMigrate(&scheduler.ProcessedItem{}) db.AutoMigrate(&scheduler.ProcessedItem{})
db.AutoMigrate(&scheduler.SchedulerMeta{})
// End your auto migrations // End your auto migrations