DEV Community

Rak
Rak

Posted on • Edited on

Building a Real-Time Messaging Service with Nitric SDK in Go

In this tutorial, we will build a simple real-time messaging service using the Nitric SDK in Go.

Our application will allow multiple clients to connect via WebSockets and broadcast messages to all connected clients.

If you haven't used the Nitric SDK before, then start with this tutorial to get your project scaffolded and ready to run.

Pre-Requisites:

  • Go installed on your machine.
  • Nitric SDK for Go.

Step 1: Import Necessary Libraries

Firstly, we need to import the required libraries.

import (
  "fmt"
  "github.com/nitrictech/go-sdk/faas"
  "github.com/nitrictech/go-sdk/nitric"
)
Enter fullscreen mode Exit fullscreen mode

Step 2: Initialize Nitric Application

Inside the main function, initialize a new WebSocket and a new collection to store connection information.

func main() {
  ws, err := nitric.NewWebsocket("public")
  if err != nil {
    return
  }

  connections, err := nitric.NewCollection("connections").With(nitric.CollectionEverything...)
  if err != nil {
    return
  }

  // TODO: onConnect, onDisconnect, onMessage handlers

  if err := nitric.Run(); err != nil {
    fmt.Println(err)
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Handle WebSocket Events

We'll define three event handlers: one for new connections, one for disconnections, and one for incoming messages.

a) Connection Event:

Register a new connection by saving the connection ID to the "connections" collection.

ws.On(faas.WebsocketConnect, func(ctx *faas.WebsocketContext, next faas.WebsocketHandler) (*faas.WebsocketContext, error) {
  err := connections.Doc(ctx.Request.ConnectionID()).Set(ctx.Request.Context(), map[string]interface{}{
    "connectionId": ctx.Request.ConnectionID(),
  })
  if err != nil {
    return ctx, err
  }

  return next(ctx)
})
Enter fullscreen mode Exit fullscreen mode

b) Disconnection Event:

Remove a registered connection from the "connections" collection on disconnection.

ws.On(faas.WebsocketDisconnect, func(ctx *faas.WebsocketContext, next faas.WebsocketHandler) (*faas.WebsocketContext, error) {
  err := connections.Doc(ctx.Request.ConnectionID()).Delete(ctx.Request.Context())
  if err != nil {
    return ctx, err
  }

  return next(ctx)
})
Enter fullscreen mode Exit fullscreen mode

c) Message Event:

Broadcast incoming messages to all the registered WebSocket connections.

ws.On(faas.WebsocketMessage, func(ctx *faas.WebsocketContext, next faas.WebsocketHandler) (*faas.WebsocketContext, error) {
  connectionStream, err := connections.Query().Stream(ctx.Request.Context())
  if err != nil {
    return ctx, err
  }

  for {
    res, err := connectionStream.Next()
    if err != nil {
      break // reached the end of the documents
    }

    connectionId, ok := res.Content()["connectionId"].(string)
    if !ok {
      continue
    }

    err = ws.Send(ctx.Request.Context(), connectionId, ctx.Request.Data())
    if err != nil {
      return ctx, err
    }
  }

  return next(ctx)
})
Enter fullscreen mode Exit fullscreen mode

Now, you have a basic real-time messaging service set up. Clients can connect to your service via WebSocket, send messages, and those messages will be broadcasted to all connected clients in real-time.

You can test it out by using the Nitric CLI.

Top comments (0)