diff --git a/client_test.go b/client_test.go index 0b9de81..a9e4f8c 100644 --- a/client_test.go +++ b/client_test.go @@ -64,11 +64,13 @@ func TestStartFailed(t *testing.T) { c.Assert(client.Close(), qt.IsNil) } +const clientVersion = 3 + func newTestClientForServer(t testing.TB, server string, codec codecs.Codec, cfg model.ExampleConfig, env ...string) *execrpc.Client[model.ExampleConfig, model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt] { client, err := execrpc.StartClient( execrpc.ClientOptions[model.ExampleConfig, model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt]{ ClientRawOptions: execrpc.ClientRawOptions{ - Version: 1, + Version: clientVersion, Cmd: "go", Dir: "./examples/servers/" + server, Args: []string{"run", "."}, @@ -224,7 +226,7 @@ func TestTyped(t *testing.T) { client, err := execrpc.StartClient( execrpc.ClientOptions[model.ExampleConfig, model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt]{ ClientRawOptions: execrpc.ClientRawOptions{ - Version: 1, + Version: clientVersion, Cmd: "go", Dir: "./examples/servers/typed", Args: []string{"run", "."}, diff --git a/examples/servers/readmeexample/main.go b/examples/servers/readmeexample/main.go index a315ebf..01651e2 100644 --- a/examples/servers/readmeexample/main.go +++ b/examples/servers/readmeexample/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "hash" "hash/fnv" "log" @@ -29,7 +30,10 @@ func main() { // Optional function to initialize the server // with the client configuration. // This will be called once on server start. - Init: func(cfg model.ExampleConfig) error { + Init: func(cfg model.ExampleConfig, procol execrpc.ProtocolInfo) error { + if procol.Version != 3 { + return fmt.Errorf("unsupported protocol version: %d", procol.Version) + } clientConfig = cfg return clientConfig.Init() }, diff --git a/examples/servers/typed/main.go b/examples/servers/typed/main.go index b243861..d6e54b7 100644 --- a/examples/servers/typed/main.go +++ b/examples/servers/typed/main.go @@ -43,7 +43,10 @@ func main() { execrpc.ServerOptions[model.ExampleConfig, model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt]{ GetHasher: getHasher, DelayDelivery: delayDelivery, - Init: func(cfg model.ExampleConfig) error { + Init: func(cfg model.ExampleConfig, protocol execrpc.ProtocolInfo) error { + if protocol.Version != 3 { + return fmt.Errorf("unsupported protocol version: %d", protocol.Version) + } clientConfig = cfg return clientConfig.Init() }, diff --git a/server.go b/server.go index 8dc1626..a6e4007 100644 --- a/server.go +++ b/server.go @@ -76,7 +76,10 @@ func NewServer[C, Q, M, R any](opts ServerOptions[C, Q, M, R]) (*Server[C, Q, M, return nil } - var cfg C + var ( + cfg C + protocolInfo = ProtocolInfo{Version: message.Header.Version} + ) err := opts.Codec.Decode(message.Body, &cfg) if err != nil { m := createErrorMessage(err, message.Header, MessageStatusErrDecodeFailed) @@ -84,7 +87,7 @@ func NewServer[C, Q, M, R any](opts ServerOptions[C, Q, M, R]) (*Server[C, Q, M, return nil } - if err := opts.Init(cfg); err != nil { + if err := opts.Init(cfg, protocolInfo); err != nil { m := createErrorMessage(err, message.Header, MessageStatusErrInitServerFailed) d.SendMessage(m) return nil @@ -259,12 +262,20 @@ func createErrorMessage(err error, h Header, failureStatus uint16) Message { return m } +// ProtocolInfo is the protocol information passed to the server's Init function. +type ProtocolInfo struct { + // The version passed down from the client. + // This usually represents a major version, + // so any increment should be considered a breaking change. + Version uint16 `json:"version"` +} + // ServerOptions is the options for a server. type ServerOptions[C, Q, M, R any] struct { // Init is the function that will be called when the server is started. // It can be used to initialize the server with the given configuration. // If an error is returned, the server will stop. - Init func(C) error + Init func(C, ProtocolInfo) error // Handle is the function that will be called when a request is received. Handle func(*Call[Q, M, R])