refactor/checkout (#8)
Co-authored-by: matst80 <mats.tornberg@gmail.com> Reviewed-on: #8 Co-authored-by: Mats Törnberg <mats@tornberg.me> Co-committed-by: Mats Törnberg <mats@tornberg.me>
This commit was merged in pull request #8.
This commit is contained in:
@@ -8,7 +8,7 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
messages "git.k6n.net/go-cart-actor/pkg/messages"
|
||||
messages "git.k6n.net/go-cart-actor/proto/control"
|
||||
"go.opentelemetry.io/contrib/bridges/otelslog"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@@ -145,7 +145,7 @@ func (s *ControlServer[V]) AnnounceExpiry(ctx context.Context, req *messages.Exp
|
||||
}
|
||||
|
||||
// ControlPlane: Ping
|
||||
func (s *ControlServer[V]) Ping(ctx context.Context, _ *messages.Empty) (*messages.PingReply, error) {
|
||||
func (s *ControlServer[V]) Ping(ctx context.Context, req *messages.Empty) (*messages.PingReply, error) {
|
||||
|
||||
host := s.pool.Hostname()
|
||||
|
||||
@@ -191,7 +191,7 @@ func (s *ControlServer[V]) Negotiate(ctx context.Context, req *messages.Negotiat
|
||||
}
|
||||
|
||||
// ControlPlane: GetCartIds (locally owned carts only)
|
||||
func (s *ControlServer[V]) GetLocalActorIds(ctx context.Context, _ *messages.Empty) (*messages.ActorIdsReply, error) {
|
||||
func (s *ControlServer[V]) GetLocalActorIds(ctx context.Context, req *messages.Empty) (*messages.ActorIdsReply, error) {
|
||||
ctx, span := tracer.Start(ctx, "grpc_get_local_actor_ids")
|
||||
defer span.End()
|
||||
ids := s.pool.GetLocalIds()
|
||||
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.k6n.net/go-cart-actor/pkg/messages"
|
||||
cart_messages "git.k6n.net/go-cart-actor/proto/cart"
|
||||
control_plane_messages "git.k6n.net/go-cart-actor/proto/control"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -70,12 +71,12 @@ func TestApplyRequestWithMutations(t *testing.T) {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client := messages.NewControlPlaneClient(conn)
|
||||
client := control_plane_messages.NewControlPlaneClient(conn)
|
||||
|
||||
// Prepare ApplyRequest with multiple Any messages
|
||||
addItemAny, _ := anypb.New(&messages.AddItem{ItemId: 1, Quantity: 2})
|
||||
removeItemAny, _ := anypb.New(&messages.RemoveItem{Id: 1})
|
||||
req := &messages.ApplyRequest{
|
||||
addItemAny, _ := anypb.New(&cart_messages.AddItem{ItemId: 1, Quantity: 2})
|
||||
removeItemAny, _ := anypb.New(&cart_messages.RemoveItem{Id: 1})
|
||||
req := &control_plane_messages.ApplyRequest{
|
||||
Id: 123,
|
||||
Messages: []*anypb.Any{addItemAny, removeItemAny},
|
||||
}
|
||||
@@ -95,10 +96,10 @@ func TestApplyRequestWithMutations(t *testing.T) {
|
||||
if len(pool.applied) != 2 {
|
||||
t.Errorf("expected 2 mutations applied, got %d", len(pool.applied))
|
||||
}
|
||||
if addItem, ok := pool.applied[0].(*messages.AddItem); !ok || addItem.ItemId != 1 {
|
||||
if addItem, ok := pool.applied[0].(*cart_messages.AddItem); !ok || addItem.ItemId != 1 {
|
||||
t.Errorf("expected AddItem with ItemId=1, got %v", pool.applied[0])
|
||||
}
|
||||
if removeItem, ok := pool.applied[1].(*messages.RemoveItem); !ok || removeItem.Id != 1 {
|
||||
if removeItem, ok := pool.applied[1].(*cart_messages.RemoveItem); !ok || removeItem.Id != 1 {
|
||||
t.Errorf("expected RemoveItem with Id=1, got %v", pool.applied[1])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,14 +95,18 @@ type MutationHandler interface {
|
||||
type RegisteredMutation[V any, T proto.Message] struct {
|
||||
name string
|
||||
handler func(*V, T) error
|
||||
create func() T
|
||||
create func() proto.Message
|
||||
msgType reflect.Type
|
||||
}
|
||||
|
||||
func NewMutation[V any, T proto.Message](handler func(*V, T) error, create func() T) *RegisteredMutation[V, T] {
|
||||
func NewMutation[V any, T proto.Message](handler func(*V, T) error) *RegisteredMutation[V, T] {
|
||||
// Derive the name and message type from a concrete instance produced by create().
|
||||
// This avoids relying on reflect.TypeFor (which can yield unexpected results in some toolchains)
|
||||
// and ensures we always peel off the pointer layer for proto messages.
|
||||
create := func() proto.Message {
|
||||
m := new(T)
|
||||
return *m
|
||||
}
|
||||
instance := create()
|
||||
rt := reflect.TypeOf(instance)
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
|
||||
@@ -6,33 +6,32 @@ import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"git.k6n.net/go-cart-actor/pkg/messages"
|
||||
cart_messages "git.k6n.net/go-cart-actor/proto/cart"
|
||||
)
|
||||
|
||||
type cartState struct {
|
||||
calls int
|
||||
lastAdded *messages.AddItem
|
||||
lastAdded *cart_messages.AddItem
|
||||
}
|
||||
|
||||
func TestRegisteredMutationBasics(t *testing.T) {
|
||||
reg := NewMutationRegistry().(*ProtoMutationRegistry)
|
||||
|
||||
addItemMutation := NewMutation(
|
||||
func(state *cartState, msg *messages.AddItem) error {
|
||||
func(state *cartState, msg *cart_messages.AddItem) error {
|
||||
state.calls++
|
||||
// copy to avoid external mutation side-effects (not strictly necessary for the test)
|
||||
cp := msg
|
||||
state.lastAdded = cp
|
||||
return nil
|
||||
},
|
||||
func() *messages.AddItem { return &messages.AddItem{} },
|
||||
)
|
||||
|
||||
// Sanity check on mutation metadata
|
||||
if addItemMutation.Name() != "AddItem" {
|
||||
t.Fatalf("expected mutation Name() == AddItem, got %s", addItemMutation.Name())
|
||||
}
|
||||
if got, want := addItemMutation.Type(), reflect.TypeOf(messages.AddItem{}); got != want {
|
||||
if got, want := addItemMutation.Type(), reflect.TypeOf(cart_messages.AddItem{}); got != want {
|
||||
t.Fatalf("expected Type() == %v, got %v", want, got)
|
||||
}
|
||||
|
||||
@@ -46,18 +45,18 @@ func TestRegisteredMutationBasics(t *testing.T) {
|
||||
|
||||
// RegisteredMutationTypes: membership (order not guaranteed)
|
||||
types := reg.RegisteredMutationTypes()
|
||||
if !slices.Contains(types, reflect.TypeOf(messages.AddItem{})) {
|
||||
if !slices.Contains(types, reflect.TypeOf(cart_messages.AddItem{})) {
|
||||
t.Fatalf("RegisteredMutationTypes missing AddItem type, got %v", types)
|
||||
}
|
||||
|
||||
// GetTypeName should resolve for a pointer instance
|
||||
name, ok := reg.GetTypeName(&messages.AddItem{})
|
||||
name, ok := reg.GetTypeName(&cart_messages.AddItem{})
|
||||
if !ok || name != "AddItem" {
|
||||
t.Fatalf("GetTypeName returned (%q,%v), expected (AddItem,true)", name, ok)
|
||||
}
|
||||
|
||||
// GetTypeName should fail for unregistered type
|
||||
if name, ok := reg.GetTypeName(&messages.Noop{}); ok || name != "" {
|
||||
if name, ok := reg.GetTypeName(&cart_messages.RemoveItem{}); ok || name != "" {
|
||||
t.Fatalf("expected GetTypeName to fail for unregistered message, got (%q,%v)", name, ok)
|
||||
}
|
||||
|
||||
@@ -66,7 +65,7 @@ func TestRegisteredMutationBasics(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("Create failed for registered mutation")
|
||||
}
|
||||
if _, isAddItem := msg.(*messages.AddItem); !isAddItem {
|
||||
if _, isAddItem := msg.(*cart_messages.AddItem); !isAddItem {
|
||||
t.Fatalf("Create returned wrong concrete type: %T", msg)
|
||||
}
|
||||
|
||||
@@ -77,7 +76,7 @@ func TestRegisteredMutationBasics(t *testing.T) {
|
||||
|
||||
// Apply happy path
|
||||
state := &cartState{}
|
||||
add := &messages.AddItem{ItemId: 42, Quantity: 3, Sku: "ABC"}
|
||||
add := &cart_messages.AddItem{ItemId: 42, Quantity: 3, Sku: "ABC"}
|
||||
if _, err := reg.Apply(context.Background(), state, add); err != nil {
|
||||
t.Fatalf("Apply returned error: %v", err)
|
||||
}
|
||||
@@ -99,7 +98,7 @@ func TestRegisteredMutationBasics(t *testing.T) {
|
||||
}
|
||||
|
||||
// Apply unregistered message
|
||||
_, err := reg.Apply(context.Background(), state, &messages.Noop{})
|
||||
_, err := reg.Apply(context.Background(), state, &cart_messages.RemoveItem{})
|
||||
if err != ErrMutationNotRegistered {
|
||||
t.Fatalf("expected ErrMutationNotRegistered, got %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user