TUTORIAL 07 · ADVANCED
Events and Background Jobs
Use the generated PostgreSQL outbox and worker adapter for asynchronous ServiceDesk processing.
By the end of this tutorial
- Declare an event from an entity
- Connect a job to an event
- Understand the PostgreSQL outbox
- Run the generated worker
Declare asynchronous intent
EVENT connects entity creation to a named outbox event. JOB connects a generated worker handler to that event.
app.raiql
CREATE APPLICATION "RAIQL ServiceDesk";
TYPE WEB;
USE STACK
FRONTEND NEXTJS,
BACKEND NEXTJS,
DATABASE POSTGRESQL;
CREATE TENANT ENTITY Tenant;
CREATE USER ENTITY User;
CREATE ENTITY Ticket (
id UUID PRIMARY,
title STRING REQUIRED,
description STRING,
status STRING REQUIRED,
priority STRING REQUIRED,
ownerId UUID REQUIRED,
tenantId UUID REQUIRED
);
CREATE CRUD Tenant;
CREATE API Tenant;
CREATE CRUD Ticket;
CREATE API Ticket;
ADD AUTHENTICATION EMAIL_PASSWORD, JWT;
ADD ROLE ADMIN, AGENT, USER;
DEFAULT ROLE USER;
RELATE Ticket.ownerId TO User.id;
RELATE Ticket.tenantId TO Tenant.id;
OWN Ticket BY ownerId;
TENANT Ticket BY tenantId;
ALLOW ADMIN CREATE Ticket, READ Ticket, UPDATE Ticket, DELETE Ticket, CREATE Tenant, READ Tenant, UPDATE Tenant, DELETE Tenant;
ALLOW AGENT READ Ticket, UPDATE Ticket;
ALLOW USER CREATE OWN Ticket, READ OWN Ticket, UPDATE OWN Ticket;
ENVIRONMENT development, staging, production;
SECRET DATABASE_URL;
SECRET RAIQL_JWT_SECRET;
EVENT TicketCreated FROM Ticket;
JOB ProcessTicket ON TicketCreated;
GENERATE OPENAPI;
GENERATE SDK TYPESCRIPT;
BUILD;
DEPLOY DOCKER;Generate event infrastructure
terminal
raiql generate
find generated -iname '*worker*' -o -iname '*event*' | sortRun web and worker processes
Keep the application server and worker as separate processes. The generated PostgreSQL outbox becomes the handoff point between request processing and background work.
terminal
# terminal 1
raiql dev --env development
# terminal 2, from generated/
npm run workerWhy an outbox
- Request processing can commit the domain change and event record together
- Workers can retry independently
- The language stays independent of a specific cloud queue
- A later adapter can bridge events to external infrastructure without changing domain syntax