Struct Windmill

Source
pub struct Windmill {
    pub workspace: String,
    pub token: String,
    pub base_internal_url: String,
    pub client_config: Configuration,
}

Fields§

§workspace: String§token: String§base_internal_url: String§client_config: Configuration

Implementations§

Source§

impl Windmill

Source

pub fn default() -> Result<Self, SdkError>

Creates a new Windmill instance with default configuration.

Reads configuration from environment variables:

  • WM_TOKEN for authentication token
  • WM_WORKSPACE for workspace name
  • BASE_INTERNAL_URL for API base URL (appends /api automatically)
§Errors

Returns SdkError if:

  • Required environment variables are missing
  • Environment variables cannot be read
Source

pub fn new( token: Option<String>, workspace: Option<String>, base_internal_url: Option<String>, ) -> Result<Self, SdkError>

Creates a new Windmill instance with optional overrides.

Falls back to environment variables for any None parameters:

  • WM_TOKEN if token is None
  • WM_WORKSPACE if workspace is None
  • BASE_INTERNAL_URL + “/api” if base_internal_url is None
§Parameters
  • token: Optional bearer token override
  • workspace: Optional workspace name override
  • base_internal_url: Optional base URL override (without /api suffix)
§Errors

Returns SdkError if:

  • Required environment variables are missing when needed
  • Environment variables cannot be read
Source

pub fn get_variable<'a>(&'a self, path: &'a str) -> Result<Value, SdkError>

Retrieves a variable from Windmill, automatically parsing it as JSON/YAML.

This is the convenience version that attempts to parse the variable value as:

  1. JSON (primary attempt)
  2. YAML (fallback if JSON parsing fails)
  3. Raw string (final fallback if both parsings fail)

For better performance when you know the format or don’t need parsing, use Self::get_variable_raw instead.

§Arguments
  • path - Variable path (e.g., “u/user/variable_name”)
§Example

use wmill::Windmill;
use serde_json::json;

let wm = Windmill::default()?;

// For a variable containing JSON: {"key": "value"}
let json_var = wm.get_variable("u/admin/config")?;

// For a variable containing plain text
let text_var = wm.get_variable("u/user/plaintext_note")?;

See also: Self::get_variable_raw for the unparsed version

Source

pub fn get_variable_raw<'a>(&'a self, path: &'a str) -> Result<String, SdkError>

This is the faster version when:

  • You know the variable contains plain text
  • You want to handle parsing yourself
  • You need maximum performance

Performance benefit comes from avoiding:

  1. JSON parsing attempt
  2. YAML parsing fallback
§Arguments
  • path - Variable path (e.g., “u/user/variable_name”)
§Example
use wmill::Windmill;
use serde_json::{json, Value};

let wm = Windmill::default()?;

// When you need the raw content
let raw_content = wm.get_variable_raw("u/user/custom_format")?;

// When you know it's JSON and want to parse it differently
let json_value: Value = serde_json::from_str(
    &wm.get_variable_raw("u/admin/config")?
)?;

See also: Self::get_variable for the auto-parsed version

Source

pub fn set_variable<'a>( &'a self, value: String, path: &'a str, is_secret: bool, ) -> Result<(), SdkError>

Creates or updates a variable in the workspace.

This function provides atomic variable management that:

  • Creates a new variable if it doesn’t exist
  • Updates an existing variable if found
  • Handles both regular and secret variables
§Parameters
  • value: The variable value to set
  • path: The variable path/identifier
  • is_secret: Whether to store as a secret (encrypted) variable
§Errors

Returns SdkError if:

  • Variable fetch fails for reasons other than “not found”
  • Variable creation fails
  • Variable update fails
  • Underlying API calls fail
§Notes
  • For new variables, defaults to empty description
  • Updates only modify the value (preserving other metadata)
  • Secret status can only be set during creation
Source

pub fn get_resource<'a, T: DeserializeOwned>( &'a self, path: &'a str, ) -> Result<T, SdkError>

Fetches and deserializes a resource into a concrete type.

This is the recommended way to access resources when you know the expected type. For raw JSON access or dynamic typing, use Self::get_resource_any instead.

