Long running, complex interactions...
...in distributed systems.
func placeOrder(o Order) {
warehouse.ReserveItems(o.Items)
payment.ProcessPayment(o)
notifyBuyer(o, OrderPlaced)
saveOrder(o)
}
func placeOrder(o Order) {
reserved, err := warehouse.ReserveItems(o.Items)
if err != nil { // Warehouse service unavailable
// Retry?
}
if !reserved { // Business error requiring user intervention
notifySeller(o, OrderFailed)
notifyBuyer(o, OrderFailed)
return
}
// ...
}
Source: StackOverflow Blog
func placeOrder(o Order) {
warehouse.ReserveItems(o.Items)
payment.ProcessPayment(o)
notifyBuyer(o, OrderPlaced)
saveOrder(o)
}
Source: Temporal docs
Checkout the following repository:
https://github.com/sagikazarmark/temporal-intro-workshop
Follow the instructions in the readme.
make shell
func placeOrder(o Order) {
warehouse.ReserveItems(o.Items)
payment.ProcessPayment(o)
notifyBuyer(o, OrderPlaced)
saveOrder(o)
}
Write a test for Example 2.
Output value is based entirely on the input.
func add(a, b int) int {
return a + b
}
func add(a, b int) int {
// This is not deterministic
resp := http.Get(fmt.Sprintf("https://add.com/%d/%d", a, b))
return decodeBody(resp.Body)
}
time.Now
, time.Sleep
Use deterministic wrappers instead.
StartTimer
-> TimerStarted
)func Workflow(ctx workflow.Context, input Input) (Output, error) {
encodedNumber := workflow.SideEffect(ctx, func(ctx workflow.Context) interface{} {
return rand.Intn(max)
})
sum := input.Number + number
workflow.Sleep(ctx, 1*time.Second)
return Output{sum}, nil
}
Write a query handler (for your workflow from examples 2, 4) that returns the current result in the loop.
Add sleep at the beginning of the loop so you have time to query it using the CLI.
Rewrite the factorial calculation (based on examples 2, 4, 7) as an activity (with retries and timeouts):
https://stackoverflow.blog/2020/11/23/the-macro-problem-with-microservices/