Skip to main content

Managing state in steps

This section provides information on how to access state in steps and to store intermediate and final state. This state can be linked to step arguments and used as a step or task output.

Within a step context, using the State property, there is easy access to the state context.

info

In steps, it is recommended to use the TaskuraiStateContext instead of the TaskuraiStateClient. The state context is aware of the context of the step and cancellation tokens.

API reference:

Required scopes:

  • Data/Buildby.Taskurai/state/create
  • Data/Buildby.Taskurai/state/read
  • Data/Buildby.Taskurai/state/delete

Optional scopes:

  • Data/Buildby.Taskurai/sensitive/read: Can return sensitive data.

Prerequisites

You have completed:

Managing state in a step

In a previous section, Storing initial state, an initial large json file was uploaded to the default state store and a task was created that accepts a state reference as argument.

The following sample of a command would process the daily sales JSON file and aggregate the sales, upload to another system:

[Command]
[Version(1)]
public async Task<TaskCommandResult> UploadDailySalesSAPSteps(TaskuraiTaskContext context, CancellationToken cancellationToken, DateTimeOffset date, StateReference dailySales)
{
// Download dailySales and make aggregate
var aggregateDailySales = await context.RunInlineAsync(
id: "download-daily-sales-aggregate",
run: async (TaskuraiStepContext context, CancellationToken cancellationToken) =>
{
Logger.LogInformation($"Generating aggregate of daily sales, run count = {context.Step.RunCount}.");

// Download file
StateDownloadResponse stateDownloadResponse = await context.State.GetBlobStateContentAsync(dailySales);

await context.ProgressAsync(10, "Downloaded daily sales.");

// Aggregate file
await Task.Delay(5000);
await context.ProgressAsync(60, "Aggregated daily sales.");

// Write aggregated file
var aggregatedState = await context.State.SaveBlobStateAsync(
new StateInput(context.Task, "dailySalesAggregate")
{
HasBlob = true,
Ttl = 30 * 24 * 60 * 60, // one month
ContentType = "application/json"
},
stateDownloadResponse.BlobDownloadResult.Content,
overwrite: true
);

return context.Succeeded(
progress: new Progress()
{
Percentage = 100,
Message = "Successfully aggregated daily sales."
},
result: new ResultResponse()
{
Outputs = new List<ResultOutput>()
{
new ResultOutput()
{
Name = "dailySalesAggregate",
StateReference = aggregatedState.StateReference
}
}
}
);
},
runTimeout: 600
);

// Upload to SAP
var uploadSap = await context.RunInlineAsync(
id: "upload-daily-sales-sap",
init: (response, arguments) =>
{
arguments.Add(new StepArgument("dailySalesAggregate")
{
StateReference = aggregateDailySales.Outputs.GetStateReference("dailySalesAggregate")
});
},
run: async (TaskuraiStepContext context, CancellationToken cancellationToken, StateReference dailySalesAggregate) =>
{
// Simulate upload
await Task.Delay(5000);

return context.Succeeded();
},
runTimeout: 600
);

return Succeeded(
result: new ResultResponse()
{
Messages = [
new ResultMessage()
{
Code = "200",
Message = "Successfully aggregated daily sales and uploaded to SAP."
}
],
Outputs = [
new ResultOutput()
{
Name = "dailySalesAggregate",
StateReference = aggregateDailySales.Outputs.GetStateReference("dailySalesAggregate")
}
]
}
);
}