During this exercise, you will:
- Define and handle a Query
- Create a handle on a Workflow to be queried
- Call the Query from the Client
- Send a Query from the Command line
Make your changes to the code in the practice
subdirectory (look for
TODO
comments that will guide you to where you should make changes to
the code). If you need a hint or want to verify your changes, look at
the complete version in the solution
subdirectory.
In this part of the exercise, you will define your Query.
- Edit the
workflow.go
file. You will use theworkflow.SetQueryHandler()
to add Query handling to your Workflow. This can be done anywhere inside of theWorkflow()
function. In this case, you'll add a query to return the Workflow'scurrentState
, so it makes sense to initialize thecurrentState
variable as you go along. Note that this is the same Workflow from the previous exercise, so it is designed to wait for a Signal after starting. - Set up two string variables,
currentState := "started"
andqueryType := "current_state"
. One of these will contain the type of your Query, which will not change. The other will contain thecurrentState
that is progressively updated and will be returned by the Query. - Next, add the
workflow.SetQueryHandler()
function with the necessary error handling:
err := workflow.SetQueryHandler(ctx, queryType, func() (string, error) {
return currentState, nil
})
if err != nil {
currentState = "failed to register query handler"
return "", err
}
- Finally, update
currentState
again after that block of code, to something like "waiting for signal". This is the state that the Workflow will be waiting at when we query it. - Save the file.
In this part of the exercise, you will create another Temporal client that sends a Query. queryclient/main.go
currently contains a near-empty Temporal client -- it looks like a Starter or a Worker, but it does not register any Workflows or do anything. You will use this client to send a Query.
- Edit the
queryclient/main.go
file. You will useclient.QueryWorkflow(context, "workflow-id", "run-id", "query-type")
to send a Query. - Within the
main()
block, add theclient.QueryWorkflow()
function with the necessary parameters and error handling:
response, err := c.QueryWorkflow(context.Background(), "queries", "", "current_state")
if err != nil {
log.Fatalln("Error sending the Query", err)
return
}
- Immediately after that, add some logging for getting the Query result and logging it to your terminal:
var result string
response.Get(&result)
log.Println("Received Query result. Result: " + result)
- Save the file.
At this point, you can run your Workflow. Because it is the same Workflow from the last exercise with added Query support, it will wait to receive a Signal after starting.
- In one terminal, navigate to the
worker
subdirectory and rungo run main.go
. - In another terminal, navigate to the
starter
subdirectory and rungo run main.go
. You should receive some logging from your Worker along these lines:
2024/03/14 08:48:10 INFO No logger configured for temporal client. Created default one.
2024/03/14 08:48:10 INFO Started Worker Namespace default TaskQueue queries WorkerID 43388@Omelas@
2024/03/14 08:48:21 INFO Query workflow started Namespace default TaskQueue queries WorkerID 43388@Omelas@ WorkflowType Workflow WorkflowID queries RunID 905330da-9c0f-490e-bd48-c6a9e8840f7a Attempt 1 input Plain text input
- You can now Query your Workflow. In a third terminal, run
go run queryclient/main.go
. It will send a Query to your Workflow, which will immediately return the Query result:
2024/03/14 10:32:09 Received Query result. Result: waiting for signal
You have now demonstrated sending a Query to a Workflow from a Temporal Client. Before moving on, you can send one from the CLI as well.
To send a Query from the CLI, use temporal workflow query
with the same parameters as your client:
temporal workflow query \
--workflow-id="queries" \
--type="current_state"
It will produce the same result:
Query result:
["waiting for signal"]
Now you can send a Signal to your Workflow as in the previous exercise so it completes successfully. In the terminal you sent your Query from, run go run signalclient/main.go
.
Finally, you can demonstrate querying completed Workflows. Update the currentState
variable in workflow.go
once more just before the Workflow returns, so that you can demonstrate querying a completed workflow. Then, re-run the workflow, and query it from the command line again:
temporal workflow query \
--workflow-id="queries" \
--type="current_state"
Query result:
["workflow completed"]
You need to have a running Worker to query completed Workflows.