§Type Parameters
  • T - Any type implementing DeserializeOwned (most structs with #[derive(Deserialize)])
§Arguments
  • path - The resource path (e.g., “u/user/resource_name”)
§Example
use wmill::Windmill;
use serde_json::{json, Value};
use serde::Deserialize;

#[derive(Deserialize)]
struct DbConfig {
    url: String,
    pool_size: Option<u32>,
}

let wm = Windmill::default()?;

// Directly deserialize to your type
let config: DbConfig = wm.get_resource("u/admin/db_connection")?;

See also: Self::get_resource_any for untyped version

Source

pub fn get_resource_any<'a>(&'a self, path: &'a str) -> Result<Value, SdkError>

Fetches a raw JSON Value from Windmill by path.

Use this when you need the raw JSON structure or don’t have a concrete type to deserialize into. For typed deserialization, prefer Self::get_resource instead.

§Arguments
  • path - The resource path (e.g., “u/user/resource_name”)
§Example
use wmill::Windmill;

let wm = Windmill::default()?;

// When you need to inspect the raw structure first
let json = wm.get_resource_any("u/admin/db_connection")?;

println!("Url is: {}", json["url"]);

See also: Self::get_resource for typed version

Source

pub fn set_resource<'a>( &'a self, value: Option<Value>, path: &'a str, resource_type: &'a str, ) -> Result<(), SdkError>

Creates or updates a resource in Windmill.

This function sets a resource’s value at the specified path, creating it if it doesn’t exist or updating it if it does. The resource will be of the specified type.

§Arguments
  • value - The value to set for the resource. Use None to create an empty resource.
  • path - The ownership path of the resource (e.g., “u/user/resource_name”). Defines permissions based on Windmill’s path prefix system.
  • resource_type - The type of resource to create (e.g., “postgresql”, “smtp”). Must be a pre-existing resource type.
§Examples
use wmill::Windmill;

let wm = Windmill::default()?;
wm.set_resource(
    Some(serde_json::json!({"host": "localhost", "port": 5432})),
    "u/admin/database",
    "postgresql"
)?;
Source

pub fn get_state<'a, T: DeserializeOwned>(&'a self) -> Result<T, SdkError>

Retrieves and deserializes the current typed state value for a script’s execution context.

This is the typed version of Self::get_state_any, automatically deserializing the state into the specified type T that implements serde::de::DeserializeOwned.

§Type Parameter
  • T - The type to deserialize into (must implement serde::de::DeserializeOwned)
§Examples
use wmill::Windmill;
use serde_json::{json, Value};
use serde::Deserialize;

#[derive(Deserialize)]
struct ScriptState {
    counter: i32,
    last_run: String,
}

let wm = Windmill::default()?;

// Get typed state
let state: ScriptState = wm.get_state()?;

println!("Counter: {}, Last run: {}", state.counter, state.last_run);
§Behavior Details
  • Uses same state path resolution as Self::get_state_any (WM_STATE_PATH_NEWWM_STATE_PATH fallback)
  • Performs runtime type checking during deserialization
§When to Use vs Self::get_state_any
Use Caseget_state<T>get_state_any
Known state structure✅ Preferred⚠️ Requires manual parsing
Dynamic state❌ Won’t compile✅ Works
Type safety✅ Compile-time checks❌ Runtime checks only
§Notes
  • For complex types, derive Deserialize using Serde attributes
  • Prefer this over Self::get_state_any when state schema is stable
  • State modifications should use corresponding Self::set_state with matching type
§See Also
Source

pub fn get_state_any<'a>(&'a self) -> Result<Value, SdkError>

Retrieves the current state value for a script’s execution context.

States persist data between runs of the same script by the same trigger (schedule or user). This is the untyped version that returns a generic Value.

§Examples
use wmill::Windmill;
use serde_json::Value;
use serde::Deserialize;

let wm = Windmill::default()?;

// Get state (returns serde_json::Value)
let state: Value = wm.get_state_any()?;

