more otel
All checks were successful
Build and Publish / Metadata (push) Successful in 11s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 53s
Build and Publish / BuildAndDeployArm64 (push) Successful in 4m49s

This commit is contained in:
2025-11-13 21:40:20 +01:00
parent cebd3ea80f
commit af5d4cd325
10 changed files with 98 additions and 69 deletions

View File

@@ -246,7 +246,7 @@ func (fs *FileServer) CartHandler(w http.ResponseWriter, r *http.Request) {
// reconstruct state from event log if present
grain := cart.NewCartGrain(id, time.Now())
err := fs.storage.LoadEvents(id, grain)
err := fs.storage.LoadEvents(r.Context(), id, grain)
if err != nil {
writeJSON(w, http.StatusInternalServerError, JsonError{Error: err.Error()})
return

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"encoding/json"
"fmt"
"log"
@@ -27,12 +28,12 @@ var tpl = `<!DOCTYPE html>
</html>
`
func (a *App) getGrainFromOrder(order *CheckoutOrder) (*cart.CartGrain, error) {
func (a *App) getGrainFromOrder(ctx context.Context, order *CheckoutOrder) (*cart.CartGrain, error) {
cartId, ok := cart.ParseCartId(order.MerchantReference1)
if !ok {
return nil, fmt.Errorf("invalid cart id in order reference: %s", order.MerchantReference1)
}
grain, err := a.pool.Get(uint64(cartId))
grain, err := a.pool.Get(ctx, uint64(cartId))
if err != nil {
return nil, fmt.Errorf("failed to get cart grain: %w", err)
}
@@ -73,14 +74,14 @@ func (a *App) HandleCheckoutRequests(amqpUrl string, mux *http.ServeMux, invento
return
}
err = confirmOrder(order, orderHandler)
err = confirmOrder(r.Context(), order, orderHandler)
if err != nil {
log.Printf("Error confirming order: %v\n", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
err = triggerOrderCompleted(a.server, order)
err = triggerOrderCompleted(r.Context(), a.server, order)
if err != nil {
log.Printf("Error processing cart message: %v\n", err)
w.WriteHeader(http.StatusInternalServerError)
@@ -143,7 +144,7 @@ func (a *App) HandleCheckoutRequests(amqpUrl string, mux *http.ServeMux, invento
}
log.Printf("Klarna order notification: %s", order.ID)
logger.InfoContext(r.Context(), "Klarna order notification received", "order_id", order.ID)
grain, err := a.getGrainFromOrder(order)
grain, err := a.getGrainFromOrder(r.Context(), order)
if err != nil {
logger.ErrorContext(r.Context(), "Unable to get grain from klarna order", "error", err.Error())
w.WriteHeader(http.StatusInternalServerError)
@@ -173,7 +174,7 @@ func (a *App) HandleCheckoutRequests(amqpUrl string, mux *http.ServeMux, invento
w.WriteHeader(http.StatusBadRequest)
}
logger.InfoContext(r.Context(), "Klarna order validation received", "order_id", order.ID, "cart_id", order.MerchantReference1)
grain, err := a.getGrainFromOrder(order)
grain, err := a.getGrainFromOrder(r.Context(), order)
if err != nil {
logger.ErrorContext(r.Context(), "Unable to get grain from klarna order", "error", err.Error())
w.WriteHeader(http.StatusInternalServerError)

View File

@@ -84,10 +84,13 @@ func main() {
reg := cart.NewCartMultationRegistry()
reg.RegisterProcessor(
actor.NewMutationProcessor(func(g *cart.CartGrain) error {
actor.NewMutationProcessor(func(ctx context.Context, g *cart.CartGrain) error {
_, span := tracer.Start(ctx, "Totals and promotions")
defer span.End()
g.UpdateTotals()
ctx := promotions.NewContextFromCart(g, promotions.WithNow(time.Now()), promotions.WithCustomerSegment("vip"))
_, actions := promotionService.EvaluateAll(promotionData.State.Promotions, ctx)
promotionCtx := promotions.NewContextFromCart(g, promotions.WithNow(time.Now()), promotions.WithCustomerSegment("vip"))
_, actions := promotionService.EvaluateAll(promotionData.State.Promotions, promotionCtx)
for _, action := range actions {
log.Printf("apply: %+v", action)
g.UpdateTotals()
@@ -100,12 +103,14 @@ func main() {
poolConfig := actor.GrainPoolConfig[cart.CartGrain]{
MutationRegistry: reg,
Storage: diskStorage,
Spawn: func(id uint64) (actor.Grain[cart.CartGrain], error) {
Spawn: func(ctx context.Context, id uint64) (actor.Grain[cart.CartGrain], error) {
_, span := tracer.Start(ctx, fmt.Sprintf("Spawn cart id %d", id))
defer span.End()
grainSpawns.Inc()
ret := cart.NewCartGrain(id, time.Now())
// Set baseline lastChange at spawn; replay may update it to last event timestamp.
err := diskStorage.LoadEvents(id, ret)
err := diskStorage.LoadEvents(ctx, id, ret)
return ret, err
},
@@ -249,7 +254,7 @@ func main() {
}
func triggerOrderCompleted(syncedServer *PoolServer, order *CheckoutOrder) error {
func triggerOrderCompleted(ctx context.Context, syncedServer *PoolServer, order *CheckoutOrder) error {
mutation := &messages.OrderCreated{
OrderId: order.ID,
Status: order.Status,
@@ -258,12 +263,12 @@ func triggerOrderCompleted(syncedServer *PoolServer, order *CheckoutOrder) error
if !ok {
return fmt.Errorf("invalid cart id in order reference: %s", order.MerchantReference1)
}
_, applyErr := syncedServer.Apply(uint64(cid), mutation)
_, applyErr := syncedServer.Apply(ctx, uint64(cid), mutation)
return applyErr
}
func confirmOrder(order *CheckoutOrder, orderHandler *AmqpOrderHandler) error {
func confirmOrder(ctx context.Context, order *CheckoutOrder, orderHandler *AmqpOrderHandler) error {
orderToSend, err := json.Marshal(order)
if err != nil {
return err

View File

@@ -55,12 +55,12 @@ func NewPoolServer(pool actor.GrainPool[*cart.CartGrain], pod_name string, klarn
}
}
func (s *PoolServer) ApplyLocal(id cart.CartId, mutation ...proto.Message) (*actor.MutationResult[*cart.CartGrain], error) {
return s.Apply(uint64(id), mutation...)
func (s *PoolServer) ApplyLocal(ctx context.Context, id cart.CartId, mutation ...proto.Message) (*actor.MutationResult[*cart.CartGrain], error) {
return s.Apply(ctx, uint64(id), mutation...)
}
func (s *PoolServer) GetCartHandler(w http.ResponseWriter, r *http.Request, id cart.CartId) error {
grain, err := s.Get(uint64(id))
grain, err := s.Get(r.Context(), uint64(id))
if err != nil {
return err
}
@@ -74,7 +74,7 @@ func (s *PoolServer) AddSkuToCartHandler(w http.ResponseWriter, r *http.Request,
if err != nil {
return err
}
data, err := s.ApplyLocal(id, msg)
data, err := s.ApplyLocal(r.Context(), id, msg)
if err != nil {
return err
}
@@ -106,7 +106,7 @@ func (s *PoolServer) DeleteItemHandler(w http.ResponseWriter, r *http.Request, i
if err != nil {
return err
}
data, err := s.ApplyLocal(id, &messages.RemoveItem{Id: uint32(itemId)})
data, err := s.ApplyLocal(r.Context(), id, &messages.RemoveItem{Id: uint32(itemId)})
if err != nil {
return err
}
@@ -126,7 +126,7 @@ func (s *PoolServer) SetDeliveryHandler(w http.ResponseWriter, r *http.Request,
if err != nil {
return err
}
data, err := s.ApplyLocal(id, &messages.SetDelivery{
data, err := s.ApplyLocal(r.Context(), id, &messages.SetDelivery{
Provider: delivery.Provider,
Items: delivery.Items,
PickupPoint: delivery.PickupPoint,
@@ -149,7 +149,7 @@ func (s *PoolServer) SetPickupPointHandler(w http.ResponseWriter, r *http.Reques
if err != nil {
return err
}
reply, err := s.ApplyLocal(id, &messages.SetPickupPoint{
reply, err := s.ApplyLocal(r.Context(), id, &messages.SetPickupPoint{
DeliveryId: uint32(deliveryId),
Id: pickupPoint.Id,
Name: pickupPoint.Name,
@@ -171,7 +171,7 @@ func (s *PoolServer) RemoveDeliveryHandler(w http.ResponseWriter, r *http.Reques
if err != nil {
return err
}
reply, err := s.ApplyLocal(id, &messages.RemoveDelivery{Id: uint32(deliveryId)})
reply, err := s.ApplyLocal(r.Context(), id, &messages.RemoveDelivery{Id: uint32(deliveryId)})
if err != nil {
return err
}
@@ -184,7 +184,7 @@ func (s *PoolServer) QuantityChangeHandler(w http.ResponseWriter, r *http.Reques
if err != nil {
return err
}
reply, err := s.ApplyLocal(id, &changeQuantity)
reply, err := s.ApplyLocal(r.Context(), id, &changeQuantity)
if err != nil {
return err
}
@@ -234,7 +234,7 @@ func (s *PoolServer) SetCartItemsHandler(w http.ResponseWriter, r *http.Request,
msgs = append(msgs, &messages.ClearCartRequest{})
msgs = append(msgs, getMultipleAddMessages(r.Context(), setCartItems.Items, setCartItems.Country)...)
reply, err := s.ApplyLocal(id, msgs...)
reply, err := s.ApplyLocal(r.Context(), id, msgs...)
if err != nil {
return err
}
@@ -248,7 +248,7 @@ func (s *PoolServer) AddMultipleItemHandler(w http.ResponseWriter, r *http.Reque
return err
}
reply, err := s.ApplyLocal(id, getMultipleAddMessages(r.Context(), setCartItems.Items, setCartItems.Country)...)
reply, err := s.ApplyLocal(r.Context(), id, getMultipleAddMessages(r.Context(), setCartItems.Items, setCartItems.Country)...)
if err != nil {
return err
}
@@ -272,7 +272,7 @@ func (s *PoolServer) AddSkuRequestHandler(w http.ResponseWriter, r *http.Request
if err != nil {
return err
}
reply, err := s.ApplyLocal(id, msg)
reply, err := s.ApplyLocal(r.Context(), id, msg)
if err != nil {
return err
}
@@ -350,7 +350,7 @@ func (s *PoolServer) CreateOrUpdateCheckout(ctx context.Context, host string, id
}
// Get current grain state (may be local or remote)
grain, err := s.Get(uint64(id))
grain, err := s.Get(ctx, uint64(id))
if err != nil {
return nil, err
}
@@ -376,9 +376,9 @@ func (s *PoolServer) CreateOrUpdateCheckout(ctx context.Context, host string, id
}
}
func (s *PoolServer) ApplyCheckoutStarted(klarnaOrder *CheckoutOrder, id cart.CartId) (*actor.MutationResult[*cart.CartGrain], error) {
func (s *PoolServer) ApplyCheckoutStarted(ctx context.Context, klarnaOrder *CheckoutOrder, id cart.CartId) (*actor.MutationResult[*cart.CartGrain], error) {
// Persist initialization state via mutation (best-effort)
return s.ApplyLocal(id, &messages.InitializeCheckout{
return s.ApplyLocal(ctx, id, &messages.InitializeCheckout{
OrderId: klarnaOrder.ID,
Status: klarnaOrder.Status,
PaymentInProgress: true,
@@ -544,7 +544,7 @@ func (s *PoolServer) AddVoucherHandler(w http.ResponseWriter, r *http.Request, c
v := voucher.Service{}
msg, err := v.GetVoucher(data.VoucherCode)
if err != nil {
s.ApplyLocal(cartId, &messages.PreConditionFailed{
s.ApplyLocal(r.Context(), cartId, &messages.PreConditionFailed{
Operation: "AddVoucher",
Error: err.Error(),
})
@@ -552,7 +552,7 @@ func (s *PoolServer) AddVoucherHandler(w http.ResponseWriter, r *http.Request, c
w.Write([]byte(err.Error()))
return err
}
reply, err := s.ApplyLocal(cartId, msg)
reply, err := s.ApplyLocal(r.Context(), cartId, msg)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
@@ -570,7 +570,7 @@ func (s *PoolServer) SubscriptionDetailsHandler(w http.ResponseWriter, r *http.R
w.Write([]byte(err.Error()))
return err
}
reply, err := s.ApplyLocal(cartId, data)
reply, err := s.ApplyLocal(r.Context(), cartId, data)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
@@ -589,7 +589,7 @@ func (s *PoolServer) CheckoutHandler(fn func(order *CheckoutOrder, w http.Respon
logger.Error("unable to create klarna session", "error", err)
return err
}
s.ApplyCheckoutStarted(order, cartId)
s.ApplyCheckoutStarted(r.Context(), order, cartId)
return fn(order, w)
}
order, err := s.klarnaClient.GetOrder(r.Context(), orderId)
@@ -609,7 +609,7 @@ func (s *PoolServer) RemoveVoucherHandler(w http.ResponseWriter, r *http.Request
w.Write([]byte(err.Error()))
return err
}
reply, err := s.ApplyLocal(cartId, &messages.RemoveVoucher{Id: uint32(id)})
reply, err := s.ApplyLocal(r.Context(), cartId, &messages.RemoveVoucher{Id: uint32(id)})
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))