diff --git a/cart-grain.go b/cart-grain.go index 0a218ae..722afdf 100644 --- a/cart-grain.go +++ b/cart-grain.go @@ -1,98 +1,16 @@ package main import ( - "bufio" - "bytes" - "encoding/binary" "encoding/json" "fmt" - "io" "log" "net/http" "time" "git.tornberg.me/go-cart-actor/git.tornberg.me/go-cart-actor/messages" "github.com/matst80/slask-finder/pkg/index" - "google.golang.org/protobuf/proto" ) -type StorableMessage interface { - GetBytes() ([]byte, error) - FromReader(io.Reader, *Message) error -} - -type Message struct { - Type uint64 - TimeStamp *int64 - Content interface{} -} - -func (m Message) GetBytes() ([]byte, error) { - var b bytes.Buffer - var err error - w := bufio.NewWriter(&b) - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, m.Type) - w.Write(bytes) - binary.LittleEndian.PutUint64(bytes, uint64(*m.TimeStamp)) - w.Write(bytes) - var messageBytes []byte - if m.Type == 1 { - messageBytes, err = proto.Marshal(m.Content.(*messages.AddRequest)) - } else if m.Type == 2 { - messageBytes, err = proto.Marshal(m.Content.(*messages.AddItem)) - } else { - return nil, fmt.Errorf("unknown message type") - } - if err != nil { - return nil, err - } - binary.LittleEndian.PutUint64(bytes, uint64(len(messageBytes))) - w.Write(bytes) - w.Write(messageBytes) - w.Flush() - return b.Bytes(), nil -} - -func (i Message) FromReader(reader io.Reader, m *Message) error { - - bytes := make([]byte, 8) - if _, err := reader.Read(bytes); err != nil { - return err - } - m.Type = binary.LittleEndian.Uint64(bytes) - if _, err := reader.Read(bytes); err != nil { - return err - } - timestamp := int64(binary.LittleEndian.Uint64(bytes)) - m.TimeStamp = ×tamp - if _, err := reader.Read(bytes); err != nil { - return err - } - messageBytes := make([]byte, binary.LittleEndian.Uint64(bytes)) - if _, err := reader.Read(messageBytes); err != nil { - return err - } - var err error - - if m.Type == 1 { - msg := &messages.AddRequest{} - err = proto.Unmarshal(messageBytes, msg) - m.Content = msg - } else if m.Type == 2 { - msg := &messages.AddItem{} - err = proto.Unmarshal(messageBytes, msg) - m.Content = msg - } else { - return fmt.Errorf("unknown message type") - } - if err != nil { - return err - } - - return nil -} - type CartItem struct { Sku string `json:"sku"` Name string `json:"name"` @@ -191,14 +109,14 @@ func (c *CartGrain) HandleMessage(message *Message, isReplay bool, reply *CartGr } var err error switch message.Type { - case 1: + case AddRequestType: msg, ok := message.Content.(*messages.AddRequest) if !ok { err = fmt.Errorf("invalid content type") } else { return c.AddItem(msg.Sku, reply) } - case 2: + case AddItemType: msg, ok := message.Content.(*messages.AddItem) if !ok { err = fmt.Errorf("invalid content type") diff --git a/git.tornberg.me/go-cart-actor/add.pb.go b/git.tornberg.me/go-cart-actor/add.pb.go deleted file mode 100644 index 0211997..0000000 --- a/git.tornberg.me/go-cart-actor/add.pb.go +++ /dev/null @@ -1,212 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.2 -// source: add.proto - -package go_cart_actor - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type AddRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Sku string `protobuf:"bytes,2,opt,name=Sku,proto3" json:"Sku,omitempty"` -} - -func (x *AddRequest) Reset() { - *x = AddRequest{} - mi := &file_add_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AddRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddRequest) ProtoMessage() {} - -func (x *AddRequest) ProtoReflect() protoreflect.Message { - mi := &file_add_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddRequest.ProtoReflect.Descriptor instead. -func (*AddRequest) Descriptor() ([]byte, []int) { - return file_add_proto_rawDescGZIP(), []int{0} -} - -func (x *AddRequest) GetSku() string { - if x != nil { - return x.Sku - } - return "" -} - -type AddItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Quantity int32 `protobuf:"varint,2,opt,name=Quantity,proto3" json:"Quantity,omitempty"` - Price int64 `protobuf:"varint,3,opt,name=Price,proto3" json:"Price,omitempty"` - Sku string `protobuf:"bytes,4,opt,name=Sku,proto3" json:"Sku,omitempty"` - Name string `protobuf:"bytes,5,opt,name=Name,proto3" json:"Name,omitempty"` - Image string `protobuf:"bytes,6,opt,name=Image,proto3" json:"Image,omitempty"` -} - -func (x *AddItem) Reset() { - *x = AddItem{} - mi := &file_add_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AddItem) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddItem) ProtoMessage() {} - -func (x *AddItem) ProtoReflect() protoreflect.Message { - mi := &file_add_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddItem.ProtoReflect.Descriptor instead. -func (*AddItem) Descriptor() ([]byte, []int) { - return file_add_proto_rawDescGZIP(), []int{1} -} - -func (x *AddItem) GetQuantity() int32 { - if x != nil { - return x.Quantity - } - return 0 -} - -func (x *AddItem) GetPrice() int64 { - if x != nil { - return x.Price - } - return 0 -} - -func (x *AddItem) GetSku() string { - if x != nil { - return x.Sku - } - return "" -} - -func (x *AddItem) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *AddItem) GetImage() string { - if x != nil { - return x.Image - } - return "" -} - -var File_add_proto protoreflect.FileDescriptor - -var file_add_proto_rawDesc = []byte{ - 0x0a, 0x09, 0x61, 0x64, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x6b, 0x75, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x53, 0x6b, 0x75, 0x22, 0x77, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x49, 0x74, 0x65, 0x6d, - 0x12, 0x1a, 0x0a, 0x08, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x50, 0x72, 0x69, - 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x6b, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x53, 0x6b, 0x75, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6d, 0x61, 0x67, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x1f, - 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x2e, 0x74, 0x6f, 0x72, 0x6e, 0x62, 0x65, 0x72, 0x67, 0x2e, 0x6d, - 0x65, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x61, 0x72, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_add_proto_rawDescOnce sync.Once - file_add_proto_rawDescData = file_add_proto_rawDesc -) - -func file_add_proto_rawDescGZIP() []byte { - file_add_proto_rawDescOnce.Do(func() { - file_add_proto_rawDescData = protoimpl.X.CompressGZIP(file_add_proto_rawDescData) - }) - return file_add_proto_rawDescData -} - -var file_add_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_add_proto_goTypes = []any{ - (*AddRequest)(nil), // 0: messages.AddRequest - (*AddItem)(nil), // 1: messages.AddItem -} -var file_add_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_add_proto_init() } -func file_add_proto_init() { - if File_add_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_add_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_add_proto_goTypes, - DependencyIndexes: file_add_proto_depIdxs, - MessageInfos: file_add_proto_msgTypes, - }.Build() - File_add_proto = out.File - file_add_proto_rawDesc = nil - file_add_proto_goTypes = nil - file_add_proto_depIdxs = nil -} diff --git a/main.go b/main.go index 2083dbf..040853e 100644 --- a/main.go +++ b/main.go @@ -58,7 +58,7 @@ func (a *App) HandleAddSku(w http.ResponseWriter, r *http.Request) { return } message := &Message{ - Type: 1, + Type: AddRequestType, Content: &messages.AddRequest{Sku: sku}, } var reply CartGrain diff --git a/message-types.go b/message-types.go new file mode 100644 index 0000000..9d5aac6 --- /dev/null +++ b/message-types.go @@ -0,0 +1,6 @@ +package main + +const ( + AddRequestType = 1 + AddItemType = 2 +) diff --git a/message.go b/message.go new file mode 100644 index 0000000..518f2f8 --- /dev/null +++ b/message.go @@ -0,0 +1,114 @@ +package main + +import ( + "bufio" + "bytes" + "encoding/binary" + "fmt" + "io" + + "git.tornberg.me/go-cart-actor/git.tornberg.me/go-cart-actor/messages" + "google.golang.org/protobuf/proto" +) + +type StorableMessage interface { + GetBytes() ([]byte, error) + FromReader(io.Reader, *Message) error +} + +type Message struct { + Type uint64 + TimeStamp *int64 + Content interface{} +} + +type MessageWriter struct { + writer io.Writer +} + +func NewMessageWriter(b *bytes.Buffer) *MessageWriter { + return &MessageWriter{writer: bufio.NewWriter(b)} +} + +func (w *MessageWriter) WriteUint64(value uint64) error { + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, value) + _, err := w.writer.Write(bytes) + return err +} + +func (w *MessageWriter) WriteInt64(value int64) error { + return w.WriteUint64(uint64(value)) +} + +func (w *MessageWriter) WriteMessage(m *Message) error { + if err := w.WriteUint64(m.Type); err != nil { + return err + } + if err := w.WriteInt64(*m.TimeStamp); err != nil { + return err + } + var messageBytes []byte + var err error + if m.Type == AddRequestType { + messageBytes, err = proto.Marshal(m.Content.(*messages.AddRequest)) + } else if m.Type == AddItemType { + messageBytes, err = proto.Marshal(m.Content.(*messages.AddItem)) + } else { + return fmt.Errorf("unknown message type") + } + if err != nil { + return err + } + if err := w.WriteUint64(uint64(len(messageBytes))); err != nil { + return err + } + _, err = w.writer.Write(messageBytes) + return err +} + +func (m Message) GetBytes() ([]byte, error) { + var b bytes.Buffer + mw := NewMessageWriter(&b) + err := mw.WriteMessage(&m) + return b.Bytes(), err +} + +func (i Message) FromReader(reader io.Reader, m *Message) error { + + bytes := make([]byte, 8) + if _, err := reader.Read(bytes); err != nil { + return err + } + m.Type = binary.LittleEndian.Uint64(bytes) + if _, err := reader.Read(bytes); err != nil { + return err + } + timestamp := int64(binary.LittleEndian.Uint64(bytes)) + m.TimeStamp = ×tamp + if _, err := reader.Read(bytes); err != nil { + return err + } + messageBytes := make([]byte, binary.LittleEndian.Uint64(bytes)) + if _, err := reader.Read(messageBytes); err != nil { + return err + } + var err error + + if m.Type == AddRequestType { + msg := &messages.AddRequest{} + err = proto.Unmarshal(messageBytes, msg) + m.Content = msg + } else if m.Type == AddItemType { + msg := &messages.AddItem{} + err = proto.Unmarshal(messageBytes, msg) + m.Content = msg + } else { + return fmt.Errorf("unknown message type") + } + if err != nil { + return err + } + + return nil +}