Getting started
To start using Qron, it is strongly encouraged to begin with a tutorial, which will guide through the setup process for your chosen framework and will provide a basic but foundational grasp on how to use the library.
Make sure to read the quick architecture overview before start coding.
Creating a client
To create a client, you will need to import the createClient
function from the @qron-run/sveltekit
package.
The client can be completely configured via env variables, you can directly pass properties to the config
object to override them.
Supported env variables are:
QRON_API_KEY
- Your Qron API keyQRON_API_URL
- The Qron API URLNODE_ENV
- This will determine if the sdk is running in production mode
The config
object supports the following properties:
Property | Description | Prod Default | Dev default | Required |
---|---|---|---|---|
token |
Your Qron API key | undefined |
undefined |
true |
publicUrl |
The public url of your application | undefined |
undefined |
true |
url |
The Qron API URL | https://api.qron.io |
http://localhost:3000 |
false |
prod |
Whether the sdk is running in production mode | equality check with NODE_ENV |
false |
false |
You can instantiate a new client by:
import { createClient } from '@qron-run/sveltekit'
export const { createQueue, createCron, sdk } = createClient()
Creating a queue
To create a queue, you will need to use the createQueue
function created when instantiating a client.
export const helloq = createQueue('helloq', async (event) => {
// ...
})
Each queue has a name and a handler function. The handler function will be invoked when a new job needs to be processed.
The event
argument contains the following properties:
retry
-Retry<T>
class used to retry the job, the job will turn intoREADY
statecommit
-Commit<T>
class used to commit the job, once called the job will be inSUCCESS
statefail
-Fail<T>
class used to fail the job, once called the job will be inFAILURE
statepause
-Pause<T>
class used to momentarily pause the job, once called the job will be inPAUSED
statestate
- stateful object that will be persisted between retries. This can hold specific information about the job
Creating a cron
Creating a cron is identical to creating a queue, you will need to use the createCron
function created when instantiating a client.
export const dailyreminder = createCron('dailyreminder', async (event) => {
// ...
})
Each cron has a name and a handler function. The handler function will be invoked when the scheduled job needs to be processed.
The event
argument contains the same properties as the queue handler.
Mount the handlers
In order to be able to process jobs, you need to mount the qron handlers in your sveltekit application.
Create a file named src/routes/api/queues/[name]/+server.ts
and add the following code:
import { counterq, helloq } from '$lib/your/queues/location'
import { createHandler } from '@qron-run/sveltekit'
export const POST = createHandler(
helloq,
counterq,
)
To make sure your queues and cron jobs are reachable via POST
method at the path /api/queues/:name
.
Type safe state
It is possible to pass a zod
schema when creating a queue or cron handler so to make sure that every time a state is persisted across
runs or at scheduling time, it is always compliant to the schema. This is also handly as it speeds up development as you will enjoy
autocompletion on the state
object.
import { z } from 'zod'
export const helloq = createQueue('helloq', async ({ state }) => {
console.log(`received greeting from ${state.name} ⏰`)
// ...
}, z.object({
name: z.string()
}))
NOTE: state will be serialized to JSON before being persisted, so make sure that everything you put in the state is JSON serializable.
Commit
It is possible to commit a job and mark it as successfully processed by calling the commit
function passed to the handler.
This will put the job in a terminal state, meaning it will not be executed anymore.
export const helloq = createQueue('helloq', async ({ state, commit }) => {
console.log('⏰ received greeting from', state.name)
return commit()
}, z.object({
name: z.string()
}))
Fail
It is possible to fail a job and mark it as failed by calling the fail
function passed to the handler.
This will put the job in a terminal state, meaning it will not be executed anymore.
The fail
function accepts an optional argument that will be persisted as the state of the job.
If no argument is passed, the state will not be updated.
export const helloq = createQueue('helloq', async ({ state, commit, fail }) => {
try {
// execute greet function
return commit()
} catch (e) {
console.error(e)
return fail({
...state,
error: e.message
})
}
}, z.object({
name: z.string(),
error: z.string()
}))
This example shows how to fail a jop and persist the error message. It is possible to inspect the state of a job in the Qron dashboard.
Pause
It is possible to pause a job by calling the pause
function passed to the handler. This will put the job in PAUSED
state.
The job will not be picked up until it is resumed either through the sdk or manually via the dashboard.
export const helloq = createQueue('helloq', async ({ state, pause }) => {
console.log('⏰ received greeting from', state.name)
return pause()
}, z.object({
name: z.string()
}))
Retry
It is possible to retry a job by calling the retry
function passed to the handler. This will put the job in READY
state and it will be picked up after the specified delay.
export const helloq = createQueue('helloq', async ({ state, retry }) => {
console.log('⏰ received greeting from', state.name)
return retry().afterDays(1)
}, z.object({
name: z.string(),
count: z.number()
}))
It is possible to invoke the retry
optionally passing the next state to be persisted.
export const helloq = createQueue('helloq', async ({ state, retry }) => {
console.log('⏰ received greeting from', state.name, state.count, 'times')
return retry({
...state,
count: state.count + 1
}).afterDays(1)
}, z.object({
name: z.string(),
count: z.number()
}))
In this example we are incrementing the count
property of the state object. Which will increase by 1 every time the job is retried.
If no state is passed to the retry
function, the state will not change.
In this case the job will be retried after 1 day, the retry
function supports many scheduling functions:
asap()
- retry the job as soon as possibleafterInterval(interval: number, unit: TimeUnit)
- retry the job after the specified interval (e.g. 1 day, 2 hours, 3 minutes)afterMinutes(interval: number)
- retry the job after the specified number of minutesafterHours(interval: number)
- retry the job after the specified number of hoursafterDays(interval: number)
- retry the job after the specified number of daysafterWeeks(interval: number)
- retry the job after the specified number of weeksafterMonths(interval: number)
- retry the job after the specified number of monthsafterYears(interval: number)
- retry the job after the specified number of yearsafterTime(time: Date)
- retry the job at the specified time
Where TimeUnit
is one of the following:
mins
- minuteshours
- hoursdays
- daysweeks
- weeksmonths
- monthsyears
- years
A full example of a greeting queue that continuously retries up to a specified count
of times is the following:
import { z } from 'zod'
export const helloq = createQueue('helloq', async ({ state, retry, commit }) => {
console.log('⏰ received greeting from', state.name, state.count, 'times')
if (state.count < 3) {
return retry({
...state,
count: state.count + 1
}).afterDays(1)
}
console.log('🎉 success')
return commit()
}, z.object({
name: z.string(),
count: z.number()
}))
Scheduling a job
It is possible to schedule a job to be executed at a specific time or after a certain delay by calling the function created when creating a queue.
export const helloq = createQueue('helloq', /* ... */)
// In your handler ..
// this job will be executed 30 minutes after 1st Jan 2024
await helloq
.afterMinutes(30)
.startsAt(new Date(2024, 1, 1))
.schedule({ name: 'world' })
The job scheduler class Job<T>
supports many methods that can be chained to configure the job execution.
When the job is configured, the schedule()
method needs to be called in order to persist the job.
The schedule(state?: T)
method optionally receives state
as argument which will be persisted by Qron and passed to the job handler.
Supported methods are:
startsAt(date: Date)
- set the start time of the job after the specified datestartsAfter(interval: number, unit: TimeUnit)
- set the start time of the job after the specified intervalafter(interval: number, unit: TimeUnit)
- set the cron expression of the job to@after interval unit
at(date: Date)
- set the cron expression of the job to@at date
. Job will be executed at or right after the specified dateasap()
- The job will be executed as soon as possibleafterMinutes(interval: number)
- set the cron expression of the job to@after interval mins
afterHours(interval: number)
- set the cron expression of the job to@after interval hours
afterDays(interval: number)
- set the cron expression of the job to@after interval days
afterWeeks(interval: number)
- set the cron expression of the job to@after interval weeks
afterMonths(interval: number)
- set the cron expression of the job to@after interval months
afterYears(interval: number)
- set the cron expression of the job to@after interval years
NOTE: It is only possible to schedule jobs server side. This is because the qron sdk requires authentication. And, given that background jobs may process sensitive information, to make sure you are in control of what is published for execution
Scheduling a recurring job
It is possible to schedule a recurring job by calling the function created when creating a cron.
export const reminder = createCron('reminder', async ({ state, commit }) => {
await sendReminderEmail(state.userId, `Remember to drink water!`)
return commit()
}, z.object({
userId: z.string(),
}))
// In your handler ..
await reminder
.everyWeeks(1)
.startsAt(new Date(2024, 1, 1))
.schedule({
userId: '123',
})
// this job will be executed every 1 week after 1st Jan 2024
It is important to return the commit()
class from the job handler in order to signal to Qron that the execution were successful.
Supported methods are:
startsAt(date: Date)
- set the start time of the cron job after the specified datestartsAfter(interval: number, unit: TimeUnit)
- set the start time of the cron job after the specified intervalevery(interval: number, unit: TimeUnit)
- set the cron expression of the job to@every interval unit
everyMinutes(interval: number)
- set the cron expression of the job to@every interval mins
everyHours(interval: number)
- set the cron expression of the job to@every interval hours
everyDays(interval: number)
- set the cron expression of the job to@every interval days
everyWeeks(interval: number)
- set the cron expression of the job to@every interval weeks
everyMonths(interval: number)
- set the cron expression of the job to@every interval months
everyYears(interval: number)
- set the cron expression of the job to@every interval years
Cloud authentication
In order to authenticate with Qron
you need to create an access token at the dedicated page.
Then set the QRON_TOKEN
variable or provide the token
option to the createClient
function.
NOTE: When developing locally, the cloud version cannot be used as it requires a serverless function that is exposed to the internet. Setup a local development environment instead.
If you have any further questions or issues, join the Discord community.