Services
Any class that extends ApplicationBackgroundedService provides the background and backgroundWithDelay methods that are used to background methods on the class. For instance, let's say you have a service that syncs your user data to a service like intercom, twilio, salesforce, helpdesk, etc...
class IntercomSync {
public static async syncUser(user: User) {
// ...sync user to intercom
}
}
You can easily make this a backgroundable service. Simply extend ApplicationBackgroundedService, and now you can background:
class IntercomSync extends ApplicationBackgroundedService {
public static async syncUser(user: User) {
await this.background('_syncUser', user.id)
}
public static async _syncUser(id: IdType) {
const user = await User.find(id)
if (!user) return
// ...sync user to intercom
}
}
Now, from anywhere in your app you can safely call syncUser without tying up resources on the api request!
Pass IDs or scalar values to background jobs, not model objects. Job arguments are serialized through Redis; model instances can go stale and lose type information. Inside the backgrounded implementation, look the record up with find and return early if it no longer exists.
If you enqueue from model hooks, use an after-commit hook such as @deco.AfterCreateCommit, @deco.AfterUpdateCommit, or @deco.AfterSaveCommit. This applies to any enqueue path: calling a backgrounded service, calling this.background(...) on a backgrounded model, or calling a helper that queues the job. Do not enqueue from inside an open transaction; the worker can race the commit and either look up a record before it exists or read stale persisted data after an update.