TUTORIAL 07 · ADVANCED

Events and Background Jobs

Use the generated PostgreSQL outbox and worker adapter for asynchronous ServiceDesk processing.

RAIQL 1.025 minProject: ServiceDesk
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*' | sort

Run 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 worker

Why 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