From 82b5150a65dc4a1035ee0c7d3fed3c892decd745 Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Wed, 15 Mar 2023 15:21:25 -0700 Subject: [PATCH] Clean up the rpc.serverInfo implementation. - Remove the RPCServerInfo client helper, it was unused outside tests. - Remove the methodFunc wrapper type, it is no longer necessary. - Fix up tests. Updates #46. --- internal_test.go | 10 +++++----- jrpc2_test.go | 6 +++--- server.go | 18 +++++++++++++++++- server/local_test.go | 4 ++-- special.go | 40 ---------------------------------------- 5 files changed, 27 insertions(+), 51 deletions(-) delete mode 100644 special.go diff --git a/internal_test.go b/internal_test.go index 1193db3..a306182 100644 --- a/internal_test.go +++ b/internal_test.go @@ -167,7 +167,7 @@ func TestClient_contextCancellation(t *testing.T) { stopped := make(chan struct{}) cpipe, spipe := channel.Direct() srv := NewServer(hmap{ - "Hang": methodFunc(func(ctx context.Context, _ *Request) (any, error) { + "Hang": Handler(func(ctx context.Context, _ *Request) (any, error) { close(started) // signal that the method handler is running select { case <-stopped: @@ -219,10 +219,10 @@ func TestServer_specialMethods(t *testing.T) { defer leaktest.Check(t)() s := NewServer(hmap{ - "rpc.nonesuch": methodFunc(func(context.Context, *Request) (any, error) { + "rpc.nonesuch": Handler(func(context.Context, *Request) (any, error) { return "OK", nil }), - "donkeybait": methodFunc(func(context.Context, *Request) (any, error) { + "donkeybait": Handler(func(context.Context, *Request) (any, error) { return true, nil }), }, nil) @@ -243,7 +243,7 @@ func TestServer_disableBuiltinHook(t *testing.T) { defer leaktest.Check(t)() s := NewServer(hmap{ - "rpc.nonesuch": methodFunc(func(context.Context, *Request) (any, error) { + "rpc.nonesuch": Handler(func(context.Context, *Request) (any, error) { return "OK", nil }), }, &ServerOptions{DisableBuiltin: true}) @@ -270,7 +270,7 @@ func TestBatchReply(t *testing.T) { cpipe, spipe := channel.Direct() srv := NewServer(hmap{ - "test": methodFunc(func(_ context.Context, req *Request) (any, error) { + "test": Handler(func(_ context.Context, req *Request) (any, error) { return req.Method() + " OK", nil }), }, nil).Start(spipe) diff --git a/jrpc2_test.go b/jrpc2_test.go index 5317c04..3c65355 100644 --- a/jrpc2_test.go +++ b/jrpc2_test.go @@ -1081,9 +1081,9 @@ func TestRPCServerInfo(t *testing.T) { loc := server.NewLocal(handler.Map{"Test": testOK}, nil) defer loc.Close() - si, err := jrpc2.RPCServerInfo(context.Background(), loc.Client) - if err != nil { - t.Errorf("RPCServerInfo failed: %v", err) + var si jrpc2.ServerInfo + if err := loc.Client.CallResult(context.Background(), "rpc.serverInfo", nil, &si); err != nil { + t.Errorf("rpc.serverInfo call failed: %v", err) } { got, want := si.Methods, []string{"Test"} diff --git a/server.go b/server.go index bb7adfb..892a46a 100644 --- a/server.go +++ b/server.go @@ -19,6 +19,10 @@ import ( "golang.org/x/sync/semaphore" ) +const ( + rpcServerInfo = "rpc.serverInfo" +) + var ( serverMetrics = new(expvar.Map) @@ -714,7 +718,9 @@ func (s *Server) assign(ctx context.Context, name string) Handler { if s.builtin && strings.HasPrefix(name, "rpc.") { switch name { case rpcServerInfo: - return methodFunc(s.handleRPCServerInfo) + return func(context.Context, *Request) (any, error) { + return s.ServerInfo(), nil + } default: return nil // reserved } @@ -827,3 +833,13 @@ func (ts tasks) numToDo() (todo, notes int) { } return } + +// CancelRequest instructs s to cancel the pending or in-flight request with +// the specified ID. If no request exists with that ID, this is a no-op. +func (s *Server) CancelRequest(id string) { + s.mu.Lock() + defer s.mu.Unlock() + if s.cancel(id) { + s.log("Cancelled request %s by client order", id) + } +} diff --git a/server/local_test.go b/server/local_test.go index ee07745..6a548fd 100644 --- a/server/local_test.go +++ b/server/local_test.go @@ -31,8 +31,8 @@ func TestLocal(t *testing.T) { loc := server.NewLocal(make(handler.Map), testOpts(t)) ctx := context.Background() - si, err := jrpc2.RPCServerInfo(ctx, loc.Client) - if err != nil { + var si jrpc2.ServerInfo + if err := loc.Client.CallResult(ctx, "rpc.serverInfo", nil, &si); err != nil { t.Fatalf("rpc.serverInfo failed: %v", err) } diff --git a/special.go b/special.go deleted file mode 100644 index abf731c..0000000 --- a/special.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2017 Michael J. Fromberger. All Rights Reserved. - -package jrpc2 - -import ( - "context" -) - -const ( - rpcServerInfo = "rpc.serverInfo" -) - -// CancelRequest instructs s to cancel the pending or in-flight request with -// the specified ID. If no request exists with that ID, this is a no-op. -func (s *Server) CancelRequest(id string) { - s.mu.Lock() - defer s.mu.Unlock() - if s.cancel(id) { - s.log("Cancelled request %s by client order", id) - } -} - -// methodFunc is a replication of handler.Func redeclared to avert a cycle. -type methodFunc func(context.Context, *Request) (any, error) - -func (m methodFunc) Handle(ctx context.Context, req *Request) (any, error) { - return m(ctx, req) -} - -// Handle the special rpc.serverInfo method, that requests server vitals. -func (s *Server) handleRPCServerInfo(context.Context, *Request) (any, error) { - return s.ServerInfo(), nil -} - -// RPCServerInfo calls the built-in rpc.serverInfo method exported by servers. -// It is a convenience wrapper for an invocation of cli.CallResult. -func RPCServerInfo(ctx context.Context, cli *Client) (result *ServerInfo, err error) { - err = cli.CallResult(ctx, rpcServerInfo, nil, &result) - return -}