pub struct RuntaraSdk { /* private fields */ }Expand description
High-level SDK client for instance communication with runtara-core.
This client wraps a backend (QUIC or embedded) and provides ergonomic methods for all instance lifecycle operations.
§Example (QUIC mode)
use runtara_sdk::RuntaraSdk;
let mut sdk = RuntaraSdk::localhost("my-instance", "my-tenant")?;
sdk.connect().await?;
sdk.register(None).await?;
// Process items with checkpointing
for i in 0..items.len() {
let state = serde_json::to_vec(&my_state)?;
if let Some(existing) = sdk.checkpoint(&format!("item-{}", i), &state).await? {
// Resuming - restore state and skip
my_state = serde_json::from_slice(&existing)?;
continue;
}
// Fresh execution - process item
process_item(&items[i]);
}
sdk.completed(b"result").await?;§Example (Embedded mode)
use runtara_sdk::RuntaraSdk;
use std::sync::Arc;
// Create persistence layer (e.g., SQLite or PostgreSQL)
let persistence: Arc<dyn Persistence> = create_persistence().await?;
let mut sdk = RuntaraSdk::embedded(persistence, "my-instance", "my-tenant");
sdk.connect().await?; // No-op for embedded
sdk.register(None).await?;
// Same checkpoint API works with embedded mode
for i in 0..items.len() {
let state = serde_json::to_vec(&my_state)?;
let result = sdk.checkpoint(&format!("item-{}", i), &state).await?;
// ...
}
sdk.completed(b"result").await?;Implementations§
Source§impl RuntaraSdk
impl RuntaraSdk
Sourcepub fn new(config: SdkConfig) -> Result<RuntaraSdk, SdkError>
pub fn new(config: SdkConfig) -> Result<RuntaraSdk, SdkError>
Create a new SDK instance with the given configuration.
This creates a QUIC-based SDK that connects to runtara-core over the network.
Sourcepub fn from_env() -> Result<RuntaraSdk, SdkError>
pub fn from_env() -> Result<RuntaraSdk, SdkError>
Create an SDK instance from environment variables.
See SdkConfig::from_env for required and optional environment variables.
Sourcepub fn localhost(
instance_id: impl Into<String>,
tenant_id: impl Into<String>,
) -> Result<RuntaraSdk, SdkError>
pub fn localhost( instance_id: impl Into<String>, tenant_id: impl Into<String>, ) -> Result<RuntaraSdk, SdkError>
Create an SDK instance for local development.
This connects to 127.0.0.1:8001 with TLS verification disabled.
Sourcepub async fn init(self, checkpoint_id: Option<&str>) -> Result<(), SdkError>
pub async fn init(self, checkpoint_id: Option<&str>) -> Result<(), SdkError>
Initialize SDK: connect, register, and make available globally for #[durable].
This is a convenience method that combines:
connect()- establish connection to runtara-coreregister(checkpoint_id)- register this instanceregister_sdk()- make SDK available globally for #[durable] functions
§Example
use runtara_sdk::RuntaraSdk;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// One-liner setup for #[durable] functions
RuntaraSdk::localhost("my-instance", "my-tenant")?
.init(None)
.await?;
// Now #[durable] functions work automatically
my_durable_function("key".to_string(), args).await?;
Ok(())
}Sourcepub async fn is_connected(&self) -> bool
pub async fn is_connected(&self) -> bool
Check if connected to runtara-core.
Sourcepub async fn register(
&mut self,
checkpoint_id: Option<&str>,
) -> Result<(), SdkError>
pub async fn register( &mut self, checkpoint_id: Option<&str>, ) -> Result<(), SdkError>
Register this instance with runtara-core.
This should be called at instance startup. If checkpoint_id is provided,
the instance is resuming from a checkpoint.
Sourcepub async fn checkpoint(
&self,
checkpoint_id: &str,
state: &[u8],
) -> Result<CheckpointResult, SdkError>
pub async fn checkpoint( &self, checkpoint_id: &str, state: &[u8], ) -> Result<CheckpointResult, SdkError>
Checkpoint with the given ID and state.
This is the primary checkpoint method that handles both save and resume:
- If a checkpoint with this ID already exists, returns the existing state (for resume)
- If no checkpoint exists, saves the provided state and returns None
This also serves as a heartbeat - each checkpoint call reports progress to runtara-core.
The returned CheckpointResult also includes any pending signal (cancel, pause)
that the instance should handle after processing the checkpoint.
§Example
// In a loop - checkpoint handles both fresh runs and resumes
for i in 0..items.len() {
let checkpoint_id = format!("item-{}", i);
let result = sdk.checkpoint(&checkpoint_id, &state).await?;
// Check for pending signals
if result.should_cancel() {
return Err("Cancelled".into());
}
if result.should_pause() {
// Exit cleanly - will be resumed later
return Ok(());
}
if let Some(existing_state) = result.existing_state() {
// Resuming - restore state and skip already-processed work
state = serde_json::from_slice(existing_state)?;
continue;
}
// Fresh execution - process item
process_item(&items[i]);
}Sourcepub async fn get_checkpoint(
&self,
checkpoint_id: &str,
) -> Result<Option<Vec<u8>>, SdkError>
pub async fn get_checkpoint( &self, checkpoint_id: &str, ) -> Result<Option<Vec<u8>>, SdkError>
Get a checkpoint by ID without saving (read-only lookup).
Returns the checkpoint state if found, or None if not found. Use this when you want to check if a cached result exists before executing.
§Example
// Check if result is already cached
if let Some(cached_state) = sdk.get_checkpoint("my-operation").await? {
let result: MyResult = serde_json::from_slice(&cached_state)?;
return Ok(result);
}
// Not cached - execute operation and save result
let result = do_expensive_operation();
let state = serde_json::to_vec(&result)?;
sdk.checkpoint("my-operation", &state).await?;Sourcepub async fn sleep(
&self,
duration: Duration,
checkpoint_id: &str,
state: &[u8],
) -> Result<(), SdkError>
pub async fn sleep( &self, duration: Duration, checkpoint_id: &str, state: &[u8], ) -> Result<(), SdkError>
Request to sleep for the specified duration.
This is a durable sleep that persists across restarts:
- Saves a checkpoint with the provided state
- Records the wake time (
sleep_until) in the database - On resume, calculates remaining time and only sleeps for the remainder
In QUIC mode, the server tracks the wake time. In embedded mode, the persistence layer tracks it directly.
Sourcepub async fn heartbeat(&self) -> Result<(), SdkError>
pub async fn heartbeat(&self) -> Result<(), SdkError>
Send a heartbeat event (simple “I’m alive” signal).
Use this for progress reporting without checkpointing.
For durable progress, use checkpoint() instead.
Sourcepub async fn completed(&self, output: &[u8]) -> Result<(), SdkError>
pub async fn completed(&self, output: &[u8]) -> Result<(), SdkError>
Send a completed event with output.
Sourcepub async fn failed(&self, error: &str) -> Result<(), SdkError>
pub async fn failed(&self, error: &str) -> Result<(), SdkError>
Send a failed event with error message.
Sourcepub async fn custom_event(
&self,
subtype: &str,
payload: Vec<u8>,
) -> Result<(), SdkError>
pub async fn custom_event( &self, subtype: &str, payload: Vec<u8>, ) -> Result<(), SdkError>
Send a custom event with arbitrary subtype and payload.
This is a fire-and-forget event stored by runtara-core with the given subtype. Core treats the subtype as an opaque string without any semantic interpretation.
§Arguments
subtype- Arbitrary event subtype stringpayload- Event payload as raw bytes (typically JSON serialized)
§Example
let payload = serde_json::to_vec(&my_event_data)?;
sdk.custom_event("my_custom_event", payload).await?;Sourcepub async fn poll_signal(&mut self) -> Result<Option<Signal>, SdkError>
pub async fn poll_signal(&mut self) -> Result<Option<Signal>, SdkError>
Poll for pending signals.
Rate-limited to avoid hammering the server.
Returns Some(Signal) if a signal is pending, None otherwise.
Note: Only available with QUIC backend.
Sourcepub async fn poll_signal_now(&mut self) -> Result<Option<Signal>, SdkError>
pub async fn poll_signal_now(&mut self) -> Result<Option<Signal>, SdkError>
Force poll for signals (ignoring rate limit).
Note: Only available with QUIC backend.
Sourcepub async fn acknowledge_signal(
&self,
signal_type: SignalType,
acknowledged: bool,
) -> Result<(), SdkError>
pub async fn acknowledge_signal( &self, signal_type: SignalType, acknowledged: bool, ) -> Result<(), SdkError>
Acknowledge a received signal.
Note: Only available with QUIC backend.
Sourcepub async fn check_cancelled(&mut self) -> Result<(), SdkError>
pub async fn check_cancelled(&mut self) -> Result<(), SdkError>
Check for cancellation and return error if cancelled.
Convenience method for use in execution loops:
for item in items {
sdk.check_cancelled().await?;
// process item...
}Note: Only available with QUIC backend.
Sourcepub async fn check_paused(&mut self) -> Result<(), SdkError>
pub async fn check_paused(&mut self) -> Result<(), SdkError>
Check for pause and return error if paused.
Note: Only available with QUIC backend.
Sourcepub async fn record_retry_attempt(
&self,
checkpoint_id: &str,
attempt_number: u32,
error_message: Option<&str>,
) -> Result<(), SdkError>
pub async fn record_retry_attempt( &self, checkpoint_id: &str, attempt_number: u32, error_message: Option<&str>, ) -> Result<(), SdkError>
Record a retry attempt for audit trail.
This is a fire-and-forget operation that records a retry attempt
in the checkpoint history. Called by the #[durable] macro when
a function fails and is about to be retried.
§Arguments
checkpoint_id- The durable function’s cache keyattempt_number- The 1-indexed retry attempt numbererror_message- Error message from the previous failed attempt
Sourcepub async fn get_status(&self) -> Result<StatusResponse, SdkError>
pub async fn get_status(&self) -> Result<StatusResponse, SdkError>
Get the current status of this instance.
Sourcepub async fn get_instance_status(
&self,
instance_id: &str,
) -> Result<StatusResponse, SdkError>
pub async fn get_instance_status( &self, instance_id: &str, ) -> Result<StatusResponse, SdkError>
Get the status of another instance.
Note: Only available with QUIC backend.
Sourcepub fn instance_id(&self) -> &str
pub fn instance_id(&self) -> &str
Get the instance ID.
Sourcepub fn is_registered(&self) -> bool
pub fn is_registered(&self) -> bool
Check if the instance is registered.
Sourcepub fn heartbeat_interval_ms(&self) -> u64
pub fn heartbeat_interval_ms(&self) -> u64
Get the configured heartbeat interval in milliseconds. Returns 0 if automatic heartbeats are disabled.