Documentation Index
Fetch the complete documentation index at: https://mintlify.com/iii-hq/sdk/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The invocation API allows you to call functions registered by other workers. All invocation methods automatically propagate trace context when the otel feature is enabled.
Calling Functions
call
Call a function and wait for the result (with default 30-second timeout).
pub async fn call(
&self,
function_id: &str,
data: impl serde::Serialize,
) -> Result<Value, IIIError>
ID of the function to call
data
impl serde::Serialize
required
Input data to pass to the function (will be serialized to JSON)
The function’s return value, or an error if the call fails or times out
Example:
use iii_sdk::III;
use serde_json::json;
let iii = III::new("ws://localhost:49134");
iii.connect().await?;
let result = iii.call("user.get", json!({
"id": "user-123"
})).await?;
println!("User: {}", result);
call_with_timeout
Call a function with a custom timeout.
pub async fn call_with_timeout(
&self,
function_id: &str,
data: Value,
timeout: Duration,
) -> Result<Value, IIIError>
ID of the function to call
Input data as a serde_json::Value
Maximum time to wait for a response
The function’s return value, or IIIError::Timeout if the timeout is exceeded
Example:
use std::time::Duration;
use serde_json::json;
// Call with 5-second timeout
let result = iii.call_with_timeout(
"long_running_task",
json!({ "task": "process" }),
Duration::from_secs(5)
).await?;
call_void
Call a function without waiting for a response (fire-and-forget).
pub fn call_void<TInput>(
&self,
function_id: &str,
data: TInput,
) -> Result<(), IIIError>
where
TInput: Serialize
ID of the function to call
Input data to pass to the function
Returns immediately after sending the invocation (does not wait for result)
Example:
use serde_json::json;
// Fire-and-forget notification
iii.call_void("notifications.send", json!({
"user_id": "user-123",
"message": "Task completed"
}))?;
println!("Notification sent (not waiting for result)");
Legacy Aliases
The SDK also provides trigger, trigger_with_timeout, and trigger_void methods that are aliases for the call methods:
pub async fn trigger(&self, function_id: &str, data: impl serde::Serialize) -> Result<Value, IIIError>
pub async fn trigger_with_timeout(&self, function_id: &str, data: Value, timeout: Duration) -> Result<Value, IIIError>
pub fn trigger_void<TInput>(&self, function_id: &str, data: TInput) -> Result<(), IIIError>
These are functionally identical to call, call_with_timeout, and call_void.
Error Handling
Error Types
Function calls can fail with these errors:
pub enum IIIError {
NotConnected, // Client is not connected to engine
Timeout, // Call exceeded timeout duration
Remote { // Function returned an error
code: String,
message: String,
},
Handler(String), // Function handler panicked or failed
Serde(String), // Serialization/deserialization error
WebSocket(String), // WebSocket communication error
}
Handling Errors
Example:
use iii_sdk::IIIError;
use serde_json::json;
match iii.call("user.delete", json!({ "id": "user-123" })).await {
Ok(result) => {
println!("User deleted: {}", result);
}
Err(IIIError::Timeout) => {
eprintln!("Request timed out");
}
Err(IIIError::Remote { code, message }) => {
eprintln!("Remote error {}: {}", code, message);
}
Err(IIIError::NotConnected) => {
eprintln!("Not connected to engine");
}
Err(e) => {
eprintln!("Error: {}", e);
}
}
Trace Context Propagation
When the otel feature is enabled, trace context is automatically propagated with function calls:
#[cfg(feature = "otel")]
{
use iii_sdk::{III, with_span, SpanKind};
use serde_json::json;
let iii = III::new("ws://localhost:49134");
iii.connect().await?;
// Create a parent span
let result = with_span(
"process_order",
None,
Some(SpanKind::Internal),
|| async {
// This call will be a child span of "process_order"
let user = iii.call("user.get", json!({ "id": "user-123" })).await?;
// This call will also be a child span
let order = iii.call("order.create", json!({
"user": user,
"items": []
})).await?;
Ok(order)
}
).await?;
}
The SDK automatically:
- Injects W3C
traceparent and baggage headers into outbound calls
- Extracts these headers from inbound invocations
- Creates parent-child span relationships across function boundaries
Calling Engine Functions
The III Engine provides built-in functions:
List Functions
let result = iii.call("engine::functions::list", json!({})).await?;
let functions = result.get("functions").unwrap();
Or use the convenience method:
let functions = iii.list_functions().await?;
List Workers
let result = iii.call("engine::workers::list", json!({})).await?;
let workers = result.get("workers").unwrap();
Or use the convenience method:
let workers = iii.list_workers().await?;
use iii_sdk::WorkerMetadata;
let metadata = WorkerMetadata {
runtime: "rust".to_string(),
version: "0.4.1".to_string(),
name: "my-worker".to_string(),
os: "linux".to_string(),
telemetry: None,
};
iii.call_void("engine::workers::register", metadata)?;
Worker metadata is automatically registered when you call connect(), so you typically don’t need to call this manually.
Create Channel
let result = iii.call(
"engine::channels::create",
json!({ "buffer_size": 1000 })
).await?;
Or use the convenience method:
let channel = iii.create_channel(Some(1000)).await?;
Typed Invocations
For type-safe function calls, define request and response types:
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct CreateUserRequest {
name: String,
email: String,
}
#[derive(Deserialize)]
struct CreateUserResponse {
id: String,
name: String,
}
let request = CreateUserRequest {
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
let result = iii.call("user.create", request).await?;
let response: CreateUserResponse = serde_json::from_value(result)?;
println!("Created user: {} ({})", response.name, response.id);
See Also