Problem
I'm using Firebase Realtime Database (for Unity) to manage the server side for a turn based game but I have a problem with my matchmaking... a high download usage.
Every online game have 2 base states to avoid more than 2 players join a game: Created and Joined
- Created: A player try to join a game, if can't find one a new game will be Created
- Joined: A player try to join a game, if find one change the state to from Created to Joined
I'm using RunTransaction
to prevent more than 2 players from joining a game, but I checked that the latest data was not fetched from the database because of the local cache, adding keepSynced
over my matches-{lang}
child node will always have the latest data but naturally this produces a high download usage.
private DatabaseReference DatabaseReference()
{
return FirebaseDatabase.DefaultInstance.RootReference.Child(MatchesLocation(LanguageManager.Manager.GetPlayerLanguageCode()));
}
private DatabaseReference DatabaseReferenceLangMatch(Language language)
{
return FirebaseDatabase.DefaultInstance.RootReference.Child(MatchesLocation(LanguageManager.Manager.GetLanguageCode(language)));
}
public void ManageKeepSyncedMatches(Language lang)
{
DatabaseReferenceLangMatch(Language.English).KeepSynced(lang == Language.English);
}
public void JoinMatchTransaction(GameMatchOnline gameMatchOnline, UnityAction<string, bool> callback)
{
JoinTransactionAbort joinResult = JoinTransactionAbort.None;
DatabaseReference matchesListRef = DatabaseReference();
Dictionary<string, object> joinerDict = gameMatchOnline.ToJoinDictionary();
matchesListRef.Child(gameMatchOnline.matchId).RunTransaction(matchData =>
{
Dictionary<string, object> matchDict = matchData.Value as Dictionary<string, object>;
if (matchDict == null)
{
joinResult = JoinTransactionAbort.Null;
return TransactionResult.Success(null);
}
if (!matchDict.ContainsKey("state"))
{
joinResult = JoinTransactionAbort.Error;
return TransactionResult.Abort();
}
GameMatchOnline.State state = (GameMatchOnline.State)System.Convert.ToInt32(matchDict["state"]);
if (state != GameMatchOnline.State.Created)
{
joinResult = JoinTransactionAbort.Error;
return TransactionResult.Abort();
}
joinResult = JoinTransactionAbort.None;
matchDict.Add("joinerInfo", joinerDict["joinerInfo"]);
matchDict["state"] = joinerDict["state"];
matchData.Value = matchDict;
return TransactionResult.Success(matchData);
}).ContinueWith(task =>
{
// Fail
if (task.IsFaulted || task.IsCanceled)
{
UnityThread.executeInUpdate(() =>
{
if (joinResult == JoinTransactionAbort.Error)
{
callback(null, false);
}
});
}
// Can Join match
else if (task.IsCompleted)
{
UnityThread.executeInUpdate(() =>
{
if (joinResult == JoinTransactionAbort.None)
{
AddListenerResultsValueChanged(gameMatchOnline.matchId, gameMatchOnline.joinerInfo.userId, gameMatchOnline.isPrivate, gameMatchOnline.language);
callback(gameMatchOnline.matchId, true);
}
else
{
callback(null, false);
}
});
}
});
}
Question
- Removing
keepSynced
players will have locally cached information formatches-{lang}
, can I trust that by doing this there will be no more than 2 players per game? *Transactions are supposed to avoid this kind of problem. - Is there a way to avoid the local cache for a request and thus always get the updated data?
- Could the best solution be to move the games to another node to reduce the size of the
matches-{lang}
node?
Thanks!