On this page
article
Windmill
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)