From 6804a92e2d15d76be3f54d25023ffd8667f4adcd Mon Sep 17 00:00:00 2001 From: Aleksander Vedvik Date: Sat, 11 Jan 2025 14:35:41 +0100 Subject: [PATCH 1/4] feat(Broadcast): required datatypes Data types, such as dtos and errors, used in the broadcast implementation --- broadcast/dtos/dtos.go | 75 ++++++++++++++++++++++++++++++++++++++ broadcast/errors/errors.go | 57 +++++++++++++++++++++++++++++ examples/go.mod | 2 +- examples/go.sum | 1 + 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 broadcast/dtos/dtos.go create mode 100644 broadcast/errors/errors.go diff --git a/broadcast/dtos/dtos.go b/broadcast/dtos/dtos.go new file mode 100644 index 00000000..bb30fac1 --- /dev/null +++ b/broadcast/dtos/dtos.go @@ -0,0 +1,75 @@ +package dtos + +import ( + "context" + "google.golang.org/protobuf/reflect/protoreflect" + "time" +) + +type Msg interface { + GetBroadcastID() uint64 + GetMethod() string + String() string +} + +type BroadcastMsg struct { + Ctx context.Context + Options BroadcastOptions + OriginAddr string + Info Info +} + +func (msg *BroadcastMsg) GetBroadcastID() uint64 { + return msg.Info.BroadcastID +} + +func (msg *BroadcastMsg) GetMethod() string { + return msg.Info.Method +} + +func (msg *BroadcastMsg) String() string { + return "broadcast" +} + +type ReplyMsg struct { + Info Info + ClientAddr string + Err error +} + +func (r *ReplyMsg) GetBroadcastID() uint64 { + return r.Info.BroadcastID +} + +func (r *ReplyMsg) GetMethod() string { + return "reply" +} + +func (r *ReplyMsg) String() string { + return "reply" +} + +type Info struct { + Message protoreflect.ProtoMessage + BroadcastID uint64 + Method string + Addr string + OriginMethod string + OriginDigest []byte + OriginSignature []byte + OriginPubKey string +} + +type Client struct { + Addr string + SendMsg func(timeout time.Duration, dto *ReplyMsg) error + Close func() error +} + +type BroadcastOptions struct { + ServerAddresses []string + AllowDuplication bool + SkipSelf bool + ProgressTo string + RelatedToReq uint64 +} diff --git a/broadcast/errors/errors.go b/broadcast/errors/errors.go new file mode 100644 index 00000000..b25967c5 --- /dev/null +++ b/broadcast/errors/errors.go @@ -0,0 +1,57 @@ +package broadcastErrors + +type BroadcastIDErr struct{} + +func (err BroadcastIDErr) Error() string { + return "wrong broadcastID" +} + +type MissingClientReqErr struct{} + +func (err MissingClientReqErr) Error() string { + return "has not received client req yet" +} + +type AlreadyProcessedErr struct{} + +func (err AlreadyProcessedErr) Error() string { + return "already processed request" +} + +type ReqFinishedErr struct{} + +func (err ReqFinishedErr) Error() string { + return "request has terminated" +} + +type ClientReqAlreadyReceivedErr struct{} + +func (err ClientReqAlreadyReceivedErr) Error() string { + return "the client req has already been received. The forward req is thus dropped." +} + +type MissingReqErr struct{} + +func (err MissingReqErr) Error() string { + return "a request has not been created yet." +} + +type OutOfOrderErr struct{} + +func (err OutOfOrderErr) Error() string { + return "the message is out of order" +} + +type ShardDownErr struct{} + +func (err ShardDownErr) Error() string { + return "the shard is down" +} + +type InvalidAddrErr struct { + Addr string +} + +func (err InvalidAddrErr) Error() string { + return "provided Addr is invalid. got: " + err.Addr +} diff --git a/examples/go.mod b/examples/go.mod index 2342412b..c2c0e059 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -6,7 +6,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/relab/gorums v0.7.0 golang.org/x/term v0.18.0 - google.golang.org/grpc v1.62.1 + google.golang.org/grpc v1.63.0 google.golang.org/protobuf v1.33.0 ) diff --git a/examples/go.sum b/examples/go.sum index 48e13940..8b52f1ee 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -22,6 +22,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= From 38a909ad0232b2809b155f99164351581a02b488 Mon Sep 17 00:00:00 2001 From: Aleksander Vedvik Date: Sat, 18 Jan 2025 13:19:25 +0100 Subject: [PATCH 2/4] refactor(Broadcast): removed unused errs and added docs --- broadcast/errors/errors.go | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/broadcast/errors/errors.go b/broadcast/errors/errors.go index b25967c5..01737489 100644 --- a/broadcast/errors/errors.go +++ b/broadcast/errors/errors.go @@ -1,53 +1,45 @@ -package broadcastErrors +package errors -type BroadcastIDErr struct{} +// IDErr should be used when a message with a BroadcastID is sent to a broadcast processor with another BroadcastID. This +// can happen if a user deliberately changes the BroadcastID of a message. +type IDErr struct{} -func (err BroadcastIDErr) Error() string { +func (err IDErr) Error() string { return "wrong broadcastID" } +// MissingClientReqErr signifies that a server tries to reply to a client, but has not yet received the original request +// form the client. This is especially important when the message does not contain routing information, such as in QuorumCalls. type MissingClientReqErr struct{} func (err MissingClientReqErr) Error() string { return "has not received client req yet" } +// AlreadyProcessedErr is used when a message is received after the broadcast processor has stopped. This means that the +// server has sent a reply to the client and thus the incoming message needs not be processed. type AlreadyProcessedErr struct{} func (err AlreadyProcessedErr) Error() string { return "already processed request" } -type ReqFinishedErr struct{} - -func (err ReqFinishedErr) Error() string { - return "request has terminated" -} - +// ClientReqAlreadyReceivedErr should be used when a duplicate client request is received. type ClientReqAlreadyReceivedErr struct{} func (err ClientReqAlreadyReceivedErr) Error() string { - return "the client req has already been received. The forward req is thus dropped." -} - -type MissingReqErr struct{} - -func (err MissingReqErr) Error() string { - return "a request has not been created yet." + return "client request already received (dropped)" } +// OutOfOrderErr should be used when the preserve ordering configuration option is used and a message is received out of +// order. type OutOfOrderErr struct{} func (err OutOfOrderErr) Error() string { return "the message is out of order" } -type ShardDownErr struct{} - -func (err ShardDownErr) Error() string { - return "the shard is down" -} - +// InvalidAddrErr should be used when an invalid server/client address is provided. type InvalidAddrErr struct { Addr string } From 45b93a31a9c11a02a3ff7f71f0ae32f64134128b Mon Sep 17 00:00:00 2001 From: Aleksander Vedvik Date: Sat, 18 Jan 2025 13:31:30 +0100 Subject: [PATCH 3/4] docs(Broadcast): documentation for broadcast dtos --- broadcast/dtos/dtos.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/broadcast/dtos/dtos.go b/broadcast/dtos/dtos.go index bb30fac1..0877c9b5 100644 --- a/broadcast/dtos/dtos.go +++ b/broadcast/dtos/dtos.go @@ -1,3 +1,4 @@ +// Package dtos implements all data transfer objects used from outside the broadcast implementation context. package dtos import ( @@ -6,15 +7,18 @@ import ( "time" ) +// Msg defines the message sent from a server to another server or client. The messages should be sent by the router. type Msg interface { GetBroadcastID() uint64 GetMethod() string String() string } +// BroadcastMsg is a data transfer object of a message received by another server or client. type BroadcastMsg struct { - Ctx context.Context - Options BroadcastOptions + Ctx context.Context + Options BroadcastOptions + // The address of the client or server that originated the broadcast request OriginAddr string Info Info } @@ -31,8 +35,10 @@ func (msg *BroadcastMsg) String() string { return "broadcast" } +// ReplyMsg is similar to BroadcastMsg, but is strictly used for replying to a client. type ReplyMsg struct { - Info Info + Info Info + // The address of the client that originated the broadcast request ClientAddr string Err error } @@ -49,6 +55,8 @@ func (r *ReplyMsg) String() string { return "reply" } +// Info contains data pertaining to the current message such as routing information, contents, and which server handler +// should receive the message. type Info struct { Message protoreflect.ProtoMessage BroadcastID uint64 @@ -60,12 +68,15 @@ type Info struct { OriginPubKey string } +// Client is a data structure used when sending a reply to a client. type Client struct { Addr string SendMsg func(timeout time.Duration, dto *ReplyMsg) error Close func() error } +// BroadcastOptions is used to configure a particular broadcast, e.g. by only broadcasting to a subset of the servers in +// a view. type BroadcastOptions struct { ServerAddresses []string AllowDuplication bool From f94e935c73e2445298a7abc4ffbc7daafae09e8f Mon Sep 17 00:00:00 2001 From: Aleksander Vedvik Date: Sat, 18 Jan 2025 13:34:44 +0100 Subject: [PATCH 4/4] refactor(Broadcast): broadcast prefix for errors --- broadcast/errors/errors.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/broadcast/errors/errors.go b/broadcast/errors/errors.go index 01737489..468d61ce 100644 --- a/broadcast/errors/errors.go +++ b/broadcast/errors/errors.go @@ -5,7 +5,7 @@ package errors type IDErr struct{} func (err IDErr) Error() string { - return "wrong broadcastID" + return "broadcast: wrong ID" } // MissingClientReqErr signifies that a server tries to reply to a client, but has not yet received the original request @@ -13,7 +13,7 @@ func (err IDErr) Error() string { type MissingClientReqErr struct{} func (err MissingClientReqErr) Error() string { - return "has not received client req yet" + return "broadcast: has not received client req yet" } // AlreadyProcessedErr is used when a message is received after the broadcast processor has stopped. This means that the @@ -21,14 +21,14 @@ func (err MissingClientReqErr) Error() string { type AlreadyProcessedErr struct{} func (err AlreadyProcessedErr) Error() string { - return "already processed request" + return "broadcast: already processed request" } // ClientReqAlreadyReceivedErr should be used when a duplicate client request is received. type ClientReqAlreadyReceivedErr struct{} func (err ClientReqAlreadyReceivedErr) Error() string { - return "client request already received (dropped)" + return "broadcast: client request already received (dropped)" } // OutOfOrderErr should be used when the preserve ordering configuration option is used and a message is received out of @@ -36,7 +36,7 @@ func (err ClientReqAlreadyReceivedErr) Error() string { type OutOfOrderErr struct{} func (err OutOfOrderErr) Error() string { - return "the message is out of order" + return "broadcast: the message is out of order" } // InvalidAddrErr should be used when an invalid server/client address is provided. @@ -45,5 +45,5 @@ type InvalidAddrErr struct { } func (err InvalidAddrErr) Error() string { - return "provided Addr is invalid. got: " + err.Addr + return "broadcast: provided Addr is invalid. got: " + err.Addr }