2

Working with Firebase in a Unity project, for a simple highscore, I stumbled on problems when doing a query. In editor, everything works like a charm (Editor does not have persistence) On devices (with persistence enabled) the troubles begin. Query is showing cached Firebase data, so it is only correct on first ever call in the client, and then when Firebase sees it fit to sync (maybe never, since there is no eventhandler)

However, looking for a solution, there is no way to force an update of the cached values. I then tested with KeepSynced(true) on the query and this seems to work:

this.HiscoreQuery = hiscoreref.OrderByChild ("Score").LimitToLast (20);
this.HiscoreQuery.KeepSynced(true);
this.HiscoreQuery.GetValueAsync().ContinueWith (task => {
  if (task.IsFaulted) {
    Debug.LogError ("Get hiscores faulted");
    return;
  }
  if (task.Result != null && task.Result.ChildrenCount > 0) {
    Debug.Log ("Get hiscore data success!");
    this.AddDelayedUpdateAction (() => this.OnGetHiScores (task.Result));
  }
});

Question: While this can be fine if Firebase only listen for the Query's LImitToLast(20), it would be a very bad thing, if the Firebase internally is keeping the whole (growing) hiscorelist copied in every client.

Does anyone know if KeepSynced(true) is limited to the actual query scope or the whole tree/branch? And how could one validate this?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

1

GetValue calls don't work well with KeepSynced(true). Firebase eagerly returns you the value from the cache, and only then loads the data from the server.

For a longer explanation, see my answer here: Firebase Offline Capabilities and addListenerForSingleValueEvent

If you want to use caching, use listeners and not GetValue calls. With a listener, your callback will be fired twice (if there is a change): once with the value from the cache, and then once with the value from the server.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks Frank, I'll try that (again). Could I use this example to tell the diffrence: String source = querySnapshot.getMetadata().isFromCache() ? "Local Cache" : "Firebase Server"; – Ole Ivanoff Jan 17 '20 at 07:56
  • I realize I can't do this, as it would only work if the data has changed. What I have done for now is to add a listener, and then reacting to updating the data one or more times. As I tested this, I realized the eventlistener will be active on ALL clients that have this. If you scale this to a mobile game with potentially 100's of thousands of users, this can affect your Firebase invoice ;) Practically I remove the listener af some seconds, 2 or 3 to stop getting news when it's not needed. – Ole Ivanoff Jan 17 '20 at 13:47
  • 1
    `isFromCache` is a Firestore API, while `KeepSynced` is part of the Realtime Database. While both databases are part of Firebase, they are completely separate and have their own APIs. – Frank van Puffelen Jan 17 '20 at 15:30