Modal.Queue reference
CreateQueue
Section titled “CreateQueue”Source:
packages/modal/src/CreateQueue.ts
Create queues by name at runtime: one per user, session or task.
Modal’s native shape is get-or-create by name, so getOrCreate is
idempotent and safe to call on every request.
Bind it to a Modal.Environment to keep these runtime objects in their
own namespace (or to nothing, for the workspace’s default environment).
They aren’t in Alchemy state: deleting the environment removes them.
Objects created at run time are tagged with the stack, stage and binding
(alchemy::stack, alchemy::stage, alchemy::id) and are not deleted when
the stack is destroyed. A Modal queue has only a name, so the tags become
its name prefix, Modal.runtimePrefix({ stack, stage, id }): list them
with modal queue list and delete the ones whose name starts with it.
CreateQueue: One queue per user
Section titled “CreateQueue: One queue per user”import * as Cloudflare from "@alchemy.run/cloudflare";import * as Modal from "@alchemy.run/modal";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import { HttpServerRequest } from "effect/http/HttpServerRequest";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { Agents, Coder } from "./Coder.ts";
export default class Api extends Cloudflare.Worker<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const queues = yield* Modal.CreateQueue(Agents); const sandboxes = yield* Modal.CreateSandbox(Coder); return { fetch: Effect.gen(function* () { const request = yield* HttpServerRequest; const user = request.headers["x-user"] ?? "anonymous"; const inbox = yield* queues.getOrCreate(`inbox-${user}`); yield* inbox.put({ task: "review" }); return HttpServerResponse.text("ok"); }).pipe(Effect.orDie), }; }).pipe(Effect.provide(Layer.mergeAll(Modal.CreateQueueHttp, Modal.CreateSandboxHttp))),) {}CreateQueueHttp
Section titled “CreateQueueHttp”Source:
packages/modal/src/CreateQueueHttp.tsKind: Layer · Provides:Modal.CreateQueue
CreateQueue over Modal’s API. Grants the host’s identity (a scoped
Modal.ServiceUser) the contributor role on the environment.
Source:
packages/modal/src/Queue.ts
A Modal Queue: a distributed FIFO queue shared by every container, Sandbox and client in the workspace, with optional named partitions. Items expire 24 hours after they are put (partitions can set their own TTL).
Bind it with WriteQueue to put items, ReadQueue to take
them, or ReadWriteQueue for both, from a Worker, Lambda or any
other runtime. Values travel as bytes: the bindings encode them as JSON by
default.
Modal queues have no tags. Ownership is inferred from Alchemy state: a
queue found under an explicit name without prior state is reported as
unowned.
Queue: Creating a Queue
Section titled “Queue: Creating a Queue”A queue with a generated name
import * as Modal from "@alchemy.run/modal";
export const Jobs = Modal.Queue("Jobs", {});A named queue in an environment
import * as Modal from "@alchemy.run/modal";
export const Agents = Modal.Environment("Agents", {});export const Tasks = Modal.Queue("Tasks", { name: "tasks", environment: Agents });Queue: Producing from a Worker
Section titled “Queue: Producing from a Worker”import * as Cloudflare from "@alchemy.run/cloudflare";import * as Modal from "@alchemy.run/modal";import * as Effect from "effect/Effect";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { Jobs } from "./Storage.ts";
export default class Api extends Cloudflare.Worker<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const jobs = yield* Modal.WriteQueue(Jobs); return { fetch: Effect.gen(function* () { yield* jobs.put({ repo: "alchemy-run/alchemy", command: "pnpm test" }); return HttpServerResponse.text("queued"); }).pipe(Effect.orDie), }; }).pipe(Effect.provide(Modal.WriteQueueHttp)),) {}Queue: Looking up an existing queue
Section titled “Queue: Looking up an existing queue”Queue.lookup references a queue Alchemy doesn’t manage (created with
the Modal CLI or by another stack). It is read during plan/deploy, never
created, updated or deleted.
const jobs = Modal.Queue.lookup({ name: "jobs" });ReadQueue
Section titled “ReadQueue”Source:
packages/modal/src/ReadQueue.ts
Take items from a Modal Queue from any runtime: take (removes), peek and len. Items are JSON.
ReadQueue: Bind a queue
Section titled “ReadQueue: Bind a queue”import * as Cloudflare from "@alchemy.run/cloudflare";import * as Modal from "@alchemy.run/modal";import * as Effect from "effect/Effect";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { Jobs } from "./Storage.ts";
export default class Api extends Cloudflare.Worker<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const queue = yield* Modal.ReadQueue(Jobs); return { fetch: Effect.gen(function* () { const [job] = yield* queue.take({ timeout: "5 seconds" }); return yield* HttpServerResponse.json(job ?? null); }).pipe(Effect.orDie), }; }).pipe(Effect.provide(Modal.ReadQueueHttp)),) {}ReadQueueHttp
Section titled “ReadQueueHttp”Source:
packages/modal/src/ReadQueueHttp.tsKind: Layer · Provides:Modal.ReadQueue
ReadQueue over Modal’s API. Grants the host’s identity (a scoped
Modal.ServiceUser) the contributor role on the queue’s environment.
ReadWriteQueue
Section titled “ReadWriteQueue”Source:
packages/modal/src/ReadWriteQueue.ts
Put and take items on a Modal Queue from any runtime. Items are JSON.
ReadWriteQueue: Bind a queue
Section titled “ReadWriteQueue: Bind a queue”import * as Cloudflare from "@alchemy.run/cloudflare";import * as Modal from "@alchemy.run/modal";import * as Effect from "effect/Effect";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { Jobs } from "./Storage.ts";
export default class Api extends Cloudflare.Worker<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const queue = yield* Modal.ReadWriteQueue(Jobs); return { fetch: Effect.gen(function* () { yield* queue.put({ n: 1 }); const items = yield* queue.take({ count: 10 }); return yield* HttpServerResponse.json(items); }).pipe(Effect.orDie), }; }).pipe(Effect.provide(Modal.ReadWriteQueueHttp)),) {}ReadWriteQueueHttp
Section titled “ReadWriteQueueHttp”Source:
packages/modal/src/ReadWriteQueueHttp.tsKind: Layer · Provides:Modal.ReadWriteQueue
ReadWriteQueue over Modal’s API. Grants the host’s identity (a scoped
Modal.ServiceUser) the contributor role on the queue’s environment.
WriteQueue
Section titled “WriteQueue”Source:
packages/modal/src/WriteQueue.ts
Put items into a Modal Queue from any runtime. Items are JSON, so a Python consumer reads them with json.loads.
WriteQueue: Bind a queue
Section titled “WriteQueue: Bind a queue”import * as Cloudflare from "@alchemy.run/cloudflare";import * as Modal from "@alchemy.run/modal";import * as Effect from "effect/Effect";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { Jobs } from "./Storage.ts";
export default class Api extends Cloudflare.Worker<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const queue = yield* Modal.WriteQueue(Jobs); return { fetch: Effect.gen(function* () { yield* queue.put({ repo: "alchemy-run/alchemy", command: "pnpm test" }); return HttpServerResponse.text("queued"); }).pipe(Effect.orDie), }; }).pipe(Effect.provide(Modal.WriteQueueHttp)),) {}WriteQueueHttp
Section titled “WriteQueueHttp”Source:
packages/modal/src/WriteQueueHttp.tsKind: Layer · Provides:Modal.WriteQueue
WriteQueue over Modal’s API. Grants the host’s identity (a scoped
Modal.ServiceUser) the contributor role on the queue’s environment.