Guide to Windmill, the CI / API Endpoint Tool

Javascript / Typescript

Async fetch query

  async function asyncWindmillPost(urlPrefix: string, functionHash: string, token: string, requestBody: object) {
  const requestOptions = {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      "Accept": "text/plain",
    },
    body: JSON.stringify(requestBody),
  };

  async function getStatus(statusUuid) {
  	const res = await fetch(`${urlPrefix}/result/${statusUuid}`, {
    	headers: {
    		Authorization: `Bearer ${token}`,
    		Accept: "application/json",
    	}
    })
    return res.json()
  }

  const resStatus = await fetch(`${urlPrefix}/a/${functionHash}`, requestOptions)
  const statusUuid = await resStatus.text()
  let status = await getStatus(statusUuid)

  while(!status.completed) {
    await new Promise(resolve => setTimeout(resolve, 1000));
  	status = await getStatus(statusUuid)
  }
}
  

Async with retry logic

  export async function windmillRequest(
  urlPrefix: string,
  functionHash: string,
  token: string,
  requestBody: object
) {

  const headers = {
    Authorization: `Bearer ${token}`,
  }
  const requestOptions = {
    method: "POST",
    headers: {
      ...headers,
      "Content-Type": "application/json",
      Accept: "text/plain",
    },
    body: JSON.stringify(requestBody)
  };

  async function getStatus(statusUuid: string): Promise<any> {
    const res = await retry(fetch, 5, `${urlPrefix}/result/${statusUuid}`, {
      headers: {
        ...headers,
        Accept: "application/json",
      }
    });
    return res.json();
  }

  const resStatus = await retry(fetch, 5, `${urlPrefix}/a/${functionHash}`, requestOptions);
  const statusUuid = await resStatus.text();
  let status = await getStatus(statusUuid);

  let waitTime = 1
  while (!status.completed) {
      status = await getStatus(statusUuid);
      const backoff = Math.floor(Math.random() * Math.pow(2, waitTime++));
      await new Promise((resolve) => setTimeout(resolve, backoff * 1000));
  }
  return status.result;
}

/**
 * Retry a function n times with exponential backoff.
 * Example: retry(exampleFunction, 3, 5, 10) will do 3 retries of exampleFunction(5, 10)
 */
async function retry<T>( fn: (...args: any[]) => Promise<T>, n: number, ...args: any[] ): Promise<T> {
  for (let i = 0; i < n; i++) {
    try {
      return await fn(...args);
    } catch (e) {
      console.error(e);
      const backoff = Math.floor(Math.random() * Math.pow(2, i));
      await new Promise((resolve) => setTimeout(resolve, backoff * 1000));
    }
  }
  throw new Error("Retry limit exceeded");
}
  

Python

Requests

  import requests
import time
import random


def windmill_request(url_prefix, function_hash, token, request_body):
    headers = {
        'Authorization': f'Bearer {token}',
        "Content-Type": "application/json",
        "Accept": "text/plain",
    }

    def get_status(status_uuid: str):
        return retry(requests.get, 5, f'{url_prefix}/result/{status_uuid}', headers=headers).json()

    # res_status = retry(requests.post, 5, f'{url_prefix}/a/{function_hash}', headers=headers, json=request_body)
    res_status = retry(requests.post, 5, f'{url_prefix}/a/{function_hash}', headers=headers, json=request_body)
    status_uuid = res_status.text
    status = get_status(status_uuid)

    wait_time = 1
    while not status.get('completed', False):
        status = get_status(status_uuid)
        time.sleep(random.randint(1, 2 ** wait_time))
        wait_time += 1

    return status.get('result')

def retry(method, max_attempts, *args, **kwargs):
    for attempt in range(max_attempts):
        try:
            print(*args, kwargs)
            response = method(*args, **kwargs)
            response.raise_for_status()
            return response
        except Exception as e:
            print(e)
            time.sleep(random.randint(1, 2 ** attempt))
    raise Exception("Retry limit exceeded")


if __name__ == '__main__':
    url_prefix = 'https://windmill.tld'
    function_hash = 'post_hash_value'
    token = 'token_value'
    request_body = { "key": "value" }

    res = windmill_request(url_prefix, function_hash, token, request_body)
    print(res)