// Use with default if empty
let counter = state.as_i64().unwrap_or(0);
§Behavior Details
  • Automatically uses the script’s state path from WM_STATE_PATH_NEW (falls back to WM_STATE_PATH)
  • Returns the full state object stored as a Windmill resource
  • State resources are hidden from Workspace view but visible under Resources → States
§Typical Use Cases
  1. Maintaining counters between runs
  2. Storing last execution timestamps
  3. Keeping reference data (like previous API responses)
§Notes
  • For typed state access, use get_state<T> instead
  • States are isolated per script and trigger combination
  • Maximum state size: 5MB (compressed)
§See Also
Source

pub fn set_state<'a>(&'a self, value: Option<Value>) -> Result<(), SdkError>

Updates or clears the script’s persistent state.

§Arguments
  • value - New state value (Some(Value)) or None to clear state
§Examples
use wmill::Windmill;
use serde_json::json;

let wm = Windmill::default()?;

// Set state
wm.set_state(Some(json!({"count": 42})))?;

// Clear state
wm.set_state(None)?;

See also: Self::get_state, Self::get_state_any

Source

pub fn run_script_sync<'a>( &'a self, ident: &'a str, ident_is_hash: bool, args: Value, scheduled_in_secs: Option<u32>, timeout_secs: Option<u64>, verbose: bool, assert_result_is_not_none: bool, ) -> Result<Value, SdkError>

Executes a script synchronously and waits for its completion.

This is a blocking version of run_script_async that handles the entire script execution lifecycle including job scheduling and result waiting.

§Parameters
  • ident: Script identifier (either path or hash)
  • ident_is_hash: Whether the identifier is a hash (true) or path (false)
  • args: JSON arguments to pass to the script
  • scheduled_in_secs: Optional delay before execution (in seconds)
  • timeout_secs: Maximum time to wait for job completion (in seconds)
  • verbose: Whether to print execution details
  • assert_result_is_not_none: Whether to fail if the result is None
§Errors

Returns SdkError if:

  • Script fails to start
  • Job times out
  • Result assertion fails
  • Underlying API calls fail
Source

pub fn run_script_async<'a>( &'a self, ident: &'a str, ident_is_hash: bool, args: Value, scheduled_in_secs: Option<u32>, ) -> Result<Uuid, SdkError>

Asynchronously executes a script in Windmill and returns its job UUID.

This function runs a script either by path or by hash, with optional:

  • Parent job inheritance (when run within a flow)
  • Scheduled execution delay
  • Argument passing
§Arguments
  • ident - Script identifier (path or hash depending on ident_is_hash)
  • ident_is_hash - If true, ident is treated as a script hash; if false, as a path
  • args - JSON arguments to pass to the script (must be an object if using path)
  • scheduled_in_secs - Optional delay (in seconds) before execution
§Examples
use wmill::Windmill;
use serde_json::json;

let wm = Windmill::default()?;
let job_id = wm.run_script_async(
    "u/user/script_path",
    false,
    json!({"param1": "value1"}),
    Some(10) // Run after 10 seconds
)?;
§Behavior Details
  • Automatic Job Inheritance:
    • Detects WM_JOB_ID env var → sets as parent_job
    • Detects WM_ROOT_FLOW_JOB_ID env var → sets as root_job
  • Scheduled Execution:
    • When scheduled_in_secs is provided, sets scheduled_in_secs in args
  • Argument Handling:
    • For path-based execution (ident_is_hash=false), args must be a JSON object
    • For hash-based execution, args can be any valid JSON value
§Errors
  • SdkError::BadValue if path-based execution receives non-object arguments
  • API errors from Windmill’s backend
Source

pub fn wait_job<'a>( &'a self, job_id: &'a str, timeout_secs: Option<u64>, verbose: bool, assert_result_is_not_none: bool, ) -> Result<Value, SdkError>

Waits for a job to complete and returns its result.

This function provides both synchronous and asynchronous interfaces for waiting on job completion, with timeout handling and result validation.

§Parameters
  • job_id: The ID of the job to wait for
  • timeout_secs: Maximum time to wait (in seconds) before cancelling the job
  • verbose: Whether to print progress information
  • assert_result_is_not_none: Whether to fail if the job returns no result
§Errors

