Files
go-cart-actor/pkg/cart/mutation_change_quantity.go
matst80 aea168160e
All checks were successful
Build and Publish / BuildAndDeployAmd64 (push) Successful in 35s
Build and Publish / BuildAndDeployArm64 (push) Successful in 3m45s
update
2025-11-27 12:45:34 +01:00

80 lines
2.2 KiB
Go

package cart
import (
"context"
"fmt"
"log"
messages "git.k6n.net/go-cart-actor/pkg/messages"
)
// mutation_change_quantity.go
//
// Registers the ChangeQuantity mutation.
//
// Behavior:
// - Locates an item by its cart-local line item Id (not source item_id).
// - If requested quantity <= 0 the line is removed.
// - Otherwise the line's Quantity field is updated.
// - Totals are recalculated (WithTotals).
//
// Error handling:
// - Returns an error if the item Id is not found.
// - Returns an error if payload is nil (defensive).
//
// Concurrency:
// - Uses the grain's RW-safe mutation pattern: we mutate in place under
// the grain's implicit expectation that higher layers control access.
// (If strict locking is required around every mutation, wrap logic in
// an explicit g.mu.Lock()/Unlock(), but current model mirrors prior code.)
func (c *CartMutationContext) ChangeQuantity(g *CartGrain, m *messages.ChangeQuantity) error {
if m == nil {
return fmt.Errorf("ChangeQuantity: nil payload")
}
ctx := context.Background()
foundIndex := -1
for i, it := range g.Items {
if it.Id == uint32(m.Id) {
foundIndex = i
break
}
}
if foundIndex == -1 {
return fmt.Errorf("ChangeQuantity: item id %d not found", m.Id)
}
if m.Quantity <= 0 {
// Remove the item
itemToRemove := g.Items[foundIndex]
err := c.ReleaseItem(ctx, g.Id, itemToRemove.Sku, itemToRemove.StoreId)
if err != nil {
log.Printf("unable to release reservation for %s in location: %v", itemToRemove.Sku, itemToRemove.StoreId)
}
g.Items = append(g.Items[:foundIndex], g.Items[foundIndex+1:]...)
g.UpdateTotals()
return nil
}
item := g.Items[foundIndex]
if item == nil {
return fmt.Errorf("ChangeQuantity: item id %d not found", m.Id)
}
if item.ReservationEndTime != nil {
err := c.ReleaseItem(ctx, g.Id, item.Sku, item.StoreId)
if err != nil {
log.Printf("unable to release reservation for %s in location: %v", item.Sku, item.StoreId)
}
}
endTime, err := c.ReserveItem(ctx, g.Id, item.Sku, item.StoreId, uint16(m.Quantity))
if err != nil {
return err
}
item.ReservationEndTime = endTime
item.Quantity = uint16(m.Quantity)
g.UpdateTotals()
return nil
}