How to put mongodb sessions in creachadair/jrpc2 Handlers


I want to build a microservice that uses jrpc2 and mongodb to manage small IoT devices. These are the libraries in question:

The problem is, being rather new to Golang in general, I'm not sure how to combine these things together. Here's the code I have:

func DeviceAdd(ctx context.Context) (map[string]string, error) {
    m := make(map[string]string)
    m["token"] = "0xdeadbeef"
    return m, nil

func DeviceBootstrap(ctx context.Context, params map[string]string) (map[string]string, error) {
    m := make(map[string]string)
    m["entered_token"] = params["token"]
    return m, nil
func NewServer() *jrpc2.Server {
    assigner := jrpc2.MapAssigner{
        "device_add":        jrpc2.NewHandler(DeviceAdd),
        "device_bootstrap":  jrpc2.NewHandler(DeviceBootstrap),
        "device_update":     jrpc2.NewHandler(DeviceUpdate),
        "device_get_status": jrpc2.NewHandler(DeviceGetStatus),
    srv := jrpc2.NewServer(assigner, nil)
    return srv

Basically, you write some basic functions that accept a context.Context or any other JSON-RPC params, and jrpc2.NewHandler(function) will attach them to the jrpc2.Server.

The problem is, I cannot change the function handler signatures to put a mgo.Session in there. Or should I make DeviceAdd/DeviceBootstrap methods of a struct, which has access to a mgo.Session?

According to another StackOverflow question, it seems I should make DeviceAdd/DeviceBootstrap methods of a struct that has an mgo.Session, but I'm really not sure if I understood it correctly, or if jrpc2.NewHandler will accept the newly converted methods, or if it's the right thing to do. Also, Golang's context.Context seems like the right place to put such a thing. Help!


1 Answer


A request can be handled by any value that implements the jrpc2.Handler interface. Perhaps the simplest way to adapt an mgo.Session to this interface would be to wrap it in a struct, e.g.,

type SessionHandler struct {

func (s SessionHandler) Handle(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
   // whatever you want your handler to do, using the s.Session
   // as a delegate.

Then you can write something like:

a := handler.Map{"DoAThing": SessionHandler{s}}

to plug it into your server.

answered on Stack Overflow Nov 6, 2019 by Michael Fromberger

User contributions licensed under CC BY-SA 3.0