Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ Generated `zorums_*_gorums.pb.go` files in `cmd/protoc-gen-gorums/dev/` are outp

Never edit any generated file to satisfy a linter; fix the generator or its inputs and regenerate.

### Versions

Never bump versions on a feature branch, even for a breaking generator or runtime change.
This covers `internal/version/version.go`, `GenVersion` and `MinVersion` in `runtime/gorumsimpl/version.go`, the gorums requirement in `benchkit/go.mod` and `examples/go.mod`, and the `replace` in `go.work`.
`gorums-release prepare` changes all of them together at release time; a partial bump breaks the nested modules.
Instead, state in the PR description which flag the next release needs:

- `-bump-gen`: the generated code needs a new runtime feature.
- `-bump-min`: code generated by an earlier release no longer compiles against the runtime.

## Tests

Follow TDD: write a failing test, watch it fail, make it pass, refactor.
Expand Down
19 changes: 6 additions & 13 deletions benchkit/benchmark/benchmark_gorums.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions benchkit/benchmark/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/relab/gorums"
"github.com/relab/gorums/benchkit"
"github.com/relab/gorums/gorumstest"
proto "google.golang.org/protobuf/proto"
)

func TestDescriptions(t *testing.T) {
Expand Down Expand Up @@ -249,7 +250,7 @@ func TestRunAsyncQCBenchmarkRejectsRateRamp(t *testing.T) {
// to registerReplyDroppingPeer's silent drop, which instead times out). Call
// before serving srv, since it registers a service.
func registerFailingQuorumCallPeer(srv *gorums.Server, errMsg string) {
srv.RegisterHandler("benchmark.Benchmark.QuorumCall", func(_ gorums.ServerContext, _ *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler("benchmark.Benchmark.QuorumCall", func(_ gorums.ServerContext, _ *gorums.Message, _ func(proto.Message)) (proto.Message, error) {
return nil, errors.New(errMsg)
})
}
Expand Down Expand Up @@ -645,11 +646,11 @@ func TestServerMeasuredVerify(t *testing.T) {
// leak deterministically detectable.
func TestServerMeasuredWindowExcludesClockSync(t *testing.T) {
const clockSyncDelay = 2 * time.Millisecond
delayClockSync := func(ctx gorums.ServerContext, in *gorums.Message, next gorums.Handler) (*gorums.Message, error) {
delayClockSync := func(ctx gorums.ServerContext, in *gorums.Message, send func(proto.Message), next gorums.Handler) (proto.Message, error) {
if in.GetMethod() == "benchkit.Control.ClockSync" {
time.Sleep(clockSyncDelay)
}
return next(ctx, in)
return next(ctx, in, send)
}
target := symmetricServers(t, 3, gorums.WithServerInterceptors(delayClockSync))

Expand Down
5 changes: 3 additions & 2 deletions benchkit/benchmark/symmetric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/relab/gorums"
"github.com/relab/gorums/benchkit"
"github.com/relab/gorums/gorumstest"
proto "google.golang.org/protobuf/proto"
)

// captureDiag redirects the probe-stall self-diagnosis to a buffer for the
Expand Down Expand Up @@ -124,11 +125,11 @@ func symmetricServers(t *testing.T, n int, serverOpts ...gorums.ServerOption) *S
func registerReplyDroppingPeer(srv *gorums.Server, drop int64) {
var remaining atomic.Int64
remaining.Store(drop)
srv.RegisterHandler("benchmark.Benchmark.QuorumCall", func(_ gorums.ServerContext, in *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler("benchmark.Benchmark.QuorumCall", func(_ gorums.ServerContext, in *gorums.Message, _ func(proto.Message)) (proto.Message, error) {
if remaining.Add(-1) >= 0 {
return nil, nil // no response and no error: nothing is sent back
}
return gorums.NewResponseMessage(in, gorums.AsProto[*Echo](in)), nil
return gorums.AsProto[*Echo](in), nil
})
}

Expand Down
27 changes: 8 additions & 19 deletions benchkit/control_gorums.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions call_async_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/relab/gorums/gorumstest"
"github.com/relab/gorums/internal/testutils/mock"
"github.com/relab/gorums/internal/testutils/mockcall"
"google.golang.org/protobuf/proto"
pb "google.golang.org/protobuf/types/known/wrapperspb"
)

Expand Down Expand Up @@ -180,9 +181,9 @@ func TestCallAsyncSendsBeforeReturn(t *testing.T) {
config := gorumstest.Config(t, numNodes, func(int) gorumstest.ServerIface {
srv := gorums.NewServer()
echo := gorumstest.EchoHandler("echo")
srv.RegisterHandler(mock.TestMethod, func(ctx gorums.ServerContext, in *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler(mock.TestMethod, func(ctx gorums.ServerContext, in *gorums.Message, send func(proto.Message)) (proto.Message, error) {
received <- struct{}{}
return echo(ctx, in)
return echo(ctx, in, send)
})
return srv
})
Expand Down
9 changes: 5 additions & 4 deletions call_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
pb "google.golang.org/protobuf/types/known/wrapperspb"
)

Expand All @@ -28,7 +29,7 @@ import (
func TestOnewayNoResourceLeak(t *testing.T) {
servers := gorumstest.LocalServers(t, 3)
for _, srv := range servers {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message, _ func(proto.Message)) (proto.Message, error) {
return nil, nil
})
}
Expand Down Expand Up @@ -62,7 +63,7 @@ func TestOnewayDroppedHandleDoesNotDispatch(t *testing.T) {
var received atomic.Int32
servers := gorumstest.LocalServers(t, 3)
for _, srv := range servers {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message, _ func(proto.Message)) (proto.Message, error) {
received.Add(1)
return nil, nil
})
Expand All @@ -86,7 +87,7 @@ func TestOnewayDroppedHandleDoesNotDispatch(t *testing.T) {
func TestOnewayCallDoubleDispatchPanics(t *testing.T) {
servers := gorumstest.LocalServers(t, 3)
for _, srv := range servers {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message, _ func(proto.Message)) (proto.Message, error) {
return nil, nil
})
}
Expand Down Expand Up @@ -137,7 +138,7 @@ func TestOnewayCallAsync(t *testing.T) {
var received atomic.Int32
servers := gorumstest.LocalServers(t, 3)
for _, srv := range servers {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message) (*gorums.Message, error) {
srv.RegisterHandler(mock.TestMethod, func(_ gorums.ServerContext, _ *gorums.Message, _ func(proto.Message)) (proto.Message, error) {
received.Add(1)
return nil, nil
})
Expand Down
56 changes: 19 additions & 37 deletions cmd/protoc-gen-gorums/dev/zorums_server_gorums.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cmd/protoc-gen-gorums/gengorums/template_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var importMap = map[string]protogen.GoImportPath{
"context": protogen.GoImportPath("context"),
"gorums": protogen.GoImportPath("github.com/relab/gorums"),
"gorumsimpl": protogen.GoImportPath("github.com/relab/gorums/runtime/gorumsimpl"),
"proto": protogen.GoImportPath("google.golang.org/protobuf/proto"),
}

func addImport(path, ident string, g *protogen.GeneratedFile) string {
Expand Down
17 changes: 6 additions & 11 deletions cmd/protoc-gen-gorums/gengorums/template_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,33 +73,28 @@ var serverInterface = `
var registerInterface = `
{{$genFile := .GenFile}}
{{$gorumsMessage := use "gorums.Message" .GenFile}}
{{$protoMessage := use "proto.Message" .GenFile}}
{{$asProto := use "gorums.AsProto" .GenFile}}
{{$newMessage := use "gorums.NewResponseMessage" $genFile}}
{{$gorumsServer := use "gorums.Server" $genFile}}
{{range .Services -}}
{{$names := .Names}}
{{$reg := localNames "srv impl" $context $gorumsMessage $asProto $newMessage (methodTypes $genFile .Service)}}
{{$reg := localNames "srv impl" $context $gorumsMessage $protoMessage $asProto (methodTypes $genFile .Service)}}

func {{$names.Register}}({{$reg.srv}} *{{$gorumsServer}}, {{$reg.impl}} {{$names.Interface}}) {
{{- range .Service.Methods}}
{{- $local := localNames "ctx in req resp err out" $context $gorumsMessage $asProto $newMessage (in $genFile .) (out $genFile .) $reg.impl}}
{{$reg.srv}}.RegisterHandler("{{.Desc.FullName}}", func({{$local.ctx}} {{$context}}, {{$local.in}} *{{$gorumsMessage}}) (*{{$gorumsMessage}}, error) {
{{- $local := localNames "ctx in req resp send" $context $gorumsMessage $protoMessage $asProto (in $genFile .) (out $genFile .) $reg.impl}}
{{$reg.srv}}.RegisterHandler("{{.Desc.FullName}}", func({{$local.ctx}} {{$context}}, {{$local.in}} *{{$gorumsMessage}}, {{if isStreamingServer .}}{{$local.send}}{{else}}_{{end}} func({{$protoMessage}})) ({{$protoMessage}}, error) {
{{$local.req}} := {{$asProto}}[*{{in $genFile .}}]({{$local.in}})
{{- if isOneway .}}
{{$reg.impl}}.{{.GoName}}({{$local.ctx}}, {{$local.req}})
return nil, nil
{{- else if isStreamingServer .}}
{{$reg.impl}}.{{.GoName}}({{$local.ctx}}, {{$local.req}}, func({{$local.resp}} *{{out $genFile .}}) {
{{$local.out}} := {{$newMessage}}({{$local.in}}, {{$local.resp}})
{{$local.ctx}}.SendMessage({{$local.out}})
{{$local.send}}({{$local.resp}})
})
return nil, nil
{{- else }}
{{$local.resp}}, {{$local.err}} := {{$reg.impl}}.{{.GoName}}({{$local.ctx}}, {{$local.req}})
if {{$local.err}} != nil {
return nil, {{$local.err}}
}
return {{$newMessage}}({{$local.in}}, {{$local.resp}}), nil
return {{$reg.impl}}.{{.GoName}}({{$local.ctx}}, {{$local.req}})
{{- end}}
})
{{- end}}
Expand Down
Loading
Loading