update api, fix tests and examples
This commit is contained in:
280
docs/README.md
Normal file
280
docs/README.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# Hero Supervisor Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
Hero Supervisor is a distributed job execution system that manages runners and coordinates job processing across multiple worker nodes. It provides a robust OpenRPC API for job management and runner administration.
|
||||
|
||||
## Architecture
|
||||
|
||||
The supervisor consists of several key components:
|
||||
|
||||
- **Supervisor Core**: Central coordinator that manages runners and job dispatch
|
||||
- **OpenRPC Server**: JSON-RPC API server for remote management
|
||||
- **Redis Backend**: Job queue and state management
|
||||
- **Process Manager**: Runner lifecycle management (Simple or Tmux)
|
||||
- **Client Libraries**: Native Rust and WASM clients for integration
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Starting the Supervisor
|
||||
|
||||
```bash
|
||||
# With default configuration
|
||||
./supervisor
|
||||
|
||||
# With custom configuration file
|
||||
./supervisor --config /path/to/config.toml
|
||||
```
|
||||
|
||||
### Example Configuration
|
||||
|
||||
```toml
|
||||
# config.toml
|
||||
redis_url = "redis://localhost:6379"
|
||||
namespace = "hero"
|
||||
bind_address = "127.0.0.1"
|
||||
port = 3030
|
||||
|
||||
# Admin secrets for full access
|
||||
admin_secrets = ["admin-secret-123"]
|
||||
|
||||
# User secrets for job operations
|
||||
user_secrets = ["user-secret-456"]
|
||||
|
||||
# Register secrets for runner registration
|
||||
register_secrets = ["register-secret-789"]
|
||||
|
||||
[[actors]]
|
||||
id = "sal_runner_1"
|
||||
name = "sal_runner_1"
|
||||
binary_path = "/path/to/sal_runner"
|
||||
db_path = "/tmp/sal_db"
|
||||
redis_url = "redis://localhost:6379"
|
||||
process_manager = "simple"
|
||||
|
||||
[[actors]]
|
||||
id = "osis_runner_1"
|
||||
name = "osis_runner_1"
|
||||
binary_path = "/path/to/osis_runner"
|
||||
db_path = "/tmp/osis_db"
|
||||
redis_url = "redis://localhost:6379"
|
||||
process_manager = "tmux:osis_session"
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
### Job API Convention
|
||||
|
||||
The Hero Supervisor follows a consistent naming convention for job operations:
|
||||
|
||||
- **`jobs.`** - General job operations (create, list)
|
||||
- **`job.`** - Specific job operations (run, start, status, result)
|
||||
|
||||
See [Job API Convention](job-api-convention.md) for detailed documentation.
|
||||
|
||||
### Core Methods
|
||||
|
||||
#### Runner Management
|
||||
- `register_runner` - Register a new runner
|
||||
- `list_runners` - List all registered runners
|
||||
- `start_runner` / `stop_runner` - Control runner lifecycle
|
||||
- `get_runner_status` - Get runner status
|
||||
- `get_runner_logs` - Retrieve runner logs
|
||||
|
||||
#### Job Management
|
||||
- `jobs.create` - Create a job without queuing
|
||||
- `jobs.list` - List all jobs with full details
|
||||
- `job.run` - Run a job and return result
|
||||
- `job.start` - Start a created job
|
||||
- `job.stop` - Stop a running job
|
||||
- `job.delete` - Delete a job from the system
|
||||
- `job.status` - Get job status (non-blocking)
|
||||
- `job.result` - Get job result (blocking)
|
||||
|
||||
#### Administration
|
||||
- `add_secret` / `remove_secret` - Manage authentication secrets
|
||||
- `get_supervisor_info` - Get system information
|
||||
- `rpc.discover` - OpenRPC specification discovery
|
||||
|
||||
## Client Usage
|
||||
|
||||
### Rust Client
|
||||
|
||||
```rust
|
||||
use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder};
|
||||
|
||||
// Create client
|
||||
let client = SupervisorClient::new("http://localhost:3030")?;
|
||||
|
||||
// Create a job
|
||||
let job = JobBuilder::new()
|
||||
.caller_id("my_client")
|
||||
.context_id("my_context")
|
||||
.payload("print('Hello World')")
|
||||
.executor("osis")
|
||||
.runner("osis_runner_1")
|
||||
.timeout(60)
|
||||
.build()?;
|
||||
|
||||
// Option 1: Fire-and-forget execution
|
||||
let result = client.job_run("user-secret", job.clone()).await?;
|
||||
match result {
|
||||
JobResult::Success { success } => println!("Output: {}", success),
|
||||
JobResult::Error { error } => println!("Error: {}", error),
|
||||
}
|
||||
|
||||
// Option 2: Asynchronous execution
|
||||
let job_id = client.jobs_create("user-secret", job).await?;
|
||||
client.job_start("user-secret", &job_id).await?;
|
||||
|
||||
// Poll for completion
|
||||
loop {
|
||||
let status = client.job_status(&job_id).await?;
|
||||
if status.status == "completed" || status.status == "failed" {
|
||||
break;
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
|
||||
let result = client.job_result(&job_id).await?;
|
||||
|
||||
// Option 3: Job management
|
||||
// Stop a running job
|
||||
client.job_stop("user-secret", &job_id).await?;
|
||||
|
||||
// Delete a job
|
||||
client.job_delete("user-secret", &job_id).await?;
|
||||
|
||||
// List all jobs (returns full Job objects)
|
||||
let jobs = client.jobs_list("user-secret").await?;
|
||||
for job in jobs {
|
||||
println!("Job {}: {} ({})", job.id, job.executor, job.payload);
|
||||
}
|
||||
```
|
||||
|
||||
### WASM Client
|
||||
|
||||
```javascript
|
||||
import { WasmSupervisorClient, WasmJob } from 'hero-supervisor-openrpc-client';
|
||||
|
||||
// Create client
|
||||
const client = new WasmSupervisorClient('http://localhost:3030');
|
||||
|
||||
// Create and run job
|
||||
const job = new WasmJob('job-id', 'print("Hello")', 'osis', 'osis_runner_1');
|
||||
const result = await client.create_job('user-secret', job);
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
### Authentication Levels
|
||||
|
||||
1. **Admin Secrets**: Full system access
|
||||
- All runner management operations
|
||||
- All job operations
|
||||
- Secret management
|
||||
- System information access
|
||||
|
||||
2. **User Secrets**: Job operations only
|
||||
- Create, run, start jobs
|
||||
- Get job status and results
|
||||
- No runner or secret management
|
||||
|
||||
3. **Register Secrets**: Runner registration only
|
||||
- Register new runners
|
||||
- No other operations
|
||||
|
||||
### Best Practices
|
||||
|
||||
- Use different secret types for different access levels
|
||||
- Rotate secrets regularly
|
||||
- Store secrets securely (environment variables, secret management systems)
|
||||
- Use HTTPS in production environments
|
||||
- Implement proper logging and monitoring
|
||||
|
||||
## Development
|
||||
|
||||
### Building
|
||||
|
||||
```bash
|
||||
# Build supervisor binary
|
||||
cargo build --release
|
||||
|
||||
# Build with OpenRPC feature
|
||||
cargo build --release --features openrpc
|
||||
|
||||
# Build client library
|
||||
cd clients/openrpc
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run tests
|
||||
cargo test
|
||||
|
||||
# Run with Redis (requires Redis server)
|
||||
docker run -d -p 6379:6379 redis:alpine
|
||||
cargo test -- --ignored
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
See the `examples/` directory for:
|
||||
- Basic supervisor setup
|
||||
- Mock runner implementation
|
||||
- Comprehensive OpenRPC client usage
|
||||
- Configuration examples
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Redis Connection Failed**
|
||||
- Ensure Redis server is running
|
||||
- Check Redis URL in configuration
|
||||
- Verify network connectivity
|
||||
|
||||
2. **Runner Registration Failed**
|
||||
- Check register secret validity
|
||||
- Verify runner binary path exists
|
||||
- Ensure runner has proper permissions
|
||||
|
||||
3. **Job Execution Timeout**
|
||||
- Increase job timeout value
|
||||
- Check runner resource availability
|
||||
- Monitor runner logs for issues
|
||||
|
||||
4. **OpenRPC Method Not Found**
|
||||
- Verify method name spelling
|
||||
- Check OpenRPC specification
|
||||
- Ensure server supports the method
|
||||
|
||||
### Logging
|
||||
|
||||
Enable debug logging:
|
||||
```bash
|
||||
RUST_LOG=debug ./supervisor --config config.toml
|
||||
```
|
||||
|
||||
### Monitoring
|
||||
|
||||
Monitor key metrics:
|
||||
- Runner status and health
|
||||
- Job queue lengths
|
||||
- Job success/failure rates
|
||||
- Response times
|
||||
- Redis connection status
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make changes with tests
|
||||
4. Update documentation
|
||||
5. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
[License information here]
|
333
docs/job-api-convention.md
Normal file
333
docs/job-api-convention.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Hero Supervisor Job API Convention
|
||||
|
||||
## Overview
|
||||
|
||||
The Hero Supervisor OpenRPC API follows a consistent naming convention for job-related operations:
|
||||
|
||||
- **`jobs.`** - General job operations (plural)
|
||||
- **`job.`** - Specific job operations (singular)
|
||||
|
||||
This convention provides a clear distinction between operations that work with multiple jobs or create new jobs versus operations that work with a specific existing job.
|
||||
|
||||
## API Methods
|
||||
|
||||
### General Job Operations (`jobs.`)
|
||||
|
||||
#### `jobs.create`
|
||||
Creates a new job without immediately queuing it to a runner.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job` (Job object): Complete job specification
|
||||
|
||||
**Returns:**
|
||||
- `job_id` (string): Unique identifier of the created job
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "jobs.create",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job": {
|
||||
"id": "job-123",
|
||||
"caller_id": "client-1",
|
||||
"context_id": "context-1",
|
||||
"payload": "print('Hello World')",
|
||||
"executor": "osis",
|
||||
"runner": "osis-runner-1",
|
||||
"timeout": 300,
|
||||
"env_vars": {},
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-01T00:00:00Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `jobs.list`
|
||||
Lists all jobs in the system with full details.
|
||||
|
||||
**Parameters:** None
|
||||
|
||||
**Returns:**
|
||||
- `jobs` (array of Job objects): List of all jobs with complete information
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "jobs.list",
|
||||
"params": []
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "job-123",
|
||||
"caller_id": "client-1",
|
||||
"context_id": "context-1",
|
||||
"payload": "print('Hello World')",
|
||||
"executor": "osis",
|
||||
"runner": "osis-runner-1",
|
||||
"timeout": 300,
|
||||
"env_vars": {},
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Specific Job Operations (`job.`)
|
||||
|
||||
#### `job.run`
|
||||
Runs a job immediately on the appropriate runner and returns the result.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job` (Job object): Complete job specification
|
||||
|
||||
**Returns:**
|
||||
- `result` (JobResult): Either success or error result
|
||||
|
||||
**JobResult Format:**
|
||||
```json
|
||||
// Success case
|
||||
{
|
||||
"success": "Job completed successfully with output..."
|
||||
}
|
||||
|
||||
// Error case
|
||||
{
|
||||
"error": "Job failed with error message..."
|
||||
}
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.run",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job": { /* job object */ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.start`
|
||||
Starts a previously created job by queuing it to its assigned runner.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job_id` (string): ID of the job to start
|
||||
|
||||
**Returns:** `null` (void)
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.start",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job_id": "job-123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.status`
|
||||
Gets the current status of a job.
|
||||
|
||||
**Parameters:**
|
||||
- `job_id` (string): ID of the job to check
|
||||
|
||||
**Returns:**
|
||||
- `status` (JobStatusResponse): Current job status information
|
||||
|
||||
**JobStatusResponse Format:**
|
||||
```json
|
||||
{
|
||||
"job_id": "job-123",
|
||||
"status": "running",
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"started_at": "2023-01-01T00:00:05Z",
|
||||
"completed_at": null
|
||||
}
|
||||
```
|
||||
|
||||
**Status Values:**
|
||||
- `created` - Job has been created but not queued
|
||||
- `queued` - Job has been queued to a runner
|
||||
- `running` - Job is currently executing
|
||||
- `completed` - Job finished successfully
|
||||
- `failed` - Job failed with an error
|
||||
- `timeout` - Job timed out
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.status",
|
||||
"params": ["job-123"]
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.result`
|
||||
Gets the result of a completed job. This method blocks until the result is available.
|
||||
|
||||
**Parameters:**
|
||||
- `job_id` (string): ID of the job to get results for
|
||||
|
||||
**Returns:**
|
||||
- `result` (JobResult): Either success or error result
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.result",
|
||||
"params": ["job-123"]
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.stop`
|
||||
Stops a running job.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job_id` (string): ID of the job to stop
|
||||
|
||||
**Returns:** `null` (void)
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.stop",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job_id": "job-123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.delete`
|
||||
Deletes a job from the system.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job_id` (string): ID of the job to delete
|
||||
|
||||
**Returns:** `null` (void)
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.delete",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job_id": "job-123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Workflow Examples
|
||||
|
||||
### Fire-and-Forget Job
|
||||
```javascript
|
||||
// Create and immediately run a job
|
||||
const result = await client.job_run(secret, jobSpec);
|
||||
if (result.success) {
|
||||
console.log("Job completed:", result.success);
|
||||
} else {
|
||||
console.error("Job failed:", result.error);
|
||||
}
|
||||
```
|
||||
|
||||
### Asynchronous Job Processing
|
||||
```javascript
|
||||
// 1. Create the job
|
||||
const jobId = await client.jobs_create(secret, jobSpec);
|
||||
|
||||
// 2. Start the job
|
||||
await client.job_start(secret, jobId);
|
||||
|
||||
// 3. Poll for completion (non-blocking)
|
||||
let status;
|
||||
do {
|
||||
status = await client.job_status(jobId);
|
||||
if (status.status === 'running') {
|
||||
await sleep(1000); // Wait 1 second
|
||||
}
|
||||
} while (status.status === 'running' || status.status === 'queued');
|
||||
|
||||
// 4. Get the result
|
||||
const result = await client.job_result(jobId);
|
||||
```
|
||||
|
||||
### Batch Job Management
|
||||
```javascript
|
||||
// Create multiple jobs
|
||||
const jobIds = [];
|
||||
for (const jobSpec of jobSpecs) {
|
||||
const jobId = await client.jobs_create(secret, jobSpec);
|
||||
jobIds.push(jobId);
|
||||
}
|
||||
|
||||
// Start all jobs
|
||||
for (const jobId of jobIds) {
|
||||
await client.job_start(secret, jobId);
|
||||
}
|
||||
|
||||
// Monitor progress
|
||||
const results = [];
|
||||
for (const jobId of jobIds) {
|
||||
const result = await client.job_result(jobId); // Blocks until complete
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
// Optional: Stop or delete jobs if needed
|
||||
for (const jobId of jobIds) {
|
||||
await client.job_stop(secret, jobId); // Stop running job
|
||||
await client.job_delete(secret, jobId); // Delete from system
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All job operations require authentication using one of the following secret types:
|
||||
|
||||
- **Admin secrets**: Full access to all operations
|
||||
- **User secrets**: Access to job operations (`jobs.create`, `job.run`, `job.start`)
|
||||
- **Register secrets**: Only access to runner registration
|
||||
|
||||
## Error Handling
|
||||
|
||||
All methods return standard JSON-RPC error responses for:
|
||||
|
||||
- **Authentication errors** (-32602): Invalid or missing secrets
|
||||
- **Job not found errors** (-32000): Job ID doesn't exist
|
||||
- **Internal errors** (-32603): Server-side processing errors
|
||||
|
||||
## Migration from Legacy API
|
||||
|
||||
### Old → New Method Names
|
||||
|
||||
| Legacy Method | New Method | Notes |
|
||||
|---------------|------------|-------|
|
||||
| `run_job` | `job.run` | Same functionality, new naming |
|
||||
| `list_jobs` | `jobs.list` | Same functionality, new naming |
|
||||
| `create_job` | `jobs.create` | Enhanced to not auto-queue |
|
||||
|
||||
### New Methods Added
|
||||
|
||||
- `job.start` - Start a created job
|
||||
- `job.stop` - Stop a running job
|
||||
- `job.delete` - Delete a job from the system
|
||||
- `job.status` - Get job status (non-blocking)
|
||||
- `job.result` - Get job result (blocking)
|
||||
|
||||
### API Changes
|
||||
|
||||
- **Job struct**: Replaced `job_type` field with `executor`
|
||||
- **jobs.list**: Now returns full Job objects instead of just job IDs
|
||||
- **Enhanced job lifecycle**: Added stop and delete operations
|
||||
|
||||
This provides much more granular control over job lifecycle management.
|
@@ -3,7 +3,27 @@
|
||||
"info": {
|
||||
"title": "Hero Supervisor OpenRPC API",
|
||||
"version": "1.0.0",
|
||||
"description": "OpenRPC API for managing Hero Supervisor runners and jobs"
|
||||
"description": "OpenRPC API for managing Hero Supervisor runners and jobs. Job operations follow the convention: 'jobs.' for general operations and 'job.' for specific job operations."
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Job": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"caller_id": { "type": "string" },
|
||||
"context_id": { "type": "string" },
|
||||
"payload": { "type": "string" },
|
||||
"runner": { "type": "string" },
|
||||
"executor": { "type": "string" },
|
||||
"timeout": { "type": "number" },
|
||||
"env_vars": { "type": "object" },
|
||||
"created_at": { "type": "string" },
|
||||
"updated_at": { "type": "string" }
|
||||
},
|
||||
"required": ["id", "caller_id", "context_id", "payload", "runner", "executor", "timeout", "env_vars", "created_at", "updated_at"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": [
|
||||
{
|
||||
@@ -41,8 +61,8 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run_job",
|
||||
"description": "Run a job on the appropriate runner",
|
||||
"name": "jobs.create",
|
||||
"description": "Create a new job without queuing it to a runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
@@ -51,20 +71,42 @@
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"caller_id": { "type": "string" },
|
||||
"context_id": { "type": "string" },
|
||||
"payload": { "type": "string" },
|
||||
"job_type": { "type": "string" },
|
||||
"runner_name": { "type": "string" },
|
||||
"timeout": { "type": "number" },
|
||||
"env_vars": { "type": "object" },
|
||||
"created_at": { "type": "string" },
|
||||
"updated_at": { "type": "string" }
|
||||
},
|
||||
"required": ["id", "caller_id", "context_id", "payload", "job_type", "runner_name", "timeout", "env_vars", "created_at", "updated_at"]
|
||||
"$ref": "#/components/schemas/Job"
|
||||
}
|
||||
},
|
||||
"required": ["secret", "job"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "job_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jobs.list",
|
||||
"description": "List all jobs",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "jobs",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/components/schemas/Job" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.run",
|
||||
"description": "Run a job on the appropriate runner and return the result",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job": {
|
||||
"$ref": "#/components/schemas/Job"
|
||||
}
|
||||
},
|
||||
"required": ["secret", "job"]
|
||||
@@ -74,7 +116,101 @@
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": {
|
||||
"type": ["string", "null"]
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": { "type": "string" }
|
||||
},
|
||||
"required": ["success"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": { "type": "string" }
|
||||
},
|
||||
"required": ["error"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.start",
|
||||
"description": "Start a previously created job by queuing it to its assigned runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job_id": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "job_id"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.status",
|
||||
"description": "Get the current status of a job",
|
||||
"params": [
|
||||
{
|
||||
"name": "job_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "status",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"job_id": { "type": "string" },
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["created", "queued", "running", "completed", "failed", "timeout"]
|
||||
},
|
||||
"created_at": { "type": "string" },
|
||||
"started_at": { "type": ["string", "null"] },
|
||||
"completed_at": { "type": ["string", "null"] }
|
||||
},
|
||||
"required": ["job_id", "status", "created_at"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.result",
|
||||
"description": "Get the result of a completed job (blocks until result is available)",
|
||||
"params": [
|
||||
{
|
||||
"name": "job_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": { "type": "string" }
|
||||
},
|
||||
"required": ["success"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": { "type": "string" }
|
||||
},
|
||||
"required": ["error"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -200,6 +336,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.stop",
|
||||
"description": "Stop a running job",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job_id": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "job_id"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.delete",
|
||||
"description": "Delete a job from the system",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job_id": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "job_id"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rpc.discover",
|
||||
"description": "OpenRPC discovery method - returns the OpenRPC document describing this API",
|
||||
|
Reference in New Issue
Block a user