-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from temporalio/order-base
Simple Order and Shipment Workflows
- Loading branch information
Showing
11 changed files
with
360 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,3 @@ | ||
package activities | ||
|
||
import "go.temporal.io/sdk/client" | ||
|
||
type Activities struct { | ||
client client.Client | ||
} | ||
type Activities struct{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package activities | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/temporalio/orders-reference-app-go/pkg/ordersapi" | ||
) | ||
|
||
type ShipmentCreatedNotificationInput struct { | ||
OrderID ordersapi.OrderID | ||
} | ||
|
||
func (a *Activities) ShipmentCreatedNotification(ctx context.Context, input ShipmentCreatedNotificationInput) error { | ||
return nil | ||
} | ||
|
||
type ShipmentDispatchedNotificationInput struct { | ||
OrderID ordersapi.OrderID | ||
} | ||
|
||
func (a *Activities) ShipmentDispatchedNotification(ctx context.Context, input ShipmentDispatchedNotificationInput) error { | ||
return nil | ||
} | ||
|
||
type ShipmentDeliveredNotificationInput struct { | ||
OrderID ordersapi.OrderID | ||
} | ||
|
||
func (a *Activities) ShipmentDeliveredNotification(ctx context.Context, input ShipmentDeliveredNotificationInput) error { | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package activities | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/temporalio/orders-reference-app-go/pkg/ordersapi" | ||
) | ||
|
||
type RegisterShipmentInput struct { | ||
OrderID ordersapi.OrderID | ||
Items []ordersapi.Item | ||
} | ||
|
||
type RegisterShipmentResult struct{} | ||
|
||
func (a *Activities) RegisterShipment(ctx context.Context, input RegisterShipmentInput) (RegisterShipmentResult, error) { | ||
return RegisterShipmentResult{}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# System Overview | ||
|
||
```mermaid | ||
sequenceDiagram | ||
participant Customer | ||
participant Order | ||
participant Shipment | ||
participant Courier | ||
Customer->>Order: place order | ||
Order->>Shipment: create shipment | ||
Shipment->>Courier: register shipment | ||
Courier->>Shipment: shipment registered | ||
Shipment->>Customer: shipment created | ||
Courier->>Shipment: shipment dispatched | ||
Shipment->>Customer: shipment dispatched | ||
Courier->>Shipment: shipment delivered | ||
Shipment->>Customer: shipment delivered | ||
Order->>Customer: order complete | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package shipmentapi | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/temporalio/orders-reference-app-go/pkg/ordersapi" | ||
) | ||
|
||
// The Shipment interfaces are only used internally. | ||
|
||
// Signals will be sent by couriers via a local API service, | ||
// so we don't need to expose these. | ||
|
||
func ShipmentWorkflowID(orderID ordersapi.OrderID) string { | ||
return fmt.Sprintf("shipment:%s", orderID) | ||
} | ||
|
||
type ShipmentInput struct { | ||
OrderID ordersapi.OrderID | ||
Items []ordersapi.Item | ||
} | ||
|
||
const ShipmentUpdateSignalName = "ShipmentUpdate" | ||
|
||
type ShipmentStatus int | ||
|
||
const ( | ||
ShipmentStatusRegistered ShipmentStatus = iota | ||
ShipmentStatusDispatched | ||
ShipmentStatusDelivered | ||
) | ||
|
||
type ShipmentUpdateSignal struct { | ||
Status ShipmentStatus | ||
} | ||
|
||
type ShipmentResult struct{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package ordersapi | ||
|
||
// The Orders API is exposed as the JSON equivalents will be used to start Orders via the local API. | ||
|
||
// TODO: Do we want to do pass-through like this or separate and translate API definitions to Workflow types? | ||
// TODO: Protobufs? | ||
|
||
type OrderID string | ||
|
||
type Item struct { | ||
SKU string | ||
Quantity int32 | ||
} | ||
|
||
type OrderInput struct { | ||
ID OrderID | ||
Items []Item | ||
} | ||
|
||
type OrderResult struct{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package workflows | ||
|
||
import ( | ||
"github.com/temporalio/orders-reference-app-go/internal/shipmentapi" | ||
"github.com/temporalio/orders-reference-app-go/pkg/ordersapi" | ||
"go.temporal.io/sdk/workflow" | ||
) | ||
|
||
func Order(ctx workflow.Context, order ordersapi.OrderInput) (ordersapi.OrderResult, error) { | ||
var result ordersapi.OrderResult | ||
|
||
ctx = workflow.WithChildOptions(ctx, | ||
workflow.ChildWorkflowOptions{ | ||
WorkflowID: shipmentapi.ShipmentWorkflowID(order.ID), | ||
}, | ||
) | ||
|
||
err := workflow.ExecuteChildWorkflow(ctx, | ||
Shipment, | ||
shipmentapi.ShipmentInput{ | ||
OrderID: order.ID, | ||
Items: order.Items, | ||
}, | ||
).Get(ctx, nil) | ||
if err != nil { | ||
return result, err | ||
} | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package workflows_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
"github.com/temporalio/orders-reference-app-go/internal/shipmentapi" | ||
"github.com/temporalio/orders-reference-app-go/pkg/ordersapi" | ||
"github.com/temporalio/orders-reference-app-go/workflows" | ||
"go.temporal.io/sdk/testsuite" | ||
"go.temporal.io/sdk/workflow" | ||
) | ||
|
||
func TestOrderWorkflow(t *testing.T) { | ||
s := testsuite.WorkflowTestSuite{} | ||
env := s.NewTestWorkflowEnvironment() | ||
|
||
env.RegisterWorkflow(workflows.Order) | ||
|
||
orderInput := ordersapi.OrderInput{ | ||
Items: []ordersapi.Item{ | ||
{SKU: "test1", Quantity: 1}, | ||
{SKU: "test2", Quantity: 3}, | ||
}, | ||
} | ||
|
||
env.OnWorkflow(workflows.Shipment, mock.Anything, mock.Anything).Return(func(ctx workflow.Context, input shipmentapi.ShipmentInput) (shipmentapi.ShipmentResult, error) { | ||
return shipmentapi.ShipmentResult{}, nil | ||
}) | ||
|
||
env.ExecuteWorkflow( | ||
workflows.Order, | ||
orderInput, | ||
) | ||
|
||
var result ordersapi.OrderResult | ||
err := env.GetWorkflowResult(&result) | ||
assert.NoError(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package workflows | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/temporalio/orders-reference-app-go/activities" | ||
"github.com/temporalio/orders-reference-app-go/internal/shipmentapi" | ||
"go.temporal.io/sdk/workflow" | ||
) | ||
|
||
type shipment struct { | ||
status shipmentapi.ShipmentStatus | ||
} | ||
|
||
func Shipment(ctx workflow.Context, input shipmentapi.ShipmentInput) (shipmentapi.ShipmentResult, error) { | ||
return new(shipment).run(ctx, input) | ||
} | ||
|
||
func (s *shipment) run(ctx workflow.Context, input shipmentapi.ShipmentInput) (shipmentapi.ShipmentResult, error) { | ||
workflow.Go(ctx, s.statusUpdater) | ||
|
||
var result shipmentapi.ShipmentResult | ||
|
||
ctx = workflow.WithActivityOptions(ctx, | ||
workflow.ActivityOptions{ | ||
StartToCloseTimeout: 5 * time.Second, | ||
}, | ||
) | ||
|
||
err := workflow.ExecuteActivity(ctx, | ||
a.RegisterShipment, | ||
activities.RegisterShipmentInput{ | ||
OrderID: input.OrderID, | ||
Items: input.Items, | ||
}, | ||
).Get(ctx, nil) | ||
if err != nil { | ||
return result, err | ||
} | ||
|
||
err = workflow.ExecuteActivity(ctx, | ||
a.ShipmentCreatedNotification, | ||
activities.ShipmentCreatedNotificationInput{ | ||
OrderID: input.OrderID, | ||
}, | ||
).Get(ctx, nil) | ||
if err != nil { | ||
return result, err | ||
} | ||
|
||
s.waitForStatus(ctx, shipmentapi.ShipmentStatusDispatched) | ||
|
||
err = workflow.ExecuteActivity(ctx, | ||
a.ShipmentDispatchedNotification, | ||
activities.ShipmentDispatchedNotificationInput{ | ||
OrderID: input.OrderID, | ||
}, | ||
).Get(ctx, nil) | ||
if err != nil { | ||
return result, err | ||
} | ||
|
||
s.waitForStatus(ctx, shipmentapi.ShipmentStatusDelivered) | ||
|
||
err = workflow.ExecuteActivity(ctx, | ||
a.ShipmentDeliveredNotification, | ||
activities.ShipmentDeliveredNotificationInput{ | ||
OrderID: input.OrderID, | ||
}, | ||
).Get(ctx, nil) | ||
if err != nil { | ||
return result, err | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func (s *shipment) statusUpdater(ctx workflow.Context) { | ||
var signal shipmentapi.ShipmentUpdateSignal | ||
|
||
ch := workflow.GetSignalChannel(ctx, shipmentapi.ShipmentUpdateSignalName) | ||
for { | ||
ch.Receive(ctx, &signal) | ||
s.status = signal.Status | ||
} | ||
} | ||
|
||
func (s *shipment) waitForStatus(ctx workflow.Context, status shipmentapi.ShipmentStatus) { | ||
workflow.Await(ctx, func() bool { | ||
return s.status == status | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package workflows_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
"github.com/temporalio/orders-reference-app-go/activities" | ||
"github.com/temporalio/orders-reference-app-go/internal/shipmentapi" | ||
"github.com/temporalio/orders-reference-app-go/pkg/ordersapi" | ||
"github.com/temporalio/orders-reference-app-go/workflows" | ||
"go.temporal.io/sdk/testsuite" | ||
) | ||
|
||
func TestShipmentWorkflow(t *testing.T) { | ||
s := testsuite.WorkflowTestSuite{} | ||
env := s.NewTestWorkflowEnvironment() | ||
var a *activities.Activities | ||
|
||
shipmentInput := shipmentapi.ShipmentInput{ | ||
OrderID: "test", | ||
Items: []ordersapi.Item{ | ||
{SKU: "test1", Quantity: 1}, | ||
{SKU: "test2", Quantity: 3}, | ||
}, | ||
} | ||
|
||
env.RegisterActivity(a.RegisterShipment) | ||
|
||
env.OnActivity(a.ShipmentCreatedNotification, mock.Anything, mock.Anything).Return( | ||
func(ctx context.Context, input activities.ShipmentCreatedNotificationInput) error { | ||
env.SignalWorkflow( | ||
shipmentapi.ShipmentUpdateSignalName, | ||
shipmentapi.ShipmentUpdateSignal{ | ||
Status: shipmentapi.ShipmentStatusDispatched, | ||
}, | ||
) | ||
|
||
return nil | ||
}, | ||
) | ||
|
||
env.OnActivity(a.ShipmentDispatchedNotification, mock.Anything, mock.Anything).Return( | ||
func(ctx context.Context, input activities.ShipmentDispatchedNotificationInput) error { | ||
env.SignalWorkflow( | ||
shipmentapi.ShipmentUpdateSignalName, | ||
shipmentapi.ShipmentUpdateSignal{ | ||
Status: shipmentapi.ShipmentStatusDelivered, | ||
}, | ||
) | ||
|
||
return nil | ||
}, | ||
) | ||
|
||
env.RegisterActivity(a.ShipmentDeliveredNotification) | ||
|
||
env.ExecuteWorkflow( | ||
workflows.Shipment, | ||
shipmentInput, | ||
) | ||
|
||
var result shipmentapi.ShipmentResult | ||
err := env.GetWorkflowResult(&result) | ||
assert.NoError(t, err) | ||
} |