-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Grant-onboarding #12
base: main
Are you sure you want to change the base?
Grant-onboarding #12
Changes from all commits
b4631af
89786cc
7aaf36f
88a9e2e
3362a33
07a92b4
ceebd1f
76df167
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,10 @@ the complete version in the `solution` subdirectory. | |
|
||
In this part of the exercise, you will define your Query. | ||
|
||
1. Edit the `workflow.go` file. You will use the `workflow.SetQueryHandler()` to add Query handling to your Workflow. This can be done anywhere inside of the `Workflow()` function. In this case, you'll add a query to return the Workflow's `currentState`, so it makes sense to initialize the `currentState` 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. | ||
1. Edit the `workflow.go` file. | ||
|
||
You will use the `workflow.SetQueryHandler()` to add Query handling to your Workflow. This can be done anywhere inside of the `Workflow()` function. In this case, you'll add a query to return the Workflow's `currentState`, which you'll modify as the Workflow progresses. Note that this is the same Workflow from the previous exercise, so it is designed to wait for a Signal after starting. | ||
|
||
2. Set up two string variables, `currentState := "started"` and `queryType := "current_state"`. One of these will contain the type of your Query, which will not change. The other will contain the `currentState` that is progressively updated and will be returned by the Query. | ||
3. Next, add the `workflow.SetQueryHandler()` function with the necessary error handling: | ||
|
||
|
@@ -30,8 +33,10 @@ if err != nil { | |
} | ||
``` | ||
|
||
4. 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. | ||
5. Save the file. | ||
4. 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. | ||
5. Finally, update `currentState` to something like `"Workflow Complete"` | ||
after the Activity has completed successfully near where the Workflow completion is logged. | ||
6. Save the file. | ||
Comment on lines
-33
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this note to change to add a statement for workflow complete. It used to be in part E, but I just moved it here. I think it's easier to have it here because I think if it's in E, the user needs to restart workers etc |
||
|
||
## Part B: Performing a Query from a Client | ||
|
||
|
@@ -41,7 +46,7 @@ In this part of the exercise, you will create another Temporal client that sends | |
2. Within the `main()` block, add the `client.QueryWorkflow()` function with the necessary parameters and error handling: | ||
|
||
```go | ||
response, err := c.QueryWorkflow(context.Background(), "queries", "", "current_state") | ||
response, err := c.QueryWorkflow(context.Background(), "queries-workflow-id", "", "current_state") | ||
Comment on lines
-44
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not necessary, but it had the workflow id and the task queue both as "queries", so I just changed them to disambiguate |
||
if err != nil { | ||
log.Fatalln("Error sending the Query", err) | ||
return | ||
|
@@ -67,8 +72,8 @@ At this point, you can run your Workflow. Because it is the same Workflow from t | |
|
||
``` | ||
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 | ||
2024/03/14 08:48:10 INFO Started Worker Namespace default TaskQueue queries-task-queue WorkerID 43388@Omelas@ | ||
2024/03/14 08:48:21 INFO Query workflow started Namespace default TaskQueue queries-task-queue WorkerID 43388@Omelas@ WorkflowType Workflow WorkflowID queries-workflow-id RunID 905330da-9c0f-490e-bd48-c6a9e8840f7a Attempt 1 input Plain text input | ||
``` | ||
|
||
1. 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: | ||
|
@@ -85,7 +90,7 @@ To send a Query from the CLI, use `temporal workflow query` with the same parame | |
|
||
```bash | ||
temporal workflow query \ | ||
--workflow-id="queries" \ | ||
--workflow-id="queries-workflow-id" \ | ||
--type="current_state" | ||
``` | ||
|
||
|
@@ -96,15 +101,20 @@ 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`. | ||
Now you can send a Signal to your Workflow as in the previous exercise so it completes successfully. | ||
|
||
1. In the terminal you sent your Query from, run `go run signalclient/main.go`. | ||
Comment on lines
-99
to
+106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. separating prose from instructions. up to you 👍 |
||
|
||
## Part E: Querying a Completed Workflow | ||
|
||
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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved to part A |
||
Now that the Workflow has been signalled, it has completed, and you | ||
can demonstrate querying completed Workflows. | ||
|
||
1. Query it from the command line again: | ||
|
||
```bash | ||
temporal workflow query \ | ||
--workflow-id="queries" \ | ||
--workflow-id="queries-workflow-id" \ | ||
--type="current_state" | ||
``` | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ import ( | |
"context" | ||
"log" | ||
|
||
queries "interacting/exercises/querying-workflows/solution" | ||
queries "interacting/exercises/querying-workflows/practice" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. significant change -- the practice code was importing from the solution, so the user's code would be working even if they didn't solve the problem yet. Lol I had this happen to me and i was pretty confused |
||
|
||
"go.temporal.io/sdk/client" | ||
) | ||
|
@@ -20,7 +20,7 @@ func main() { | |
Fulfilled: true, | ||
} | ||
|
||
err = c.SignalWorkflow(context.Background(), "queries", "", "fulfill-order-signal", signal) | ||
err = c.SignalWorkflow(context.Background(), "queries-workflow-id", "", "fulfill-order-signal", signal) | ||
if err != nil { | ||
log.Fatalln("Error sending the Signal", err) | ||
return | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,53 +14,66 @@ the complete version in the `solution` subdirectory. | |
|
||
## Part A: Defining a Signal | ||
|
||
1. This exercise contains one Client that runs two different Workflows | ||
— `PizzaWorkflow` and `FulfillOrderWorkflow`. Both Workflows are defined in | ||
`workflow.go`. `PizzaWorkflow` is designed not to complete its final activity | ||
— `SendBill` — until it receives a Signal from `FulfillOrderWorkflow`. You'll | ||
start by defining that Signal. Edit `workflow.go`. Near the top of the file, | ||
This exercise contains one Client that runs two different Workflows | ||
— `PizzaWorkflow` and `FulfillOrderWorkflow`. Both Workflows are defined in | ||
`workflow.go`. `PizzaWorkflow` is designed not to complete its final activity | ||
— `SendBill` — until it receives a Signal from `FulfillOrderWorkflow`. You'll | ||
start by defining that Signal. | ||
|
||
1. Edit `workflow.go`. Near the top of the file, | ||
Comment on lines
-17
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prose from instruction |
||
after the `import()` block and before your Workflow definitions, create a | ||
type of `struct{}` named `FulfillOrderSignal` that contains a single `bool` | ||
named `Fulfilled`. | ||
2. Next, directly below that, create a `var` named `signal` that is an instance | ||
of `FulfillOrderSignal` with `Fulfilled: true`. This is the Signal that | ||
`FulfillOrderWorkflow` will send to `PizzaWorkflow`. | ||
3. Save the file. | ||
2. Save the file. | ||
|
||
## Part B: Handling the Signal | ||
|
||
1. Next, you need to enable your `PizzaWorkflow` to receive a Signal from | ||
`FulfillOrderWorkflow`. After `var confirmation OrderConfirmation`, define a | ||
Signal Channel, and use `signalChan.Receive()` to block the Workflow until it | ||
receives a Signal, after which it can proceed with the logic contained in `if | ||
signal.Fulfilled == true{}`. Begin by adding a call to | ||
`workflow.GetSignalChannel(ctx, "fulfill-order-signal")` and assign it to | ||
a variable like `signalChan`. | ||
2. After that, add `signalChan.Receive(ctx, &signal)` on the following line. | ||
3. Save the file. | ||
Next, you need to enable your `PizzaWorkflow` to receive a Signal from | ||
`FulfillOrderWorkflow`. | ||
|
||
After `var confirmation OrderConfirmation`, define a | ||
Signal Channel, and use `signalChan.Receive()` to block the Workflow until it | ||
receives a Signal, after which it can proceed with the logic contained in | ||
`if receivedSignal.Fulfilled == true{}`. | ||
|
||
1. Create a `var` named `receivedSignal` that is an instance | ||
of `FulfillOrderSignal`. This is the Signal that | ||
`PizzaWorkflow` will receive from `FulfillOrderWorkflow`. | ||
2. Add `signalChan := workflow.GetSignalChannel(ctx, "fulfill-order-signal")`. | ||
3. On the following line, add `signalChan.Receive(ctx, &receivedSignal)`. | ||
4. Save the file. | ||
|
||
## Part C: Signaling your Workflow | ||
|
||
1. Near the bottom of `workflow.go`, within `FulfillOrderWorkflow`, you will | ||
notice that it runs two Activities — `MakePizzas` and `DeliverPizzas`. After | ||
those Activities complete successfuly, the next step should be to send a | ||
Signal to the `PizzaWorkflow` that it is time to bill the customer and | ||
complete the Workflow. To do this, you need call | ||
`workflow.SignalExternalWorkflow()`. | ||
2. Add this call to the end of `FulfillOrderWorkflow`. `SignalExternalWorkflow` | ||
needs, as arguments, the `ctx` Workflow context, Workflow ID (which should be | ||
Near the bottom of `workflow.go`, within `FulfillOrderWorkflow`, you will | ||
notice that it runs two Activities — `MakePizzas` and `DeliverPizzas`. After | ||
those Activities complete successfuly, the next step should be to send a | ||
Signal to the `PizzaWorkflow` that it is time to bill the customer and | ||
complete the Workflow. To do this, you need call | ||
`workflow.SignalExternalWorkflow()`. | ||
|
||
1. Create a `var` named `signalToSend` that is an instance | ||
of `FulfillOrderSignal` with `Fulfilled: true`. This is the Signal that | ||
`FulfillOrderWorkflow` will send to `PizzaWorkflow`. | ||
2. Add a call to `workflow.SignalExternalWorkflow()` at the end of `FulfillOrderWorkflow`. `SignalExternalWorkflow` | ||
needs the following as arguments: the `ctx` Workflow context, Workflow ID (which should be | ||
`pizza-workflow-order-Z1238`), an optional Run ID (which you can omit by | ||
providing "" as the next argument), and the name of the | ||
providing "" as the argument), and the name of the | ||
Signal,`fulfill-order-signal`. For `SignalExternalWorkflow` calls to block | ||
and return properly in Go, you also need to append `.Get(ctx, | ||
[return-value-pointer])` to a `SignalExternalWorkflow` call, though | ||
`[return-value-pointer]` can be `nil` here. | ||
@@@@@ the course content doesn't say anything about this `.Get`. @@@@ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, is this just about appending |
||
3. Save and close the file. | ||
|
||
## Part D: Making your Client start both Workflows | ||
|
||
1. Finally, open `start/main.go` for editing. Currently, this Client only starts | ||
the `PizzaWorkflow`. Directly after the `c.ExecuteWorkflow()` call for the | ||
1. Finally, open `start/main.go` for editing. | ||
|
||
Currently, this Client only starts | ||
the `PizzaWorkflow`. | ||
|
||
2. Directly after the `c.ExecuteWorkflow()` call for the | ||
`PizzaWorkflow`, add another call that starts the `FulfillOrderWorkflow`. You | ||
can use the call that starts the `PizzaWorkflow` and the | ||
`signalFulfilledOptions` block as a reference. Don't forget to capture the | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,9 +11,6 @@ import ( | |
// TODO Part A: Create a type of `struct{}` named `FulfillOrderSignal` | ||
// that contains a single `bool` named `Fulfilled`. | ||
|
||
// TODO Part A: create a `var` named `signal` that is an instance of | ||
// `FulfillOrderSignal` with `Fulfilled: true`. This is the Signal that | ||
// `FulfillOrderWorkflow` will send to `PizzaWorkflow`. | ||
Comment on lines
-14
to
-16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we were using the |
||
|
||
func PizzaWorkflow(ctx workflow.Context, order PizzaOrder) (OrderConfirmation, error) { | ||
retrypolicy := &temporal.RetryPolicy{ | ||
|
@@ -48,9 +45,9 @@ func PizzaWorkflow(ctx workflow.Context, order PizzaOrder) (OrderConfirmation, e | |
var confirmation OrderConfirmation | ||
// TODO Part B: Add a call to `workflow.GetSignalChannel(ctx, "fulfill-order-signal")` | ||
// and assign it to a variable like `signalChan`. After that, add | ||
// `signalChan.Receive(ctx, &signal)` on the following line. | ||
// `signalChan.Receive(ctx, &receivedSignal)` on the following line. | ||
|
||
if signal.Fulfilled == true { | ||
if receivedSignal.Fulfilled == true { | ||
bill := Bill{ | ||
CustomerID: order.Customer.CustomerID, | ||
OrderNumber: order.OrderNumber, | ||
|
@@ -94,6 +91,10 @@ func FulfillOrderWorkflow(ctx workflow.Context, order PizzaOrder) (string, error | |
return "orderUnfulfilled", nil | ||
} | ||
|
||
// TODO Part C: create a `var` named `signalToSend` that is an instance of | ||
// `FulfillOrderSignal` with `Fulfilled: true`. This is the Signal that | ||
// `FulfillOrderWorkflow` will send to `PizzaWorkflow`. | ||
|
||
// TODO Part C: call `workflow.SignalExternalWorkflow()` | ||
// to send a Signal to your `PizzaWorkflow`. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tom suggested to me one time to separate prose from instruction/commands. I tried to do that here -- totally up to you on whether or not to keep it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just adding a linebreak is a pretty reasonable way of doing that imo! I'd previously rejected suggestions along these lines that distorted the number of actual steps there were, but this works fine. Thanks!