Implement RPC
This commit is contained in:
parent
9699582d72
commit
496d5f412f
6 changed files with 289 additions and 0 deletions
82
rpc/call.go
Normal file
82
rpc/call.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
func (s *server) Call(ctx context.Context, c *websocket.Conn, method string, params, result any) (*Response, error) {
|
||||
id := uuid.New().String()
|
||||
resp := make(chan *Response, 1)
|
||||
|
||||
var dataParams []byte
|
||||
var err error
|
||||
if params != nil {
|
||||
dataParams, err = json.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error Marshalling Params: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
rawParams := json.RawMessage(dataParams)
|
||||
|
||||
req := Request{
|
||||
ID: id,
|
||||
Method: method,
|
||||
Params: &rawParams,
|
||||
}
|
||||
|
||||
reqData, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error Marshalling Request: %w", err)
|
||||
}
|
||||
|
||||
// Add Call to Request Map
|
||||
func() {
|
||||
s.requestMutex.Lock()
|
||||
defer s.requestMutex.Unlock()
|
||||
|
||||
s.requests[id] = resp
|
||||
}()
|
||||
|
||||
// Remove Call from Request map
|
||||
defer func() {
|
||||
s.requestMutex.Lock()
|
||||
defer s.requestMutex.Unlock()
|
||||
|
||||
delete(s.requests, id)
|
||||
}()
|
||||
|
||||
// Write Request
|
||||
err = c.Write(ctx, websocket.MessageText, reqData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error Writing Request: %w", err)
|
||||
}
|
||||
|
||||
// Wait for Response, TODO add Select Timeout
|
||||
response := <-resp
|
||||
|
||||
if response.Error != nil {
|
||||
return response, fmt.Errorf("Call Error: %w", err)
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
if response.Result == nil {
|
||||
return response, fmt.Errorf("Got Empty Result")
|
||||
}
|
||||
|
||||
err = json.Unmarshal(*response.Result, &result)
|
||||
if err != nil {
|
||||
return response, fmt.Errorf("Error Parsing Result: %w", err)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// TODO Call with Multiple Response (Chunked file upload)
|
Loading…
Add table
Add a link
Reference in a new issue