// Welcome emails queued at sign-up and sent by a worker, with retries and a dead-letter list.
//
//   quillo run job_queue.qwe      then open http://localhost:8080/signup?email=ada@example.com
//   then http://localhost:8080/work runs the worker once, /drain until the queue is empty.

use "job_queue.qwer"

let Q = "data/jobs.redb"

route GET /signup ? { email: str } {
    let id = job_push(Q, "emails", { to: email, template: "welcome" }, 0)?
    { queued: id, stats: job_stats(Q)?.emails }
}

// One turn of a worker: take a job, do it, ack it, or retry it when it fails.
route GET /work {
    let job = job_take(Q, "emails", 30)?
    if job == null { return { done: null } }
    if ends_with(job.payload.to, "@example.invalid") {
        { failed: job.payload.to, state: job_retry(Q, job.id, "no such domain", 0, 2)? }
    } else {
        job_ack(Q, job.id)?
        { done: job.payload.to, attempts: job.attempts }
    }
}

// The worker run until the queue is empty: what it did, job by job.
route GET /drain {
    let did = []
    let job = job_take(Q, "emails", 30)?
    while job != null {
        if ends_with(job.payload.to, "@example.invalid") {
            did = push(did, `${job.payload.to}: ${job_retry(Q, job.id, "no such domain", 0, 2)?}`)
        } else {
            job_ack(Q, job.id)?
            did = push(did, `${job.payload.to}: sent`)
        }
        job = job_take(Q, "emails", 30)?
    }
    did
}

route GET /dead = job_dead(Q, "emails", 10)? | map((j) => { to: j.payload.to, error: j.error, attempts: j.attempts })
