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 serversimport"github.com/Diarkis/diarkis/matching"funcmain() {// 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 byprops :=make(map[string]int)props["level"] =30props["rank"] =7// Unique name of the match-making definition to add the room tomatchingName :="levelAndRank"// roomMetadata will be retrieved as the search results.data :=make(map[string]interface{})data["roomID"] = roomIDdata["roomType"] =2data["roomName"] ="Room of level 30 and rank 7"// TTL of the room in match-making. TTL is in secondsttl :=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 isrelayLimit :=2matching.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 frommatchingName :="levelAndRank"// Unique ID list of items to be removedidlist := []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 isrelayLimit :=2matching.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 conditionsconds :=make(map[string]int)conds["level"] =14conds["rank"] =3// How many search results you requirehowmany :=10matching.Search(matchingNames, conds, howmany, func(err error, results []interface{}) {if err !=nil {// Handle errorreturn }// 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 foundfunctryToJoin(next func(error)) {if index ==len(results) {// We tried all rooms we found, but none worked// try matching.Search againdone(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 MatchMakerfor _, 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 roomsdone(nil) }) }}// This function will be called when everything is finishedfuncdone(err error) {if err !=nil {// Handle errorreturn } logger.Debug("We are done!") }}