Skip to main content

Async Jobs (TypeScript)

Server-based job execution with persistence, webhooks, and streaming. Ideal for production deployments.

Installation

npm install praisonai-ts

Basic Usage

Submitting a Job

import { recipe } from 'praisonai-ts';

// Submit recipe as async job
const job = await recipe.submitJob('my-recipe', {
  input: { query: 'What is AI?' },
  config: { maxTokens: 1000 },
  sessionId: 'session_123',
  timeoutSec: 3600,
  webhookUrl: 'https://example.com/webhook',
  idempotencyKey: 'unique-key-123',
  apiUrl: 'http://127.0.0.1:8005',
});

console.log(`Job ID: ${job.jobId}`);
console.log(`Status: ${job.status}`);

JobHandle Interface

interface JobHandle {
  jobId: string;
  recipeName: string;
  status: JobStatus;
  
  getStatus(): Promise<JobStatus>;
  getResult(): Promise<any>;
  cancel(): Promise<boolean>;
  wait(pollInterval?: number, timeout?: number): Promise<any>;
}

type JobStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';

Waiting for Completion

// Submit and wait
const job = await recipe.submitJob('my-recipe', {
  input: 'test',
  wait: true,
});

// Or wait after submission
const job = await recipe.submitJob('my-recipe', { input: 'test' });
const result = await job.wait(5, 300); // poll every 5s, timeout 300s
console.log(`Result: ${result}`);

Using the Jobs API Client

import { JobsClient, JobSubmitRequest } from 'praisonai-ts';

const client = new JobsClient('http://127.0.0.1:8005');

// Submit job
const request: JobSubmitRequest = {
  prompt: 'Analyze this data',
  recipeName: 'data-analyzer',
  recipeConfig: { format: 'json' },
  timeout: 3600,
  webhookUrl: 'https://example.com/callback',
};

const job = await client.submit(request);
console.log(`Job ID: ${job.jobId}`);

// Get status
const status = await client.getStatus(job.jobId);

// Get result
const result = await client.getResult(job.jobId);

// Stream progress
for await (const event of client.stream(job.jobId)) {
  console.log(`Progress: ${event.progress}%`);
}

Webhooks

const job = await recipe.submitJob('my-recipe', {
  input: 'test',
  webhookUrl: 'https://example.com/webhook',
});
Webhook payload:
{
  "jobId": "run_abc123",
  "status": "succeeded",
  "result": {"output": "..."},
  "completedAt": "2024-01-15T10:30:00Z",
  "durationSeconds": 45.2
}

Idempotency

// Same key = same job (no duplicate)
const job1 = await recipe.submitJob('my-recipe', {
  idempotencyKey: 'order-123',
});
const job2 = await recipe.submitJob('my-recipe', {
  idempotencyKey: 'order-123',
});

console.log(job1.jobId === job2.jobId); // true

Configuration

TEMPLATE.yaml Runtime Block

runtime:
  job:
    enabled: true
    timeout_sec: 3600
    webhook_url: "${WEBHOOK_URL}"
    idempotency_scope: "session"

Error Handling

import { recipe, JobError } from 'praisonai-ts';

try {
  const job = await recipe.submitJob('my-recipe', { input: 'test' });
  const result = await job.wait(5, 60);
  
  if (result.status === 'failed') {
    console.error(`Job failed: ${result.error}`);
  }
} catch (error) {
  if (error instanceof JobError) {
    console.error(`Job error: ${error.message}`);
  }
}

See Also