RPC
RPC stands for Remote Procedure Calls, and allows for external Go microservices to call functions in our application directly.
Listener
To do this, you need to define a RPCServer dummy type, and payload to receive, and a function that gets a pointer to a response string and returns an error.
go
type RPCServer struct{}
type RPCPayload struct {
Name string
Data string
}
func (r *RPCServer) LogInfo(payload RPCPayload, resp *string) error {
collection := client.Database("logs").Collection("logs")
_, err := collection.InsertOne(context.TODO(), data.LogEntry{
Name: payload.Name,
Data: payload.Data,
})
if err != nil {
log.Println("error writing to mongo ", err)
return err
}
*resp = "processed payload via RPC: " + payload.Name
return nil
}
To instantiate the RPCServer, use the below syntax in your main application file. Basically you define a function that creates the connection and listens on a port. Then, you register your RPC handler type and serve the RPC server.
go
func (app *Config) rpcListen() error {
log.Println("Starting RPC server on port " + RPC_PORT)
listen, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%s", RPC_PORT))
if err != nil {
return err
}
defer listen.Close()
for {
rpcConn, err := listen.Accept()
if err != nil {
log.Println("Error accepting connection: ", err)
continue
}
go rpc.ServeConn(rpcConn)
}
}
// in function where you start your app...
err = rpc.Register(new(RPCServer))
go app.rpcListen()
Sender
To send messages via RPC, you need to create a type for the payload that exactly matches that of the receiver.
go
type RPCPayload struct {
Name string
Data string
}
func (app *Config) logItemViaRPC(r http.ResponseWriter, l LogPayload) {
client, err := rpc.Dial("tcp", "logger:5001")
if err != nil {
app.errorJSON(r, err)
return
}
payload := RPCPayload{
Name: l.Name,
Data: l.Data,
}
var resp string
err = client.Call("RPCServer.LogInfo", payload, &resp)
if err != nil {
app.errorJSON(r, err)
return
}
returnPayload := jsonResponse{
Error: false,
Message: resp,
}
app.writeJSON(r, http.StatusAccepted, returnPayload)
}