MatchMaker

Diakris’ MatchMaker distributes the matching data across the servers in the cluster enabling horizontal scaling.

The MatchMaker definition (rule) MUST be defined in HTTP servers (This is because MatchMaker data is managed by Diarkis HTTP server memory). Configurations must be loaded by HTTP and TCP and/or UDP servers.

// You MUST import matching package in HTTP server and other servers

import "github.com/Diarkis/diarkis/matching"

func main() {
  // You MUST call this to enable matching package (MatchMaker)
    matching.Setup("absolute path to a configuration file or an empty string")

  // other things to do here
  diarkis.Start()
}

How To Add An Item To MatchMaker

You must “add” to MatchMaker in order to be searched and matched. We recommend adding items with short TTL and keep adding them until they are no longer needed. Add is relatively cheap, but Remove is expensive.

NOTE: Maximum TTL is 60 seconds. In order to have long-lasting items (longer than 60 seconds), you need to add the items repeatedly until you no longer need them.

NOTE: This can be written on HTTP, TCP, and/or UDP/RUDP

The example below shows how to add a room to MatchMaker:

// MatchMaker item property to be searched by
props := make(map[string]int)
props["level"] = 30
props["rank"] = 7

// Unique name of the match-making definition to add the room to
matchingName := "levelAndRank"

// roomMetadata will be retrieved as the search results.
data := make(map[string]interface{})
data["roomID"] = roomID
data["roomType"] = 2
data["roomName"] = "Room of level 30 and rank 7"

// TTL of the room in match-making. TTL is in seconds
ttl := int64(30)

// relayLimit is the number of server nodes to send the data to at a time:
// Greater the value, the faster and more CPU intense it is
relayLimit := 2

matching.Add(matchingName, roomID, props, roomMetadata, ttl, relayLimit)

How To Remove Items From MatchMaker

The Remove function of MatchMaker is expensive. We recommend relying on TTL or Add as much as you can.

NOTE: This can be written on HTTP, TCP, and/or UDP/RUDP

// match-making definition name to remove items from
matchingName := "levelAndRank"

// Unique ID list of items to be removed
idlist := []string{ roomIDA, roomIDB }

// relayLimit is the number of server nodes to send the data to at a time:
// Greater the value, the faster and more CPU intense it is
relayLimit := 2

matching.Remove(matchingName, idlist, relayLimit)

How To Search In MatchMaker

You need to choose which MatchMaker definition(s) to search in. You may search in multiple MatchMaker definitions by giving multiple MatchMaker definition names. The order of the search will be the same as the order of the MatchMaker definition array passed to the search function.

NOTE: This can be written on HTTP, TCP, and/or UDP/RUDP

/**
* Must import the following:
*
* github.com/Diarkis/diarkis/matching
* github.com/Diarkis/diarkis/room
* github.com/Diarkis/diarkis/util
*
*/
matchingNames := []string{ "levelAndRank" }

// Search conditions
conds := make(map[string]int)
conds["level"] = 14
conds["rank"] = 3

// How many search results you require
howmany := 10

matching.Search(matchingNames, conds, howmany, func(err error, results []interface{}) {

if err != nil {
// Handle error
return
}

// util.Waterfall executes a list of functions in order
operations := make([]func(error), len(results))

for i := range results {
operations[i] = tryToJion
}

utill.Waterfall(operations, done)

index := 0

// We try the rooms we found
func tryToJoin(next func(error)) {

if index == len(results) {
// We tried all rooms we found, but none worked
// try matching.Search again
  done(nil)
  return
}

roomID := results[index]["roomID"].(string)

room.Join(roomID, userData, ver, cmd, func(err error, members []string, owner string, createdTime int64, props map[string]interface{}) {

if err != nil {
  // this room was no good, remove from MatchMaker
for _, matchingName := range {
// we assume roomID is used as a unique ID with matching.Addd
matching.Remove(matchingName, roomID)
}
// We have failed to join the room - try the next room
    index++
    next(nil)
return
  }

  // We have joined the room successfully - skip the rest  of the rooms
  done(nil)
})

}

}

// This function will be called when everything is finished
func done(err error) {
if err != nil {
// Handle error
  return
}
logger.Debug("We are done!")
}
}