Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
fix: backend services and frontend codegen (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
wesbillman authored Feb 7, 2024
1 parent 6ff12ec commit dd7cbb1
Show file tree
Hide file tree
Showing 38 changed files with 518 additions and 485 deletions.
20 changes: 12 additions & 8 deletions backend/online-boutique/services/ad/ad.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
_ "embed"
"math/rand"

"ftl/builtin"

"github.com/TBD54566975/ftl/examples/online-boutique/common"
"golang.org/x/exp/maps"
)
Expand Down Expand Up @@ -34,15 +36,17 @@ type AdResponse struct {

//ftl:verb
//ftl:ingress GET /ad
func Get(ctx context.Context, req AdRequest) (AdResponse, error) {
resp := AdResponse{}
if len(req.ContextKeys) > 0 {
resp.Ads = contextualAds(req.ContextKeys)
}
if len(resp.Ads) == 0 {
resp.Ads = randomAds()
func Get(ctx context.Context, req builtin.HttpRequest[AdRequest]) (builtin.HttpResponse[AdResponse], error) {
var ads []Ad
if len(req.Body.ContextKeys) > 0 {
ads = contextualAds(req.Body.ContextKeys)
} else {
ads = randomAds()
}
return resp, nil

return builtin.HttpResponse[AdResponse]{
Body: AdResponse{Name: "ad", Ads: ads},
}, nil
}

func contextualAds(contextKeys []string) (ads []Ad) {
Expand Down
23 changes: 15 additions & 8 deletions backend/online-boutique/services/cart/cart.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cart

import (
"context"
"ftl/builtin"
)

var store = NewStore()
Expand All @@ -26,9 +27,11 @@ type Cart struct {

//ftl:verb
//ftl:ingress POST /cart/add
func AddItem(ctx context.Context, req AddItemRequest) (AddItemResponse, error) {
store.Add(req.UserID, req.Item)
return AddItemResponse{}, nil
func AddItem(ctx context.Context, req builtin.HttpRequest[AddItemRequest]) (builtin.HttpResponse[AddItemResponse], error) {
store.Add(req.Body.UserID, req.Body.Item)
return builtin.HttpResponse[AddItemResponse]{
Body: AddItemResponse{},
}, nil
}

type GetCartRequest struct {
Expand All @@ -37,8 +40,10 @@ type GetCartRequest struct {

//ftl:verb
//ftl:ingress GET /cart
func GetCart(ctx context.Context, req GetCartRequest) (Cart, error) {
return Cart{Items: store.Get(req.UserID), UserID: req.UserID}, nil
func GetCart(ctx context.Context, req builtin.HttpRequest[GetCartRequest]) (builtin.HttpResponse[Cart], error) {
return builtin.HttpResponse[Cart]{
Body: Cart{Items: store.Get(req.Body.UserID), UserID: req.Body.UserID},
}, nil
}

type EmptyCartRequest struct {
Expand All @@ -49,7 +54,9 @@ type EmptyCartResponse struct{}

//ftl:verb
//ftl:ingress POST /cart/empty
func EmptyCart(ctx context.Context, req EmptyCartRequest) (EmptyCartResponse, error) {
store.Empty(req.UserID)
return EmptyCartResponse{}, nil
func EmptyCart(ctx context.Context, req builtin.HttpRequest[EmptyCartRequest]) (builtin.HttpResponse[EmptyCartResponse], error) {
store.Empty(req.Body.UserID)
return builtin.HttpResponse[EmptyCartResponse]{
Body: EmptyCartResponse{},
}, nil
}
86 changes: 49 additions & 37 deletions backend/online-boutique/services/checkout/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/google/uuid"

"ftl/builtin"
"ftl/cart"
"ftl/currency"
"ftl/payment"
Expand All @@ -15,6 +16,7 @@ import (

"github.com/TBD54566975/ftl/backend/common/slices"
"github.com/TBD54566975/ftl/examples/online-boutique/common/money"

ftl "github.com/TBD54566975/ftl/go-runtime/sdk"
)

Expand Down Expand Up @@ -42,78 +44,88 @@ type Order struct {

//ftl:verb
//ftl:ingress POST /checkout/{userID}
func PlaceOrder(ctx context.Context, req PlaceOrderRequest) (Order, error) {
cartItems, err := ftl.Call(ctx, cart.GetCart, cart.GetCartRequest{UserID: req.UserID})
func PlaceOrder(ctx context.Context, req builtin.HttpRequest[PlaceOrderRequest]) (builtin.HttpResponse[Order], error) {
cartItems, err := ftl.Call(ctx, cart.GetCart, builtin.HttpRequest[cart.GetCartRequest]{Body: cart.GetCartRequest{UserID: req.Body.UserID}})
if err != nil {
return Order{}, fmt.Errorf("failed to get cart: %w", err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("failed to get cart: %w", err)
}

orders := make([]OrderItem, len(cartItems.Items))
for i, item := range cartItems.Items {
product, err := ftl.Call(ctx, productcatalog.Get, productcatalog.GetRequest{Id: item.ProductID})
orders := make([]OrderItem, len(cartItems.Body.Items))
for i, item := range cartItems.Body.Items {
products, err := ftl.Call(ctx, productcatalog.Get, builtin.HttpRequest[productcatalog.GetRequest]{Body: productcatalog.GetRequest{Id: item.ProductID}})
if err != nil {
return Order{}, fmt.Errorf("failed to get product #%q: %w", item.ProductID, err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("failed to get product #%q: %w", item.ProductID, err)
}
price, err := ftl.Call(ctx, currency.Convert, currency.ConvertRequest{
From: product.PriceUSD,
ToCode: req.UserCurrency,
price, err := ftl.Call(ctx, currency.Convert, builtin.HttpRequest[currency.ConvertRequest]{
Body: currency.ConvertRequest{
From: products.Body.PriceUSD,
ToCode: req.Body.UserCurrency,
},
})
if err != nil {
return Order{}, fmt.Errorf("failed to convert price of %q to %s: %w", item.ProductID, req.UserCurrency, err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("failed to convert price of %q to %s: %w", item.ProductID, req.Body.UserCurrency, err)
}
orders[i] = OrderItem{
Item: item,
Cost: price,
Cost: price.Body,
}
}

shippingUSD, err := ftl.Call(ctx, shipping.GetQuote, shipping.ShippingRequest{
Address: req.Address,
Items: slices.Map(orders, func(i OrderItem) cart.Item { return i.Item }),
shippingUSD, err := ftl.Call(ctx, shipping.GetQuote, builtin.HttpRequest[shipping.ShippingRequest]{
Body: shipping.ShippingRequest{
Address: req.Body.Address,
Items: slices.Map(orders, func(i OrderItem) cart.Item { return i.Item }),
},
})
if err != nil {
return Order{}, fmt.Errorf("failed to get shipping quote: %w", err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("failed to get shipping quote: %w", err)
}
shippingPrice, err := ftl.Call(ctx, currency.Convert, currency.ConvertRequest{
From: shippingUSD,
ToCode: req.UserCurrency,
shippingPrice, err := ftl.Call(ctx, currency.Convert, builtin.HttpRequest[currency.ConvertRequest]{
Body: currency.ConvertRequest{
From: shippingUSD.Body,
ToCode: req.Body.UserCurrency,
},
})
if err != nil {
return Order{}, fmt.Errorf("failed to convert shipping cost to currency: %w", err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("failed to convert shipping cost to currency: %w", err)
}

total := currency.Money{CurrencyCode: req.UserCurrency}
total = money.Must(money.Sum(total, shippingPrice))
total := currency.Money{CurrencyCode: req.Body.UserCurrency}
total = money.Must(money.Sum(total, shippingPrice.Body))
for _, it := range orders {
multPrice := money.MultiplySlow(it.Cost, uint32(it.Item.Quantity))
total = money.Must(money.Sum(total, multPrice))
}
txID, err := ftl.Call(ctx, payment.Charge, payment.ChargeRequest{
Amount: total,
CreditCard: req.CreditCard,
txID, err := ftl.Call(ctx, payment.Charge, builtin.HttpRequest[payment.ChargeRequest]{
Body: payment.ChargeRequest{
Amount: total,
CreditCard: req.Body.CreditCard,
},
})
if err != nil {
return Order{}, fmt.Errorf("failed to charge card: %w", err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("failed to charge card: %w", err)
}
fmt.Printf("Charged card, ID %s", txID.TransactionID)
fmt.Printf("Charged card, ID %s", txID.Body.TransactionID)

shippingTrackingID, err := ftl.Call(ctx, shipping.ShipOrder, shipping.ShippingRequest{
Address: req.Address,
Items: cartItems.Items,
shippingTrackingID, err := ftl.Call(ctx, shipping.ShipOrder, builtin.HttpRequest[shipping.ShippingRequest]{
Body: shipping.ShippingRequest{
Address: req.Body.Address,
Items: cartItems.Body.Items,
},
})
if err != nil {
return Order{}, fmt.Errorf("shipping error: %w", err)
return builtin.HttpResponse[Order]{}, fmt.Errorf("shipping error: %w", err)
}
fmt.Printf("Shipped order, tracking ID %s", shippingTrackingID.Id)
fmt.Printf("Shipped order, tracking ID %s", shippingTrackingID.Body.Id)

// Empty the cart, but don't worry about errors.
_, _ = ftl.Call(ctx, cart.EmptyCart, cart.EmptyCartRequest{UserID: req.UserID})
_, _ = ftl.Call(ctx, cart.EmptyCart, builtin.HttpRequest[cart.EmptyCartRequest]{Body: cart.EmptyCartRequest{UserID: req.Body.UserID}})

order := Order{
ID: uuid.New().String(),
ShippingTrackingID: shippingTrackingID.Id,
ShippingCost: shippingPrice,
ShippingAddress: req.Address,
ShippingTrackingID: shippingTrackingID.Body.Id,
ShippingCost: shippingPrice.Body,
ShippingAddress: req.Body.Address,
Items: orders,
}
// if err := s.emailService.Get().SendOrderConfirmation(ctx, req.Email, order); err != nil {
Expand All @@ -122,5 +134,5 @@ func PlaceOrder(ctx context.Context, req PlaceOrderRequest) (Order, error) {
// s.Logger(ctx).Info("order confirmation email sent", "email", req.Email)
// }

return order, nil
return builtin.HttpResponse[Order]{Body: order}, nil
}
14 changes: 7 additions & 7 deletions backend/online-boutique/services/checkout/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ go 1.21.6
replace github.com/TBD54566975/ftl/examples/online-boutique => ../..

require (
github.com/TBD54566975/ftl v0.107.0
github.com/TBD54566975/ftl v0.118.2
github.com/TBD54566975/ftl/examples/online-boutique v0.0.0-00010101000000-000000000000
github.com/google/uuid v1.5.0
github.com/google/uuid v1.6.0
)

require (
Expand All @@ -16,7 +16,7 @@ require (
connectrpc.com/otelconnect v0.7.0 // indirect
github.com/alecthomas/concurrency v0.0.2 // indirect
github.com/alecthomas/participle/v2 v2.1.1 // indirect
github.com/alecthomas/types v0.9.0 // indirect
github.com/alecthomas/types v0.10.1 // indirect
github.com/alessio/shellescape v1.4.2 // indirect
github.com/danieljoos/wincred v1.2.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
Expand All @@ -25,7 +25,7 @@ require (
github.com/iancoleman/strcase v0.2.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.5.2 // indirect
github.com/jackc/pgx/v5 v5.5.3 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
Expand All @@ -34,9 +34,9 @@ require (
github.com/swaggest/jsonschema-go v0.3.64 // indirect
github.com/swaggest/refl v1.3.0 // indirect
github.com/zalando/go-keyring v0.2.3 // indirect
go.opentelemetry.io/otel v1.21.0 // indirect
go.opentelemetry.io/otel/metric v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
go.opentelemetry.io/otel v1.22.0 // indirect
go.opentelemetry.io/otel/metric v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
golang.design/x/reflect v0.0.0-20220504060917-02c43be63f3b // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect
Expand Down
36 changes: 18 additions & 18 deletions backend/online-boutique/services/checkout/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U
connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY=
connectrpc.com/otelconnect v0.7.0 h1:ZH55ZZtcJOTKWWLy3qmL4Pam4RzRWBJFOqTPyAqCXkY=
connectrpc.com/otelconnect v0.7.0/go.mod h1:Bt2ivBymHZHqxvo4HkJ0EwHuUzQN6k2l0oH+mp/8nwc=
github.com/TBD54566975/ftl v0.107.0 h1:zdeWEETDkcu+0onfgk/9IVsB5QPC++mv751fTVXePtA=
github.com/TBD54566975/ftl v0.107.0/go.mod h1:7yRFD+2zC5zstcXYcSJzAubRi6MecQZndMnEbd1zMwM=
github.com/TBD54566975/ftl v0.118.2 h1:UgeM/nRFyrKAsCO9xL4QBR3+2mL+KOBcAmyZkqageoU=
github.com/TBD54566975/ftl v0.118.2/go.mod h1:pk9NJHy+waKcZgCpbf67vSZC6dOs/GG0CrlkeTAs90g=
github.com/alecthomas/assert/v2 v2.5.0 h1:OJKYg53BQx06/bMRBSPDCO49CbCDNiUQXwdoNrt6x5w=
github.com/alecthomas/assert/v2 v2.5.0/go.mod h1:fw5suVxB+wfYJ3291t0hRTqtGzFYdSwstnRQdaQx2DM=
github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo=
Expand All @@ -14,8 +14,8 @@ github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6i
github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c=
github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8=
github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/types v0.9.0 h1:g/P/fNElr7Ot1tWxSEms/I2gnRemxAqGNeetW6HOlO4=
github.com/alecthomas/types v0.9.0/go.mod h1:t7PnU03TVweFpbPVKaeLtFykjJD8rqiBJ7gfkp6UvLQ=
github.com/alecthomas/types v0.10.1 h1:PuBMoHpFL2jaW3VgPDRhCk1oKoBCzfbsL5sAxEc3U3A=
github.com/alecthomas/types v0.10.1/go.mod h1:fIOGnLeeUJXe1AAVofQmMaEMWLxY9bK4QxTLGIo30PA=
github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0=
github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/bool64/dev v0.2.31 h1:OS57EqYaYe2M/2bw9uhDCIFiZZwywKFS/4qMLN6JUmQ=
Expand All @@ -38,8 +38,8 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc=
Expand All @@ -50,8 +50,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.2 h1:iLlpgp4Cp/gC9Xuscl7lFL1PhhW+ZLtXZcrfCt4C3tA=
github.com/jackc/pgx/v5 v5.5.2/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s=
github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
Expand Down Expand Up @@ -90,16 +90,16 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3Ifn
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms=
github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk=
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0=
go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q=
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw=
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
go.opentelemetry.io/otel/sdk/metric v1.22.0 h1:ARrRetm1HCVxq0cbnaZQlfwODYJHo3gFL8Z3tSmHBcI=
go.opentelemetry.io/otel/sdk/metric v1.22.0/go.mod h1:KjQGeMIDlBNEOo6HvjhxIec1p/69/kULDcp4gr0oLQQ=
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
golang.design/x/reflect v0.0.0-20220504060917-02c43be63f3b h1:lkOPTy76R9NZ6FeDQWkDj3NsLtD8Csc9AAFYEl3kiME=
golang.design/x/reflect v0.0.0-20220504060917-02c43be63f3b/go.mod h1:QXG482h3unP32W/YwIPOc+09bvY447B7T+iLjC/JPcA=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
Expand Down
23 changes: 14 additions & 9 deletions backend/online-boutique/services/currency/currency.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"math"

"ftl/builtin"

"golang.org/x/exp/maps"

"github.com/TBD54566975/ftl/examples/online-boutique/common"
Expand Down Expand Up @@ -45,8 +47,10 @@ type GetSupportedCurrenciesResponse struct {

//ftl:verb
//ftl:ingress GET /currency/supported
func GetSupportedCurrencies(ctx context.Context, req GetSupportedCurrenciesRequest) (GetSupportedCurrenciesResponse, error) {
return GetSupportedCurrenciesResponse{CurrencyCodes: maps.Keys(database)}, nil
func GetSupportedCurrencies(ctx context.Context, req builtin.HttpRequest[GetSupportedCurrenciesRequest]) (builtin.HttpResponse[GetSupportedCurrenciesResponse], error) {
return builtin.HttpResponse[GetSupportedCurrenciesResponse]{
Body: GetSupportedCurrenciesResponse{CurrencyCodes: maps.Keys(database)},
}, nil
}

type ConvertRequest struct {
Expand All @@ -56,20 +60,21 @@ type ConvertRequest struct {

//ftl:verb
//ftl:ingress POST /currency/convert
func Convert(ctx context.Context, req ConvertRequest) (Money, error) {
from := req.From
func Convert(ctx context.Context, req builtin.HttpRequest[ConvertRequest]) (builtin.HttpResponse[Money], error) {
from := req.Body.From
fromRate, ok := database[from.CurrencyCode]
if !ok {
return Money{}, fmt.Errorf("unknown origin currency %q", req.From.CurrencyCode)
return builtin.HttpResponse[Money]{}, fmt.Errorf("unknown origin currency %q", req.Body.From.CurrencyCode)
}
toRate, ok := database[req.ToCode]
toRate, ok := database[req.Body.ToCode]
if !ok {
return Money{}, fmt.Errorf("unknown destination currency %q", req.ToCode)
return builtin.HttpResponse[Money]{}, fmt.Errorf("unknown destination currency %q", req.Body.ToCode)
}
euros := carry(float64(from.Units)/fromRate, float64(from.Nanos)/fromRate)
to := carry(float64(euros.Units)*toRate, float64(euros.Nanos)*toRate)
to.CurrencyCode = req.ToCode
return to, nil
to.CurrencyCode = req.Body.ToCode

return builtin.HttpResponse[Money]{Body: to}, nil
}

// carry is a helper function that handles decimal/fractional carrying.
Expand Down
Loading

0 comments on commit dd7cbb1

Please sign in to comment.