# Batch API

Batch processing for large sets of items with parallelism, retry logic, and progress tracking.

## Quick Start

```typescript
handler: async (input, ctx) => {
  // Create a batch job to process files
  const { job } = await ctx.majk.batch.create_batch_job({
    name: 'Review TypeScript files',
    input: {
      source: { type: 'glob', pattern: 'src/**/*.ts' }
    },
    processor: {
      type: 'teammate',
      teammateId: 'code-reviewer',
      taskTemplate: 'Review {{item}} for best practices'
    },
    execution: { maxParallelism: 3 },
    autoStart: true
  });

  // Wait for completion
  const result = await ctx.majk.batch.await_batch_job({ jobId: job.id });
  return { processed: result.finalProgress.completedItems };
}
```

## API Reference

### create_batch_job(input)

Create a new batch processing job.

```typescript
const { job } = await ctx.majk.batch.create_batch_job({
  name: string,
  description?: string,
  input: {
    source: BatchInputSource,
    transformTemplate?: string,  // Transform items before processing
    skipIfTemplate?: string,     // Skip items matching condition
    limit?: number
  },
  processor: BatchProcessorConfig,
  execution?: BatchExecutionConfig,
  tags?: string[],
  metadata?: Record<string, any>,
  autoStart?: boolean
});
```

### Input Sources

```typescript
// List of items
{ type: 'list', items: ['item1', 'item2', 'item3'] }

// Directory scan
{ type: 'directory', path: 'src/', recursive: true, extensions: ['.ts', '.js'] }

// Glob pattern
{ type: 'glob', pattern: 'src/**/*.ts', basePath: '.', ignore: ['node_modules'] }
```

### Processor Types

```typescript
// Delegate to teammate
{ type: 'teammate', teammateId: 'code-reviewer', taskTemplate: 'Review {{item}}', witness: {...} }

// Call RPC function
{ type: 'rpc', pluginId: 'my-plugin', serviceName: 'analyzer', functionName: 'analyze', input: { file: '{{item}}' } }

// Run witness check
{ type: 'witness', witness: { bash: 'eslint {{item}}' } }

// Execute script
{ type: 'script', code: 'return processItem(item)', timeoutMs: 5000 }
```

### Execution Config

```typescript
execution: {
  maxParallelism: 5,      // Concurrent items
  itemTimeoutMs: 60000,   // Per-item timeout
  jobTimeoutMs: 3600000,  // Total job timeout
  retry: {
    maxAttempts: 3,
    backoff: 'exponential',  // 'none' | 'fixed' | 'linear' | 'exponential'
    initialDelayMs: 1000,
    maxDelayMs: 30000,
    jitter: true
  }
}
```

### start_batch_job(input)

Start a pending batch job.

```typescript
const { job } = await ctx.majk.batch.start_batch_job({ jobId: string });
```

### pause_batch_job(input)

Pause a running job.

```typescript
const { job } = await ctx.majk.batch.pause_batch_job({ jobId: string, reason?: string });
```

### resume_batch_job(input)

Resume a paused job.

```typescript
const { job } = await ctx.majk.batch.resume_batch_job({ jobId: string });
```

### cancel_batch_job(input)

Cancel a job.

```typescript
const { job } = await ctx.majk.batch.cancel_batch_job({ jobId: string });
```

### check_batch_job(input)

Get current status and progress.

```typescript
const result = await ctx.majk.batch.check_batch_job({
  jobId: string,
  includeFailedItems?: boolean,
  failedItemsLimit?: number
});
// Returns: { job, progress: { totalItems, completedItems, failedItems, ... }, failedItems? }
```

### await_batch_job(input)

Wait for job completion.

```typescript
const result = await ctx.majk.batch.await_batch_job({
  jobId: string,
  timeoutMs?: number,
  ignoreBlockers?: boolean
});
// Returns: { job, finalProgress, resultSummary?, hasBlockers?, blockedCount? }
```

### list_batch_jobs(input?)

List jobs with filters.

```typescript
const { jobs, total, hasMore } = await ctx.majk.batch.list_batch_jobs({
  status?: BatchJobStatus | BatchJobStatus[],
  tags?: string[],
  limit?: number,
  offset?: number
});
```

### get_batch_job_items(input)

Get items from a job.

```typescript
const { items, total, hasMore } = await ctx.majk.batch.get_batch_job_items({
  jobId: string,
  status?: BatchItemStatus | BatchItemStatus[],
  limit?: number,
  offset?: number
});
```

### replay_failed_batch_items(input)

Create new job to retry failed items.

```typescript
const { job } = await ctx.majk.batch.replay_failed_batch_items({ jobId: string });
```

### clone_batch_job(input)

Clone a job configuration.

```typescript
const { job } = await ctx.majk.batch.clone_batch_job({
  jobId: string,
  name?: string,
  tags?: string[]
});
```

## Common Patterns

### Process Files with Progress

```typescript
const { job } = await ctx.majk.batch.create_batch_job({
  name: 'Analyze codebase',
  input: { source: { type: 'glob', pattern: '**/*.ts' } },
  processor: { type: 'rpc', pluginId: 'analyzer', functionName: 'analyze' },
  autoStart: true
});

// Poll for progress
let status;
do {
  await new Promise(r => setTimeout(r, 5000));
  status = await ctx.majk.batch.check_batch_job({ jobId: job.id });
  ctx.logger.info(`Progress: ${status.progress.completedItems}/${status.progress.totalItems}`);
} while (status.job.status === 'running');
```

### Handle Failures

```typescript
const result = await ctx.majk.batch.await_batch_job({ jobId: job.id });

if (result.finalProgress.failedItems > 0) {
  const { items } = await ctx.majk.batch.get_batch_job_items({
    jobId: job.id,
    status: 'failed'
  });

  for (const item of items) {
    ctx.logger.error(`Failed: ${item.data}`, { error: item.error });
  }

  // Retry failed items
  await ctx.majk.batch.replay_failed_batch_items({ jobId: job.id });
}
```

## Best Practices

1. **Set appropriate parallelism** - Balance throughput vs resource usage
2. **Use retry with backoff** - Handle transient failures gracefully
3. **Monitor progress** - Check status periodically for long jobs
4. **Handle partial failures** - Use replay for failed items
5. **Tag jobs** - Organize and filter jobs by purpose

## Next Steps

Run `npx @majkapp/plugin-kit --delegation` - Task delegation API
Run `npx @majkapp/plugin-kit --scripting` - Script execution API
