Querying Task Status and Output
Fetching task status using the API
Once a task has been accepted, you can use its TaskID
to query the status of the task from the API by making a GET request to /tasks/{taskID}.
The Signaloid Cloud Compute Engine returns the task status in the Status field of the response object.
You should continue to poll the API until the task status is in a terminal state; i.e., either Completed, Cancelled, or Stopped.
- TypeScript
- cURL
The code snippet below shows how to fetch the status of the task from the API using the axios library.
interface TaskAPIResponse {
data: {
Status: string;
// Add other properties here
};
}
let taskID = taskPostResponse.data.TaskID;
let taskStatus = "";
let retryCountTask = 0;
let retryDelayTask = 2000;
let taskStdout: string;
const maxRetryDelayTask = 30000;
console.log("Waiting for the task to finish...");
// Keep checking until build reaches terminal state
while (!["Completed", "Cancelled", "Stopped"].includes(taskStatus)) {
try {
const response: TaskAPIResponse = await signaloidClient.get(`/tasks/${taskID}`);
taskStatus = response.data.Status;
console.log(`...task status: ${taskStatus}`);
if (!["Completed", "Cancelled", "Stopped"].includes(taskStatus)) {
// Calculate delay with exponential backoff
retryDelayTask = Math.min(Math.pow(2, retryCountTask) * 1000, maxRetryDelayTask);
console.log(`Task still active. Waiting ${retryDelayTask}ms before retry...`);
// Wait before next check
await new Promise(resolve => setTimeout(resolve, retryDelayTask));
retryCountTask++;
}
} catch (error) {
console.error("Error checking build status:", error);
throw error;
}
}
// task is in a terminal state
console.log(`Task in terminal state : ${taskStatus}. Can fetch task outputs.`);
await getTaskOutputs(taskID); // `getTaskOutputs` is defined below.
await getTaskOutputsChunks(taskID) // `getTaskOutputsChunks` is defined below. To be used as an alternative if stdout is large.
await getTaskStreamOutput(taskID, "Stdout"); // `getTaskStreamOutput` is defined below. An alternative to `/outputs` that fetches a single stream directly.
The code snippet below shows how to fetch the status of the task from the API using curl.
# The following calls to the Signaloid API check whether your task has completed its execution.
# Delay for consecutive calls to the API.
delayForAPIPolling=2
# The following call to the Signaloid API gets back the Task status.
# The call queries the `tasks` endpoint using the Task ID. The output
# is redirected to the `jq` utility to retrieve the `Status` field.
taskStatus=$(curl -s --request GET --location https://api.signaloid.io/tasks/$taskID \
--header "Authorization: $signaloidAPIKey" \
| jq -r '.Status')
while [ "$taskStatus" != "Completed" ] && [ "$taskStatus" != "Cancelled" ] && [ "$taskStatus" != "Stopped" ];
do
echo "Specified task status is: \""$taskStatus\"". Waiting."
sleep $delayForAPIPolling
# The following call to the Signaloid API gets back the Task status.
taskStatus=$(curl -s --request GET --location https://api.signaloid.io/tasks/$taskID \
--header "Authorization: $signaloidAPIKey" \
| jq -r '.Status')
done
echo "Task "$taskID" completed with status: \""$taskStatus"\""
Retrieving task outputs from the API
Once the task is in a terminal state, you can retrieve the outputs of the task from the API by making a GET request to /tasks/{taskID}/outputs.
- TypeScript
- cURL
The code snippet below shows an implementation of the getTaskOutputs placeholder function referred to in the previous step that will fetch the outputs of the task from the API using the axios library.
// Helper function for fetching task output
async function getTaskOutputs(taskID: string) {
console.log("Fetching task outputs...");
try {
// get task data from API
const taskOutputsResponse = await signaloidClient.get(`/tasks/${taskID}/outputs`);
if (taskOutputsResponse.data.Stdout) {
const outputStream = await axios.get(taskOutputsResponse.data.Stdout);
taskStdout = outputStream.data;
console.log(`Task Stdout: \n${taskStdout}`);
}
} catch (error) {
console.log("Error:", error);
}
}
The code snippet below shows how to get the standard output (stdout) of the task from the API using curl.
# Use this API endpoint to get the Task output using a taskID
taskOutputsEndpointResponse=$(curl --request GET \
--location 'https://api.signaloid.io/tasks/'$taskID'/outputs' \
--header "Authorization: $signaloidAPIKey")
# The tasks outputs endpoint contains multiple fields. You can use the following to get the field corresponding to `stdout`
taskStdout=$(echo $taskOutputsEndpointResponse | jq -r '.Stdout')
if [ "$taskStdout" == "null" ];
then
errorMessage=$(echo $taskOutputsEndpointResponse | jq -r '.error')
echo "Task outputs endpoint returned error message: \""$errorMessage"\""
exit 1
else
# Use curl to download and print the Task output
curl "$taskStdout"
fi
- TypeScript
- cURL
The code snippet below shows how to get the first compressed chunk of standard output (stdout) of the task from the API using the axios library.
async function getTaskOutputsChunks(taskID: string) {
console.log("Fetching task outputs...");
try {
const taskOutputsResponse = await signaloidClient.get(`/tasks/${taskID}/outputs`);
if (taskOutputsResponse.data.StdoutChunks.length) {
const response = await axios.get(taskOutputsResponse.data.StdoutChunks[0], {
responseType: "arraybuffer",
});
// The chunks are GZIP-compressed. `DecompressionStream` is a Web standard
// available both in browsers and in Node 18+, so inflating the chunk needs
// no third-party library.
const gzipStream = new Response(response.data).body.pipeThrough(
new DecompressionStream("gzip")
);
const decompressedStdOutChunk = await new Response(gzipStream).text();
console.log(`Task Stdout First Chunk: \n${decompressedStdOutChunk}`);
}
} catch (error) {
console.log("Error :>> ", error);
}
}
The code snippet below shows how to get the first compressed chunk of standard output (stdout) of the task from the API using curl.
# Use this API endpoint to get the Task outputs using a taskID
taskOutputsEndpointResponse=$(curl -s --request GET \
--location 'https://api.signaloid.io/tasks/'$taskID'/outputs' \
--header "Authorization: $signaloidAPIKey")
# The tasks outputs endpoint contains multiple fields. You can use the following to get the URL
# of the first compressed chunk of the standard output stream (`StdoutChunks`)
firstStdoutChunkURL=$(echo $taskOutputsEndpointResponse | jq -r '.StdoutChunks[0]')
if [ "$firstStdoutChunkURL" == "null" ];
then
echo "The task has no compressed standard output chunks."
else
# Use curl to download the compressed chunk and decompress it using `gzip`
curl -s "$firstStdoutChunkURL" | gzip -d
The task outputs response will have the following shape:
{
"Stdout": "<presigned URL>",
"Stderr": "<presigned URL>",
"StdoutChunks": ["<presigned URL>", "..."]
}
The Stdout and Stderr keys are each a URL to the file containing the output of the task from the corresponding output stream.
The Stdout and Stderr streams may not be available for tasks that failed.
The StdoutChunks is an array of URLs, one per compressed chunk of the standard output stream, in order. After the completion of a task, these chunks let you fetch and decompress the output incrementally rather than downloading the entire Stdout stream; the cURL and TypeScript examples above fetch and decompress only the first chunk (StdoutChunks[0]).
Retrieving a single output stream directly
You can fetch a single output stream (Stdout or Stderr) of a Task with a GET /tasks/{taskID}/output/{Stream} request. Stream can be Stdout or Stderr.
This endpoint returns the plain text content of the stream for outputs of size 5 MB or less. For larger outputs, the endpoint returns a HTTP 302 redirect with the Location header pointing to the download URL for the stream content.
- TypeScript
- cURL
The code snippet below shows how to fetch the Stdout stream of the task directly from the API using axios which follows the redirect automatically. This works correctly regardless of the size of the output.
// Helper function for fetching a task's output stream (`Stdout` or `Stderr`) directly.
// For outputs larger than 5 MB, the API responds with an HTTP redirect to a download URL
// instead of the plain text content; axios follows this redirect automatically, so
// `taskStreamOutputResponse.data` will contain the stream content in both cases.
async function getTaskStreamOutput(taskID: string, stream: "Stdout" | "Stderr") {
console.log(`Fetching task ${stream} stream output...`);
try {
const taskStreamOutputResponse = await signaloidClient.get(`/tasks/${taskID}/output/${stream}`);
console.log(`Task ${stream}: \n${taskStreamOutputResponse.data}`);
} catch (error) {
console.log("Error:", error);
}
}
The code snippet below shows how to fetch the Stdout stream of the task directly from the API using curl.
For small outputs, the API responds with the plain text content directly (HTTP 200). For outputs larger than 5 MB, the API instead responds with an HTTP 302 redirect and a Location header pointing to a download URL.
Since the redirect response is not guaranteed to accept the Authorization header, the snippet checks the response status and follows the Location header manually rather than letting curl follow the redirect automatically.
# Output stream to fetch: "Stdout" or "Stderr"
outputStream="Stdout"
taskStreamOutputHeaders=$(mktemp)
taskStreamOutputBody=$(curl -s --request GET \
--dump-header "$taskStreamOutputHeaders" \
'https://api.signaloid.io/tasks/'$taskID'/output/'$outputStream \
--header "Authorization: $signaloidAPIKey")
taskStreamOutputStatus=$(head -n 1 "$taskStreamOutputHeaders" | awk '{print $2}')
if [ "$taskStreamOutputStatus" == "302" ];
then
# The output was larger than 5 MB. Follow the download URL from the `Location` header.
# The download URL is a presigned URL and does not require the `Authorization` header.
downloadURL=$(grep -i '^location:' "$taskStreamOutputHeaders" | sed -E 's/^[Ll]ocation: *//' | tr -d '\r')
curl -s "$downloadURL"
else
echo "$taskStreamOutputBody"
fi
rm -f "$taskStreamOutputHeaders"
Output of an uncertainty-tracking (UT) C0 or C0 Pro core
For each floating-point variable that you print in the stdout or stderr of your application, the Signaloid Cloud Compute Engine also prints the distributional
information of the variable in the form of the Uncertainty Hexadecimal (“Ux”) data format.
You can instruct the Signaloid Cloud Compute Engine to avoid printing the Ux data format by using the particle %P modifier when printing floating-point values.
You can feed the Ux data format in other Signaloid Cloud Compute Engine endpoints, e.g., for sampling or plotting the associated distributional information.
For example, the file containing the output of the Stdout stream should contain text similar to the following:
Alloy strength (σc) = 6.5E+02Ux0400000000000010004086182D94915B0500000040405417BDA0AC9B250188F2CF171EF8E0405B6757D802080F01AA44F4C3CE568040605E6EDBDD0AA702040E39582CDA604062549EC48E6D54020049C5A87763C040640CD2FABF29F1022269E95ECAD3204065A2D65BCAA361022F84B7CF914A00406727AAD835034E022C821EA01770804068ABA18A9EE5DC0233ECFFBF89D480406A1A71BCBA96AA021309E840103300406B7F731CA16D9D023008CD59709980406CEA500FE458BE0216D7D76EA0CD60406E4625AE7BBFB2020894010FDC81C0406FAE24D94A8ED3022E84F454DD4DC0407091C94C35C8CD021F4E4D67909B6040714ADA1EC604E7020934E1AD5155C04072073BE9D7C24002380BAD55143FA04072C877D44122360219C4964B2DEDC040738B6D24BC0CB3023624DCF65BCEE0407468DAE5A46FD102348E828B9D4040407539A19D9F821B022AA3BD78F283204076167CFC01CEE8021EAFD30F8D4F804076FEEB22272855022FD02B048E12004077F8D99DA024F4021FBFEDEFCF39E0407911F818FF1163024B9A05B43447E0407A44B81557DD0B020AC5B8BAED2980407B8E07EC978C0101FD737CB6050FB0407D0E31FBF77D3601C9D92AB5DDC9C0407EE3846D4850FB01B43118EE7BDFA040807F8E3216120901A47793B2ACECE04081B8804AECCFDC01C654E526CDF2404082F417B2B6626101E413F66F2E0BE040840D1DBA88D35701CEBE2AB6CD70C0408523C73B05C890021438342616F4C04086298D67225EC6020013D66E8E76C040871E9A2AA378710230A511292A23804087F9B09002581701D759C8D68904604088C7B205CAB0AB021E0FB3C15CA2804089965E2291CDE7021DA9F67BE6FF20408A698B9837CD60024A1C4F46724F80408B36CFF7F80044020D42C0D2B48740408BF982A4EA135402177F700F0C7260408CB56FF95BF061020DC70452029680408D7F1051A80FE2024B9180F3388240408E4C026194A08602254479374CCCE0408F11E4C8CC147E0233CFEF28534EA0408FE9FE2B2171910259E3427835FB0040905B657856A26A01FFD69C48900AE04090C529DBCEB142023ECCA96C147E40409131C144D49BCE01F9712FECEDF4E040919F70F107944E022F3F8EEA118040409217F42CBAA75902099DCD5C4478804092925B872D66D202148613EE120C60409321859F3242A901CDABBE98092FD04093B3D8892B772B01C170077C3F2280409447C6AFCE86FE01B05B17344BD5E04094E93148DE8CB301DE50DA37D36D0040959763034D4D0E01C5164F700D8CA040965B0C13AC387B01FD2C401BCDB7E04097247B8B31A85E01A2730BD05949004097FDF4B706DFC001E33E60D12A90D04098F3FDDF43582D01BA699075EEE5D0409A0E41FFBE591C01CABF57DA2AF080409B90AD8877191901BC28A982C0B7C0409E41771B832D090117EFFC3F286460 MPa
Output of a C0 or C0 Pro Reference core
For each floating-point variable that you print in the stdout or stderr of your application, the Signaloid Cloud Compute Engine also prints a ValueID field which is a reference to the distributional data.
You can feed this ValueID in other Signaloid Cloud Compute Engine endpoints, e.g., for sampling or plotting the associated distributional information.
For example, the file containing the output of the Stdout stream should contain text similar to the following:
Alloy strength (σc) = 4.5E+02<ValueID>val_80e5b9ed7a2a530eb1d15bc32ef5b337</ValueID> MPa