docs(worker): document and expose JetStream storage limits for jobs and KV state

Add `COMPUTE_JOBS_STREAM_MAX_BYTES` and `COMPUTE_JOB_STATES_MAX_BYTES` to
environment example, worker server configuration, and deployment docs. These
variables allow tuning JetStream resource caps for job queue and state storage
to better fit deployment requirements.
This commit is contained in:
Richard R 2026-05-20 15:34:17 -06:00
parent 1bd13c02fe
commit 4ddedee8ec
3 changed files with 14 additions and 1 deletions

View file

@ -27,3 +27,5 @@ S3_FORCE_PATH_STYLE=true
# Queue + execution tuning # Queue + execution tuning
COMPUTE_PREWARM_MODELS=true COMPUTE_PREWARM_MODELS=true
COMPUTE_JOBS_STREAM_MAX_BYTES=268435456
COMPUTE_JOB_STATES_MAX_BYTES=67108864

View file

@ -243,12 +243,14 @@ async function ensureJetStreamResources(
whisperTimeoutMs: number, whisperTimeoutMs: number,
pdfTimeoutMs: number, pdfTimeoutMs: number,
attempts: number, attempts: number,
maxBytes: number,
): Promise<void> { ): Promise<void> {
const streamConfig = { const streamConfig = {
name: JOBS_STREAM_NAME, name: JOBS_STREAM_NAME,
subjects: [WHISPER_JOBS_SUBJECT, LAYOUT_JOBS_SUBJECT], subjects: [WHISPER_JOBS_SUBJECT, LAYOUT_JOBS_SUBJECT],
retention: RetentionPolicy.Workqueue, retention: RetentionPolicy.Workqueue,
storage: StorageType.File, storage: StorageType.File,
max_bytes: maxBytes,
}; };
try { try {
@ -257,6 +259,7 @@ async function ensureJetStreamResources(
if (!isAlreadyExistsError(error)) throw error; if (!isAlreadyExistsError(error)) throw error;
await jsm.streams.update(JOBS_STREAM_NAME, { await jsm.streams.update(JOBS_STREAM_NAME, {
subjects: [WHISPER_JOBS_SUBJECT, LAYOUT_JOBS_SUBJECT], subjects: [WHISPER_JOBS_SUBJECT, LAYOUT_JOBS_SUBJECT],
max_bytes: maxBytes,
}); });
} }
@ -414,6 +417,8 @@ async function main(): Promise<void> {
const pdfTimeoutMs = readIntEnv('COMPUTE_PDF_TIMEOUT_MS', 90_000); const pdfTimeoutMs = readIntEnv('COMPUTE_PDF_TIMEOUT_MS', 90_000);
const attempts = readIntEnv('COMPUTE_JOB_ATTEMPTS', 2); const attempts = readIntEnv('COMPUTE_JOB_ATTEMPTS', 2);
const prewarmModels = parseBoolEnv('COMPUTE_PREWARM_MODELS', true); const prewarmModels = parseBoolEnv('COMPUTE_PREWARM_MODELS', true);
const jobsStreamMaxBytes = readIntEnv('COMPUTE_JOBS_STREAM_MAX_BYTES', 256 * 1024 * 1024);
const jobStatesMaxBytes = readIntEnv('COMPUTE_JOB_STATES_MAX_BYTES', 64 * 1024 * 1024);
const connectOpts: any = { servers: natsUrl }; const connectOpts: any = { servers: natsUrl };
const natsCreds = process.env.NATS_CREDS?.trim(); const natsCreds = process.env.NATS_CREDS?.trim();
@ -433,11 +438,12 @@ async function main(): Promise<void> {
const js: JetStreamClient = jetstream(nc); const js: JetStreamClient = jetstream(nc);
const jsm: JetStreamManager = await jetstreamManager(nc); const jsm: JetStreamManager = await jetstreamManager(nc);
await ensureJetStreamResources(jsm, whisperTimeoutMs, pdfTimeoutMs, attempts); await ensureJetStreamResources(jsm, whisperTimeoutMs, pdfTimeoutMs, attempts, jobsStreamMaxBytes);
const kv = await new Kvm(js).create(JOB_STATES_BUCKET, { const kv = await new Kvm(js).create(JOB_STATES_BUCKET, {
history: 1, history: 1,
ttl: JOB_STATES_TTL_MS, ttl: JOB_STATES_TTL_MS,
max_bytes: jobStatesMaxBytes,
}); });
const s3 = buildS3Client(); const s3 = buildS3Client();

View file

@ -45,6 +45,8 @@ Common optional:
- `COMPUTE_WORKER_PORT=8081` - `COMPUTE_WORKER_PORT=8081`
- `COMPUTE_LOG_FORMAT=pretty` (default) or `json` - `COMPUTE_LOG_FORMAT=pretty` (default) or `json`
- `COMPUTE_PREWARM_MODELS=true` - `COMPUTE_PREWARM_MODELS=true`
- `COMPUTE_JOBS_STREAM_MAX_BYTES=268435456` (256MB JetStream jobs stream cap)
- `COMPUTE_JOB_STATES_MAX_BYTES=67108864` (64MB JetStream KV bucket cap)
## App server environment variables (worker mode) ## App server environment variables (worker mode)
@ -102,6 +104,8 @@ Set these in the Railway worker service:
COMPUTE_WORKER_HOST=0.0.0.0 COMPUTE_WORKER_HOST=0.0.0.0
COMPUTE_WORKER_PORT=8081 COMPUTE_WORKER_PORT=8081
COMPUTE_WORKER_TOKEN=<long-random-shared-token> COMPUTE_WORKER_TOKEN=<long-random-shared-token>
COMPUTE_JOBS_STREAM_MAX_BYTES=268435456
COMPUTE_JOB_STATES_MAX_BYTES=67108864
NATS_URL=tls://connect.ngs.global:4222 NATS_URL=tls://connect.ngs.global:4222
NATS_CREDS="-----BEGIN NATS USER JWT----- NATS_CREDS="-----BEGIN NATS USER JWT-----
@ -122,6 +126,7 @@ Notes:
- `NATS_CREDS` should be the full Synadia `.creds` file content, including begin/end markers. - `NATS_CREDS` should be the full Synadia `.creds` file content, including begin/end markers.
- Keep `COMPUTE_WORKER_TOKEN` identical between app server and worker. - Keep `COMPUTE_WORKER_TOKEN` identical between app server and worker.
- If your platform supports mounted files, you can use `NATS_CREDS_FILE` instead of `NATS_CREDS`. - If your platform supports mounted files, you can use `NATS_CREDS_FILE` instead of `NATS_CREDS`.
- `COMPUTE_JOBS_STREAM_MAX_BYTES` and `COMPUTE_JOB_STATES_MAX_BYTES` are optional; defaults are `268435456` (256MiB) and `67108864` (64MiB).
### 4. Configure the OpenReader app server (worker mode) ### 4. Configure the OpenReader app server (worker mode)