Inbox API with Server Workers
The Inbox API provides a message-based communication system for Server Workers in Jazz.
It works on top of the Jazz APIs and uses sync to transfer messages between the client and the server.
Setting up the Inbox API
Define the inbox message schema
Define the inbox message schema in your schema file:
export const BookTicketMessage = co.map({ type: co.literal("bookTicket"), event: Event, })
Any kind of CoMap is valid as an inbox message.
Setting up the Server Worker
Run a server worker and subscribe to the inbox
:
import { startWorker } from "jazz-tools/worker"; import { BookTicketMessage } from "@/schema"; const { worker, experimental: { inbox }, } = await startWorker({ accountID: process.env.JAZZ_WORKER_ACCOUNT, accountSecret: process.env.JAZZ_WORKER_SECRET, syncServer: "wss://cloud.jazz.tools/?key=your-api-key", }); inbox.subscribe( BookTicketMessage, async (message, senderID) => { const madeBy = await co.account().load(senderID, { loadAs: worker }); const { event } = await message.ensureLoaded({ resolve: { event: { reservations: true, }, }, }); const ticketGroup = Group.create(jazzServer.worker); const ticket = Ticket.create({ account: madeBy, event, }); // Give access to the ticket to the client ticketGroup.addMember(madeBy, "reader"); event.reservations.push(ticket); return ticket; }, );
Handling multiple message types
inbox.subscribe
should be called once per worker instance.
If you need to handle multiple message types, you can use the co.discriminatedUnion
function to create a union of the message types.
const CancelReservationMessage = co.map({ type: co.literal("cancelReservation"), event: Event, ticket: Ticket, }); export const InboxMessage = co.discriminatedUnion("type", [ BookTicketMessage, CancelReservationMessage ]);
And check the message type in the handler:
import { InboxMessage } from "@/schema"; inbox.subscribe( InboxMessage, async (message, senderID) => { switch (message.type) { case "bookTicket": return await handleBookTicket(message, senderID); case "cancelReservation": return await handleCancelReservation(message, senderID); } }, );
Sending messages from the client
Using the Inbox Sender hook
Use experimental_useInboxSender
to send messages from React components:
import { experimental_useInboxSender } from "jazz-tools/react"; import { BookTicketMessage, Event } from "@/schema"; function EventComponent({ event }: { event: Event }) { const sendInboxMessage = experimental_useInboxSender(WORKER_ID); const [isLoading, setIsLoading] = useState(false); const onBookTicketClick = async () => { setIsLoading(true); const ticketId = await sendInboxMessage( BookTicketMessage.create({ type: "bookTicket", event: event, }), ); alert(`Ticket booked: ${ticketId}`); }; return ( <Button onClick={onBookTicketClick} loading={isLoading}> Book Ticket </Button> ); }
The sendInboxMessage
API returns a Promise that waits for the message to be handled by a Worker.
A message is considered to be handled when the Promise returned by inbox.subscribe
resolves.
The value returned will be the id of the CoValue returned in the inbox.subscribe
resolved promise.
Deployment considerations
Multi-region deployments are not supported when using the Inbox API.
If you need to split the workload across multiple regions, you can use the HTTP API instead.