mirror of https://github.com/dapr/docs.git
update quickstart, start updating patterns
Signed-off-by: Hannah Hunter <hannahhunter@microsoft.com>
This commit is contained in:
parent
0f50934b63
commit
c5ee2810a3
|
@ -164,7 +164,49 @@ public class ChainWorkflow extends Workflow {
|
|||
<!--go-->
|
||||
|
||||
```go
|
||||
|
||||
func TaskChainWorkflow(ctx *workflow.WorkflowContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
var result1 int
|
||||
if err := ctx.CallActivity(Step1, workflow.ActivityInput(input)).Await(&result1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result2 int
|
||||
if err := ctx.CallActivity(Step1, workflow.ActivityInput(input)).Await(&result2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result3 int
|
||||
if err := ctx.CallActivity(Step1, workflow.ActivityInput(input)).Await(&result3); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []int{result1, result2, result3}, nil
|
||||
}
|
||||
func Step1(ctx workflow.ActivityContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Printf("Step 1: Received input: %s", input)
|
||||
return input + 1, nil
|
||||
}
|
||||
func Step2(ctx workflow.ActivityContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Printf("Step 2: Received input: %s", input)
|
||||
return input * 2, nil
|
||||
}
|
||||
func Step3(ctx workflow.ActivityContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Printf("Step 3: Received input: %s", input)
|
||||
return int(math.Pow(float64(input), 2)), nil
|
||||
}
|
||||
```
|
||||
|
||||
{{% /codetab %}}
|
||||
|
|
|
@ -20,6 +20,7 @@ In this guide, you'll:
|
|||
|
||||
<img src="/images/workflow-quickstart-overview.png" width=800 style="padding-bottom:15px;">
|
||||
|
||||
Select your preferred language-specific Dapr SDK before proceeding with the Quickstart.
|
||||
|
||||
{{< tabs "Python" ".NET" "Java" "Go" >}}
|
||||
|
||||
|
@ -68,14 +69,12 @@ pip3 install -r requirements.txt
|
|||
|
||||
### Step 3: Run the order processor app
|
||||
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar:
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar using [Multi-App Run]({{< ref multi-app-dapr-run >}}):
|
||||
|
||||
```bash
|
||||
dapr run --app-id order-processor --resources-path ../../../components/ -- python3 app.py
|
||||
dapr run -f .
|
||||
```
|
||||
|
||||
> **Note:** Since Python3.exe is not defined in Windows, you may need to use `python app.py` instead of `python3 app.py`.
|
||||
|
||||
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
|
||||
|
||||
Expected output:
|
||||
|
@ -303,10 +302,10 @@ cd workflows/csharp/sdk/order-processor
|
|||
|
||||
### Step 3: Run the order processor app
|
||||
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar:
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar using [Multi-App Run]({{< ref multi-app-dapr-run >}}):
|
||||
|
||||
```bash
|
||||
dapr run --app-id order-processor dotnet run
|
||||
dapr run -f .
|
||||
```
|
||||
|
||||
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
|
||||
|
@ -559,10 +558,10 @@ mvn clean install
|
|||
|
||||
### Step 3: Run the order processor app
|
||||
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar:
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar using [Multi-App Run]({{< ref multi-app-dapr-run >}}):
|
||||
|
||||
```bash
|
||||
dapr run --app-id WorkflowConsoleApp --resources-path ../../../components/ --dapr-grpc-port 50001 -- java -jar target/OrderProcessingService-0.0.1-SNAPSHOT.jar io.dapr.quickstarts.workflows.WorkflowConsoleApp
|
||||
dapr run -f .
|
||||
```
|
||||
|
||||
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
|
||||
|
@ -856,7 +855,7 @@ The `Activities` directory holds the four workflow activities used by the workfl
|
|||
{{% codetab %}}
|
||||
|
||||
|
||||
The `order-processor` console app starts and manages the `OrderProcessingWorkflow`, which simulates purchasing items from a store. The workflow consists of five unique workflow activities, or tasks:
|
||||
The `order-processor` console app starts and manages the `OrderProcessingWorkflow` workflow, which simulates purchasing items from a store. The workflow consists of five unique workflow activities, or tasks:
|
||||
|
||||
- `NotifyActivity`: Utilizes a logger to print out messages throughout the workflow. These messages notify you when:
|
||||
- You have insufficient inventory
|
||||
|
@ -890,15 +889,9 @@ In a new terminal window, navigate to the `order-processor` directory:
|
|||
cd workflows/go/sdk/order-processor
|
||||
```
|
||||
|
||||
Install the Dapr Go SDK dependencies:
|
||||
|
||||
```bash
|
||||
go build .
|
||||
```
|
||||
|
||||
### Step 3: Run the order processor app
|
||||
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar:
|
||||
In the terminal, start the order processor app alongside a Dapr sidecar using [Multi-App Run]({{< ref multi-app-dapr-run >}}):
|
||||
|
||||
```bash
|
||||
dapr run -f .
|
||||
|
@ -1097,177 +1090,8 @@ func restockInventory(daprClient client.Client, inventory []InventoryItem) error
|
|||
}
|
||||
```
|
||||
|
||||
#### `order-processor/workflow.go`
|
||||
Meanwhile, the `OrderProcessingWorkflow` and its activities are defined as methods in [`workflow.go`](https://github.com/dapr/quickstarts/workflows/go/sdk/order-processor/workflow.go)
|
||||
|
||||
In `main.go`, the workflow is defined as a method with all of its associated tasks (determined by workflow activities).
|
||||
|
||||
```go
|
||||
// OrderProcessingWorkflow is the main workflow for orchestrating activities in the order process.
|
||||
func OrderProcessingWorkflow(ctx *workflow.WorkflowContext) (any, error) {
|
||||
orderID := ctx.InstanceID()
|
||||
var orderPayload OrderPayload
|
||||
if err := ctx.GetInput(&orderPayload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Received order %s for %d %s - $%d", orderID, orderPayload.Quantity, orderPayload.ItemName, orderPayload.TotalCost)})).Await(nil); err != nil {
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
|
||||
var verifyInventoryResult InventoryResult
|
||||
if err := ctx.CallActivity(VerifyInventoryActivity, workflow.ActivityInput(InventoryRequest{
|
||||
RequestID: orderID,
|
||||
ItemName: orderPayload.ItemName,
|
||||
Quantity: orderPayload.Quantity,
|
||||
})).Await(&verifyInventoryResult); err != nil {
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
|
||||
if !verifyInventoryResult.Success {
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Insufficient inventory for %s", orderPayload.ItemName)})).Await(nil); err != nil {
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
}
|
||||
|
||||
if orderPayload.TotalCost > 50000 {
|
||||
var approvalRequired ApprovalRequired
|
||||
if err := ctx.CallActivity(RequestApprovalActivity, workflow.ActivityInput(orderPayload)).Await(&approvalRequired); err != nil {
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
if err := ctx.WaitForExternalEvent("manager_approval", time.Second*200).Await(nil); err != nil {
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
// TODO: Confirm timeout flow - this will be in the form of an error.
|
||||
if approvalRequired.Approval {
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Payment for order %s has been approved!", orderID)})).Await(nil); err != nil {
|
||||
log.Printf("failed to notify of a successful order: %v\n", err)
|
||||
}
|
||||
} else {
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Payment for order %s has been rejected!", orderID)})).Await(nil); err != nil {
|
||||
log.Printf("failed to notify of an unsuccessful order :%v\n", err)
|
||||
}
|
||||
return OrderResult{Processed: false}, nil
|
||||
}
|
||||
}
|
||||
if err := ctx.CallActivity(ProcessPaymentActivity, workflow.ActivityInput(PaymentRequest{
|
||||
RequestID: orderID,
|
||||
ItemBeingPurchased: orderPayload.ItemName,
|
||||
Amount: orderPayload.TotalCost,
|
||||
Quantity: orderPayload.Quantity,
|
||||
})).Await(nil); err != nil {
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Order %s failed!", orderID)})).Await(nil); err != nil {
|
||||
log.Printf("failed to notify of a failed order: %v", err)
|
||||
}
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
if err := ctx.CallActivity(UpdateInventoryActivity, workflow.ActivityInput(PaymentRequest{RequestID: orderID, ItemBeingPurchased: orderPayload.ItemName, Amount: orderPayload.TotalCost, Quantity: orderPayload.Quantity})).Await(nil); err != nil {
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Order %s failed!", orderID)})).Await(nil); err != nil {
|
||||
log.Printf("failed to notify of a failed order: %v", err)
|
||||
}
|
||||
return OrderResult{Processed: false}, err
|
||||
}
|
||||
|
||||
if err := ctx.CallActivity(NotifyActivity, workflow.ActivityInput(Notification{Message: fmt.Sprintf("Order %s has completed!", orderID)})).Await(nil); err != nil {
|
||||
log.Printf("failed to notify of a successful order: %v", err)
|
||||
}
|
||||
return OrderResult{Processed: true}, nil
|
||||
}
|
||||
|
||||
// NotifyActivity outputs a notification message
|
||||
func NotifyActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input Notification
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Printf("NotifyActivity: %s\n", input.Message)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ProcessPaymentActivity is used to process a payment
|
||||
func ProcessPaymentActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input PaymentRequest
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Printf("ProcessPaymentActivity: %s for %d - %s (%dUSD)\n", input.RequestID, input.Quantity, input.ItemBeingPurchased, input.Amount)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// VerifyInventoryActivity is used to verify if an item is available in the inventory
|
||||
func VerifyInventoryActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input InventoryRequest
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("VerifyInventoryActivity: Verifying inventory for order %s of %d %s\n", input.RequestID, input.Quantity, input.ItemName)
|
||||
dClient, err := client.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item, err := dClient.GetState(context.Background(), stateStoreName, input.ItemName, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if item == nil {
|
||||
return InventoryResult{
|
||||
Success: false,
|
||||
InventoryItem: InventoryItem{},
|
||||
}, nil
|
||||
}
|
||||
var result InventoryItem
|
||||
if err := json.Unmarshal(item.Value, &result); err != nil {
|
||||
log.Fatalf("failed to parse inventory result %v", err)
|
||||
}
|
||||
fmt.Printf("VerifyInventoryActivity: There are %d %s available for purchase\n", result.Quantity, result.ItemName)
|
||||
if result.Quantity >= input.Quantity {
|
||||
return InventoryResult{Success: true, InventoryItem: result}, nil
|
||||
}
|
||||
return InventoryResult{Success: false, InventoryItem: InventoryItem{}}, nil
|
||||
}
|
||||
|
||||
// UpdateInventoryActivity modifies the inventory.
|
||||
func UpdateInventoryActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input PaymentRequest
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("UpdateInventoryActivity: Checking Inventory for order %s for %d * %s\n", input.RequestID, input.Quantity, input.ItemBeingPurchased)
|
||||
dClient, err := client.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item, err := dClient.GetState(context.Background(), stateStoreName, input.ItemBeingPurchased, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result InventoryItem
|
||||
err = json.Unmarshal(item.Value, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newQuantity := result.Quantity - input.Quantity
|
||||
if newQuantity < 0 {
|
||||
return nil, fmt.Errorf("insufficient inventory for: %s", input.ItemBeingPurchased)
|
||||
}
|
||||
result.Quantity = newQuantity
|
||||
newState, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal new state: %v", err)
|
||||
}
|
||||
dClient.SaveState(context.Background(), stateStoreName, input.ItemBeingPurchased, newState, nil)
|
||||
fmt.Printf("UpdateInventoryActivity: There are now %d %s left in stock\n", result.Quantity, result.ItemName)
|
||||
return InventoryResult{Success: true, InventoryItem: result}, nil
|
||||
}
|
||||
|
||||
// RequestApprovalActivity requests approval for the order
|
||||
func RequestApprovalActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input OrderPayload
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("RequestApprovalActivity: Requesting approval for payment of %dUSD for %d %s\n", input.TotalCost, input.Quantity, input.ItemName)
|
||||
return ApprovalRequired{Approval: true}, nil
|
||||
}
|
||||
```
|
||||
{{% /codetab %}}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue