Core Concepts

Understanding jobs, states, and real-time updates.

#Job Lifecycle

Every job in Seenn follows a predictable lifecycle:

pending
Job created
queued
Waiting in queue
running
Processing
completed
or
failed
Status Description Terminal?
pending Job created but not yet started processing No
queued Job is waiting in a queue (optional) No
running Job is actively being processed No
completed Job finished successfully with result Yes
failed Job failed with error Yes

#Stages

Many jobs have multiple distinct phases. Use stages to show users where they are in the process:

// Backend: Update job with stage info
await job.setProgress(33, {
  message: 'Analyzing your prompt...',
  stage: {
    name: 'analysis',
    current: 1,
    total: 3,
    description: 'Understanding your requirements',
  },
});

await job.setProgress(66, {
  message: 'Generating video frames...',
  stage: {
    name: 'generation',
    current: 2,
    total: 3,
  },
});

await job.setProgress(90, {
  message: 'Rendering final video...',
  stage: {
    name: 'rendering',
    current: 3,
    total: 3,
  },
});

Client apps can display this as a step indicator:

2
3
Analysis Generation Rendering

#Queue Position

When jobs need to wait (e.g., during high demand), show users their position:

// Backend: Start job with queue position
const job = await seenn.jobs.start({
  userId: 'user_123',
  jobType: 'video-generation',
  title: 'Creating your video...',
  queue: {
    position: 5,
    total: 12,
    queueName: 'free-tier',
  },
});

// Update queue position as it changes
await job.setProgress(0, {
  message: 'Waiting in queue...',
  queue: { position: 3, total: 10 },
});
Queue position is passive. Seenn transports the queue data you provide — it doesn't manage the actual queue. Your backend is responsible for determining queue positions.

#Parent-Child Jobs

For batch processing (e.g., AI image packs, multi-stage pipelines), use parent-child jobs. The parent's progress is automatically calculated from its children.

Parent: Christmas Image Pack 3/5 completed 60%
Snowflake
Tree
Santa
⟳ 45%
Reindeer
Gift Box

#Creating Parent-Child Jobs

// Option 1: Create parent first, then children
const parent = await seenn.jobs.createParent({
  userId: 'user_123',
  jobType: 'batch-processing',
  title: 'Christmas Image Pack (5 images)',
  childCount: 5,
  childProgressMode: 'average',  // How to calculate parent progress
});

// Create each child with its index
for (let i = 0; i < images.length; i++) {
  const child = await seenn.jobs.createChild({
    parentJobId: parent.id,
    childIndex: i,  // 0-based index
    userId: 'user_123',
    jobType: 'image-generation',
    title: images[i].name,
  });
}
// Option 2: Create everything at once with createBatch()
const { parent, children } = await seenn.jobs.createBatch({
  userId: 'user_123',
  jobType: 'image-generation',
  parentTitle: 'Christmas Pack',
  childTitles: ['Snowflake', 'Tree', 'Santa', 'Reindeer', 'Gift Box'],
  childProgressMode: 'average',
});

// Process children in parallel
await Promise.all(children.map(async (child) => {
  await child.setProgress(50);
  // ... AI processing ...
  await child.complete({ result: { url: 'https://...' } });
}));

// Parent auto-completes when all children are done!

#Child Progress Mode

Control how the parent's progress is calculated from its children:

Mode Calculation Best For
average Sum of all children's progress ÷ total children Parallel processing (e.g., batch images)
sequential Completed children ÷ total children × 100 Sequential pipelines (only count done items)
weighted Same as average (future: custom weights) Reserved for future use
Example: With average mode and 5 children at [100%, 100%, 100%, 45%, 0%], parent progress = (100+100+100+45+0)/5 = 69%

#Auto-Update Mechanism

When a child job's status or progress changes, the parent is automatically updated:

1. Child completes
child.complete()
2. DynamoDB Stream triggers
Lambda: updateParent()
3. Parent stats recalculated
progress, completedChildren++
4. SSE event published
job.progress → clients

The parent automatically transitions to:

  • completed — when ALL children complete successfully
  • failed — when ANY child fails (configurable)

#Retrieving Parent with Children

// Get parent job with all children
const { parent, children } = await seenn.jobs.getWithChildren(parentId);

console.log(parent.progress);       // 60 (auto-calculated)
console.log(parent.childProgress); // { completed: 3, failed: 0, running: 1, pending: 1 }

for (const child of children) {
  console.log(`${child.title}: ${child.status} (${child.progress}%)`);
}

#Client-Side Tracking

// React Native: useSeennJob automatically receives parent updates
const { job } = useSeennJob(parentJobId);

// job.progress auto-updates when children complete
// job.childrenCompleted / job.childrenTotal available
<Text>{job.childrenCompleted}/{job.childrenTotal} completed</Text>

#Real-time Updates (SSE)

Seenn uses Server-Sent Events (SSE) to push updates to clients instantly:

Instant Delivery

Updates arrive within milliseconds of being sent from your backend.

Auto Reconnection

SDKs automatically reconnect with exponential backoff.

Missed Event Recovery

Reconnecting clients receive any events they missed.

Heartbeat

Connection health monitored with periodic heartbeat.

#Estimated Time (ETA)

Provide users with estimated completion time:

// Backend: Set estimated completion time
const eta = new Date(Date.now() + 60000);  // 60 seconds from now

await job.setProgress(50, {
  message: 'Processing...',
  estimatedCompletionAt: eta.toISOString(),
});
Two ETA sources: You can provide your own ETA, or Seenn can calculate it based on historical job completion times for your job type.