From a008ef47c7334cb7de789fbfc50c56c70d2c1a7f Mon Sep 17 00:00:00 2001
From: a <a@tuxpa.in>
Date: Fri, 17 Feb 2023 00:55:47 -0600
Subject: [PATCH] create interface :O

---
 client.go     | 25 +++++++++----------------
 conn.go       | 13 +++++++++++++
 helper.go     |  6 ++++--
 json_codec.go | 10 +++++-----
 4 files changed, 31 insertions(+), 23 deletions(-)
 create mode 100644 conn.go

diff --git a/client.go b/client.go
index 27d78a3..8fa8446 100644
--- a/client.go
+++ b/client.go
@@ -57,6 +57,8 @@ type BatchElem struct {
 	Error error
 }
 
+var _ SubscriptionConn = (*Client)(nil)
+
 // Client represents a connection to an RPC server.
 type Client struct {
 	isHTTP bool // connection type: http, ws or ipc
@@ -295,11 +297,11 @@ func (c *Client) call(ctx context.Context, result any, msg *jsonrpcMessage) erro
 //
 // The result must be a pointer so that package json can unmarshal into it. You
 // can also pass nil, in which case the result is ignored.
-func (c *Client) Do(result any, method string, param any) error {
-	ctx := context.Background()
+func (c *Client) Do(ctx context.Context, result any, method string, param any) error {
 	return c.DoContext(ctx, result, method, param)
 }
 
+// DEPRECATED: use Do
 func (c *Client) DoContext(ctx context.Context, result any, method string, param any) error {
 	if result != nil && reflect.TypeOf(result).Kind() != reflect.Ptr {
 		return fmt.Errorf("call result parameter must be pointer or nil interface: %v", result)
@@ -312,11 +314,11 @@ func (c *Client) DoContext(ctx context.Context, result any, method string, param
 }
 
 // Call calls Do, except accepts variadic parameters
-func (c *Client) Call(result any, method string, args ...any) error {
-	return c.Do(result, method, args)
+func (c *Client) Call(ctx context.Context, result any, method string, args ...any) error {
+	return c.Do(ctx, result, method, args)
 }
 
-// CallContext calls DoContext, except accepts variadic parameters
+// DEPRECATED: use Call
 func (c *Client) CallContext(ctx context.Context, result any, method string, args ...any) error {
 	return c.DoContext(ctx, result, method, args)
 }
@@ -328,20 +330,11 @@ func (c *Client) CallContext(ctx context.Context, result any, method string, arg
 // a request is reported through the Error field of the corresponding BatchElem.
 //
 // Note that batch calls may not be executed atomically on the server side.
-func (c *Client) BatchCall(b []BatchElem) error {
-	ctx := context.Background()
+func (c *Client) BatchCall(ctx context.Context, b ...BatchElem) error {
 	return c.BatchCallContext(ctx, b)
 }
 
-// BatchCallContext sends all given requests as a single batch and waits for the server
-// to return a response for all of them. The wait duration is bounded by the
-// context's deadline.
-//
-// In contrast to CallContext, BatchCallContext only returns errors that have occurred
-// while sending the request. Any error specific to a request is reported through the
-// Error field of the corresponding BatchElem.
-//
-// Note that batch calls may not be executed atomically on the server side.
+// DEPRECATED: use BatchCall
 func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
 	var (
 		msgs = make([]*jsonrpcMessage, len(b))
diff --git a/conn.go b/conn.go
new file mode 100644
index 0000000..9e7b9a3
--- /dev/null
+++ b/conn.go
@@ -0,0 +1,13 @@
+package jrpc
+
+import "context"
+
+type Conn interface {
+	Do(ctx context.Context, result any, method string, params any) error
+	BatchCall(b ...BatchElem) error
+}
+
+type SubscriptionConn interface {
+	Notify(ctx context.Context, method string, args ...any) error
+	Subscribe(ctx context.Context, namespace string, channel any, args ...any) (*ClientSubscription, error)
+}
diff --git a/helper.go b/helper.go
index 02e123e..04fa2b7 100644
--- a/helper.go
+++ b/helper.go
@@ -1,8 +1,10 @@
 package jrpc
 
-func Do[T any](c *Client, method string, args any) (T, error) {
+import "context"
+
+func Do[T any](ctx context.Context, c Conn, method string, args any) (T, error) {
 	var t T
-	err := c.Do(t, method, args)
+	err := c.Do(ctx, t, method, args)
 	if err != nil {
 		return t, err
 	}
diff --git a/json_codec.go b/json_codec.go
index 1c4fda4..c9666a9 100644
--- a/json_codec.go
+++ b/json_codec.go
@@ -9,8 +9,8 @@ import (
 	"time"
 )
 
-// Conn is a subset of the methods of net.Conn which are sufficient for creating a jsonCodec
-type Conn interface {
+// DeadlineConn is a subset of the methods of net.Conn which are sufficient for creating a jsonCodec
+type DeadlineConn interface {
 	io.ReadWriteCloser
 	SetWriteDeadline(time.Time) error
 }
@@ -25,14 +25,14 @@ type jsonCodec struct {
 	decode    func(v any) error // decoder to allow multiple transports
 	encMu     sync.Mutex        // guards the encoder
 	encode    func(v any) error // encoder to allow multiple transports
-	conn      Conn
+	conn      DeadlineConn
 }
 
 // NewFuncCodec creates a codec which uses the given functions to read and write. If conn
 // implements ConnRemoteAddr, log messages will use it to include the remote address of
 // the connection.
 func NewFuncCodec(
-	conn Conn,
+	conn DeadlineConn,
 	encode, decode func(v any) error,
 	closeFunc func() error,
 ) ServerCodec {
@@ -51,7 +51,7 @@ func NewFuncCodec(
 
 // NewCodec creates a codec on the given connection. If conn implements ConnRemoteAddr, log
 // messages will use it to include the remote address of the connection.
-func NewCodec(conn Conn) ServerCodec {
+func NewCodec(conn DeadlineConn) ServerCodec {
 	encr := func(v any) error {
 		enc := jzon.BorrowStream(conn)
 		defer jzon.ReturnStream(enc)
-- 
GitLab