In the Temporal Go SDK programming model, a Workflow is an exportable function.
The first parameter,
workflow.Context is a requirement for all Workflow functions as it is used by the Temporal Go SDK to pass around an execution context, and virtually all the Go SDK APIs that are callable from the Workflow require it.
workflow.Context entity operates similarly to the standard
context.Context entity provided by Go.
The only difference is that the
Done() function provided by
workflow.Channel instead of the standard Go
The second parameter,
string, is a custom parameter that can be used to pass data into the Workflow when it starts.
A Workflow can have one or more such parameters.
All Workflow function parameters must be serializable, which essentially means that params can’t be channels, functions, variadic, or unsafe pointers.
Returning an error from a Workflow is used to indicate that an error was encountered during its execution and the Workflow should be terminated.
There is a single requirement for how the code inside a Workflow is written. Workflow code must be "deterministic". This requirement stems from how the Temporal Server tracks the state of code execution and its need to be able to replay an execution.
In practical terms, this means the following:
- Workflow code can only read and manipulate local variables or variables received as return values from Temporal Go SDK APIs.
- Workflow code can not affect changes in external systems directly.
- Workflow code must use Go SDK APIs to handle things like time, logging, and goroutines.
- Workflow code can not directly iterate over maps using
rangebecause the order of the map's iteration is randomized.
However, the Go SDK provides a number of features to handle these restrictions with ease.
- To interact with external systems and nondeterministic code, Workflows can execute Activities.
- To handle things like time, logging, and goroutines, as mentioned above, there are specific Go SDK APIs available, such as:
workflow.Now()This is a replacement for
workflow.Sleep()This is a replacement for
workflow.GetLogger()This is to ensure that the provided logger does not duplicate logs during a replay.
workflow.Go()This is a replacement for the the
workflow.ChannelThis is a replacement for the native
chantype. Temporal provides support for both buffered and unbuffered channels.
workflow.SelectorThis is a replacement for the
selectstatement. Learn more on the Go SDK Selectors page
workflow.ContextThis is a replacement for
context.Context. Learn more on the Go SDK Context Propagation page.
- Additionally, for executing very small pieces of nondeterministic logic within the Workflow, you can use the
Below is a sample Workflow that is treated as a cron job by the Temporal Server.
It executes a single Activity and uses
With the Go SDK, there are two ways that you can start a Workflow:
- Use the Go SDK
clientto start a Workflow from a Go process, as described below.
- Start a Workflow from an already running Workflow, which is known as a Child Workflow.
Starting a Workflow is not the same as executing a Workflow. Starting a Workflow means that you are telling the Server to begin tracking the state of the Workflow execution. In a Temporal application, you do not run Workflow code directly, instead Workflow code is hosted and executed by a Worker.
To start a Workflow you need to create the Temporal Go SDK client, call
ExecuteWorkflow(), and pass it the following:
context.Context, which is a normal Go
client.StartWorkflowOptionsWhich can include timeout settings and a
- The name of the Workflow function.
- Variables that should be passed to the Workflow when it begins execution.
You can start Workflows asynchronously or synchronously. In Go, the only difference is whether the code waits for the result of the Workflow in the same process in which you started it. Workflows do not rely on the process that invoked it, and will continue executing even if the waiting process crashes or stops.
When you start a Workflow with
WorkflowExecution is returned (which is the
we variable above).
WorkflowExecution can be used to get the result or capture the WorkflowId.
You can retrieve the result of the Workflow from a completely different process, as long as you have the WorkflowId, by using
In most uses cases it is better to be prepared to execute the Workflow asynchronously.
Signals are the mechanism by which you can get data into already running Workflow.
Queries are the mechanism by which you can get data out of currently running Workflow.
Workflow method arguments and return values are serializable to a Payload protobuf that contains a bytearray as well as metadata map. You can use the SDK's DataConverter interface to do this. The default implementation uses JSON serializer, but you can use any alternative serialization mechanism.
The values passed to Workflows through invocation parameters or returned through a result value are recorded in the execution history.
Even though Workflow execution history is cached in the Workers, in the case of Worker failure, the full execution history has to be transferred from the Temporal service to the Workflow Workers.
In those cases a large execution history could adversely impact the performance of your Workflow. Be mindful of the amount of data that you transfer via Activity invocation parameters or return values. Otherwise, no additional limitations exist on Activity implementations.
We discuss how to work around the history size limitations with
ContinueAsNew in the Large Event Histories section.
Temporal stores the execution history of all Workflows. There is a maximum limit of this execution history (50,000 events). Even though Temporal Server emits warnings while your workflow are approaching this limit (every 10,000 events), you should make sure your workflows don't reach it.
Workflows that periodically execute a number of Activities, for a long time, have the potential of running into this execution history size limit.
One way of dealing with this issue is to use
ContinueAsNew. This feature allows you
to complete the current Workflow execution and start a new one atomically.
This new execution has the same Workflow Id, but a different Run Id, and as such will
get its own execution history.
If your Workflows are running periodically using a Cron definition, the
feature is used internally by Temporal.
In this case, each Workflow execution as defined by the Cron definition will have its own Run Id and execution history.
To trigger this behavior, the Workflow function should terminate by returning the special ContinueAsNewError error: