more
This commit is contained in:
@@ -10,7 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type QueueEvent struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type MutationResult[V any] struct {
|
||||
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
"time"
|
||||
|
||||
messages "git.k6n.net/go-cart-actor/pkg/messages"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"go.opentelemetry.io/contrib/bridges/otelslog"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// ControlServer implements the ControlPlane gRPC services.
|
||||
@@ -142,56 +142,10 @@ func (s *ControlServer[V]) Ping(ctx context.Context, _ *messages.Empty) (*messag
|
||||
|
||||
func (s *ControlServer[V]) Apply(ctx context.Context, in *messages.ApplyRequest) (*messages.ApplyResult, error) {
|
||||
msgs := make([]proto.Message, len(in.Messages))
|
||||
for i, mut := range in.Messages {
|
||||
var msg proto.Message
|
||||
if m := mut.GetClearCart(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetAddItem(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetRemoveItem(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetChangeQuantity(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetSetDelivery(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetSetPickupPoint(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetRemoveDelivery(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetSetUserId(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetLineItemMarking(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetRemoveLineItemMarking(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetSubscriptionAdded(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetPaymentDeclined(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetConfirmationViewed(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetCreateCheckoutOrder(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetOrderCreated(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetNoop(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetInitializeCheckout(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetInventoryReserved(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetAddVoucher(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetRemoveVoucher(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetUpsertSubscriptionDetails(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetPreConditionFailed(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetAddGiftcard(); m != nil {
|
||||
msg = m
|
||||
} else if m := mut.GetRemoveGiftcard(); m != nil {
|
||||
msg = m
|
||||
for i, anyMsg := range in.Messages {
|
||||
msg, err := anyMsg.UnmarshalNew()
|
||||
if err != nil {
|
||||
return &messages.ApplyResult{Accepted: false}, fmt.Errorf("failed to unmarshal message: %w", err)
|
||||
}
|
||||
msgs[i] = msg
|
||||
}
|
||||
|
||||
104
pkg/actor/grpc_server_test.go
Normal file
104
pkg/actor/grpc_server_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package actor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.k6n.net/go-cart-actor/pkg/messages"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
)
|
||||
|
||||
// MockGrainPool for testing
|
||||
type mockGrainPool struct {
|
||||
applied []proto.Message
|
||||
}
|
||||
|
||||
func (m *mockGrainPool) Apply(ctx context.Context, id uint64, mutations ...proto.Message) (*MutationResult[*mockGrain], error) {
|
||||
m.applied = mutations
|
||||
// Simulate successful application
|
||||
return &MutationResult[*mockGrain]{
|
||||
Result: &mockGrain{},
|
||||
Mutations: []ApplyResult{
|
||||
{Error: nil}, // Assume success
|
||||
{Error: nil},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockGrainPool) Get(ctx context.Context, id uint64) (*mockGrain, error) {
|
||||
return &mockGrain{}, nil
|
||||
}
|
||||
|
||||
func (m *mockGrainPool) OwnerHost(id uint64) (Host, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m *mockGrainPool) TakeOwnership(id uint64) {}
|
||||
|
||||
func (m *mockGrainPool) Hostname() string { return "test-host" }
|
||||
|
||||
func (m *mockGrainPool) HandleOwnershipChange(host string, ids []uint64) error { return nil }
|
||||
func (m *mockGrainPool) HandleRemoteExpiry(host string, ids []uint64) error { return nil }
|
||||
func (m *mockGrainPool) Negotiate(hosts []string) {}
|
||||
func (m *mockGrainPool) GetLocalIds() []uint64 { return []uint64{} }
|
||||
func (m *mockGrainPool) RemoveHost(host string) {}
|
||||
func (m *mockGrainPool) AddRemoteHost(host string) {}
|
||||
func (m *mockGrainPool) IsHealthy() bool { return true }
|
||||
func (m *mockGrainPool) IsKnown(host string) bool { return false }
|
||||
func (m *mockGrainPool) Close() {}
|
||||
|
||||
type mockGrain struct{}
|
||||
|
||||
func TestApplyRequestWithMutations(t *testing.T) {
|
||||
// Setup mock pool
|
||||
pool := &mockGrainPool{}
|
||||
|
||||
// Create gRPC server
|
||||
server, err := NewControlServer[*mockGrain](DefaultServerConfig(), pool)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server: %v", err)
|
||||
}
|
||||
defer server.GracefulStop()
|
||||
|
||||
// Create client connection
|
||||
conn, err := grpc.Dial("localhost:1337", grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to dial: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client := 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{
|
||||
Id: 123,
|
||||
Messages: []*anypb.Any{addItemAny, removeItemAny},
|
||||
}
|
||||
|
||||
// Call Apply
|
||||
resp, err := client.Apply(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatalf("Apply failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify response
|
||||
if !resp.Accepted {
|
||||
t.Errorf("expected Accepted=true, got false")
|
||||
}
|
||||
|
||||
// Verify mutations were extracted and applied
|
||||
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 {
|
||||
t.Errorf("expected AddItem with ItemId=1, got %v", pool.applied[0])
|
||||
}
|
||||
if removeItem, ok := pool.applied[1].(*messages.RemoveItem); !ok || removeItem.Id != 1 {
|
||||
t.Errorf("expected RemoveItem with Id=1, got %v", pool.applied[1])
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type ApplyResult struct {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type SimpleGrainPool[V any] struct {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type StateStorage struct {
|
||||
|
||||
Reference in New Issue
Block a user