Returns SdkError if:

  • Job fails or times out
  • Result assertion fails when assert_result_is_not_none is true
  • Underlying API calls fail
§Behavior
  1. Polls job status at 500ms intervals
  2. Cancels job if timeout is reached
  3. Validates success status and optional result presence
  4. Returns either the result or appropriate error
Source

pub fn get_job_status<'a>( &'a self, job_id: &'a str, ) -> Result<JobStatus, SdkError>

Retrieves the current status of a Windmill job by its UUID.

This function queries the Windmill backend to determine whether a job is:

  • Waiting to be executed
  • Currently running
  • Already completed
§Arguments
  • job_id - The UUID of the job to check (format: “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”)
§Job Lifecycle States
  • Waiting: Job is queued but hasn’t started execution
  • Running: Job is currently being executed
  • Completed: Job has finished (successfully or with errors)
Source

pub fn get_result<'a>(&'a self, job_id: &'a str) -> Result<Value, SdkError>

Retrieves the result of a completed job.

This provides both synchronous and asynchronous interfaces for fetching the final result of a successfully completed job.

§Parameters
  • job_id: The ID of the completed job to fetch results for
§Errors

Returns SdkError if:

  • Job is not found
  • Job failed to complete successfully
  • Underlying API calls fail
  • Result cannot be parsed
§Notes
  • Only works for jobs that have already completed
  • For pending/running jobs, use wait_job instead
  • Does not handle timeouts or polling - assumes job is already complete
Source

pub fn set_progress<'a>( &'a self, value: u32, job_id: Option<String>, ) -> Result<(), SdkError>

Updates the progress percentage of a running Windmill job.

This function allows scripts to report their execution progress (0-100%) back to the Windmill UI. Progress updates are visible in both the jobs dashboard and flow visualizations.

§Arguments
  • value - Progress percentage (0-100)
  • job_id - Optional job UUID. If None, uses current job’s ID from WM_JOB_ID environment variable
§Examples
use wmill::Windmill;
let wm = Windmill::default()?;

// Report progress for current job
wm.set_progress(25, None)?;
§Behavior Details
  • Automatically handles flow context by detecting parent job ID
  • Progress updates are reflected in real-time in the Windmill UI
  • Typical usage pattern:
    for (i, item) in items.iter().enumerate() {
        process(item);
        let progress = ((i + 1) * 100 / items.len()) as i32;
        wmill.set_progress(progress, None).await?;
    }
§Notes
  • Only affects jobs that are currently running
  • Progress values outside 0-99 range are clamped by the server
  • Progress cannot decrease
  • For flows, updates the progress of both the step and parent flow
§See Also
Source

pub fn get_progress<'a>( &'a self, job_id: Option<String>, ) -> Result<u32, SdkError>

Retrieves the current progress percentage of a Windmill job.

This function queries the Windmill backend to get the execution progress (0-100%) of either a specific job or the current job context.

§Arguments
  • job_id - Optional job UUID. If None, uses current job’s ID from WM_JOB_ID env var
§See Also
Source

pub fn call_api<'a, T>( &'a self, callback: impl Future<Output = T> + Send + 'a, ) -> T

Executes an API call in either asynchronous or synchronous mode based on compilation context.

This function serves as a bridge between async and sync code, automatically adapting its behavior:

  • With async feature: Returns a boxed future for later await
  • Without async feature: Blocks immediately using the global runtime
§Examples
§Async usage (with async feature)
use wmill::Windmill;
let wm = Windmill::default()?;
let user = wm.call_api(wmill::apis::admin_api::get_user(&wm.client_config, &wm.workspace, "Bob"))?;
println!("User details: {:?}", user);
§Sync usage (without async feature)
use wmill::Windmill;
let wm = Windmill::new(Some("<TOKEN>".into()), Some("admins".into()), Some("http://localhost:5000/api".into()))?;
let user = wm.call_api(wmill::apis::admin_api::get_user(&wm.client_config, &wm.workspace, "Bob"));
println!("User details: {:?}", user);

Trait Implementations§

Source§

impl Clone for Windmill

Source§

fn clone(&self) -> Windmill

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Windmill

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,