Internal Communications (Server-to-Server Communications) - Mesh Package

Diarkis servers (pods) can talk to each other to execute certain operations on other servers and even perform request and response style communications.

We recommend using github.com/Diarkis/diarkis/datacapsule for handling transported data (response data of mesh communications)

Request And Response Style Communication

This type of communication is when one server node sends a request to another server node expecting a response from it.

Request Receiver

// import "github.com/Diarkis/diarkis/datacapsule" // This is used to handle to transported data

// cmdID is a unique ID for the internal command similar to HTTP URL
mesh.Command(cmdID, handleInternalCommand)

func handleInternalCommmand(req map[string]interface{}) (map[string]interface{}, error) {
    // request parameters
    question := mesh.GetInt(req, "question")
    userMessage := mesh.GetBytes(req, "message")
    messageData := make([]byte, 0)
    switch question {
    case 1:
        messageData = CreateMessageDataForCaseOne(userMessage)
    case 2:
        messageData = CreateMessageDataForCaseTwo(userMessage)
    default:
        return nil, errors.New("Invalid question")
    }

    cp := datacapsule.NewCapsule()

    cp.SetAsBytes("messageData", messageData)
    // returned value of cp.Export() will be sent as a response data
    return cp.Export(), nil
}

Request Sender

requestParams := make(map[string]interface{})
requestParams["question"] = 1
requestParams["message"] = userMessage

// cmdID is a unique ID for the internal command similar to HTTP URL
mesh.SendRequest(cmdID, receiverAddr, requestParams, func(err error, res map[string]interface{}) {
     if err != nil {
         // handle the error here
         return
    }

    responseCapsule := datacapsule.NewCapsule()

    responseData, err := responseCapsule.Import(res)

    if err != nil {

        // handle error here

    }
    logger.Debug("We have the response %v - error? %v", responseData.GetAsBytes("messageData"))
})

Send An Internal Message To Multiple Server Nodes

This style of internal communication does not expect remote server nodes to send a response.

Receiver

mesh.Command(commandID, handleCommand)

func handleCommand(req map[string]interface{}) (error, map[string]interface{}) {
message := mesh.GetString(req, "message")
      id := mesh.GetUint32("id")
      timestamp := GetInt64("timestamp")
      logger.Debug("Do something with %s of %v and %v", message, id, timestamp)
      // We do not send a response
      return nil, nil
}

Sender

// All UDP server node addresses
udpNodes := mesh.GetNodeAddressesByType(udp.Type)
// Message data to be delivered
data := make(map[string]interface{})
data["message"] = message
data["id"] = messageID // messageID is uint32
Data["timestamp"] = timestamp // timestamp in milliseconds is int64
// deliveryLimit is the number of server nodes to send the message to simultaneously
deliveryLimit := 2
// This is a reliable message delivery to guarantee the delivery of the message to all server nodes
mesh.SendMany(commandID, udpNodes, data, deliveryLimit)
/// This is an unreliable message delivery: faster and cheaper, but not reliable
mesh.USendMany(commandID, udpNodes, data, deliveryLimit)

How To Check Online/Offline Status Of A Server Node

A Diarkis server node may go offline when a server node receives SIGTERM. 

When a server node is offline, it stops receiving new client connections, and Room and Group will not allow new rooms/groups to be created.

The connected clients may continue with the communications as normal but are encouraged to reconnect to another node by receiving OnOffline event notifications.

// Check to see if a specific server node is online or not
online := mesh.IsNodeOnline(nodeMeshAddr)

// Check to see if itself is online or not
amIOnline := mesh.IsMyNodeOnline()