In client(Unity), I am calling an Atlas function to create a player’s document. However, the Unity client is not able to retrieve the newly created document immediately after the Atlas function finishes writing it. I have tried using WaitForDownloadAsync to ensure that the download is complete, but it doesn’t seem to be working. Here is the code snippet for my Atlas function
This is my atlas function
public static async Task<Dictionary<string, object>> CallAtlasFunc(AtlasFunc _func, bool _waitSync, Dictionary<string, object> _data) {
string jsonResult = null;
if (_data == null) jsonResult = await MyApp.CurrentUser.Functions.CallAsync<string>(_func.ToString());
else jsonResult = await MyApp.CurrentUser.Functions.CallAsync<string>(_func.ToString(), _data);
try {
//WriteLog.LogColorFormat("jsonResult: {0}", WriteLog.LogType.Realm, jsonResult);
var dataDic = HandleReplyData(jsonResult);
if (_waitSync) await MyRealm.SyncSession.WaitForDownloadAsync(); //<----- I use WaitForDownloadAsync to make sure downalod finished but it's not working.
//dataDic.Log();
return dataDic;
} catch (Exception _e) {
WriteLog.LogError("CallAtlasFunc Error: " + _e);
return null;
}
}
I use WaitForDownloadAsync to make sure downalod finished but it’s not working.
So I can’t make sure I got the newest player data.
var player = MyRealm.Find(MyApp.CurrentUser.Id);// <–player’s data may be old
The issue here is caused by the fact that data from Atlas is asynchronously picked up by Atlas Device Sync, so there’s a small window between inserting a document in Atlas and it being propagated to sync clients. Calling WaitForDownloadAsync is not going to solve this here because at the time the request is issues, Sync doesn’t know about the new documents in Atlas. Instead, you could register a notification listener on the collection to be notified when it changes. I don’t have enough details to write an example using your entities, but it would look something like this:
async Task InsertSomeData(Dictionary<string, object> data)
{
// Assuming the function returns an id here, otherwise you can read it from the data or
// somewhere else depending on your app needs
var insertedId = await MyApp.CurrentUser.Functions.CallAsync<string>("insertFunc", data);
var tcs = new TaskCompletionSource();
using var token = realm.All<UserData>().Where(d => d.Id == instertedId).SubscribeForNotifications((sender, changes) =>
{
// When we see the item inserted, we resolve the task completion source
// and return from the function.
if (sender.Count > 0)
{
tcs.TrySetResult();
}
});
await tcs.Task;
}
Of course, this will only work for insertions as we’re relying on having an empty initial collection, which then gets populated with the item we just inserted. If you have updates, you’ll probably want to have some other property on the object you use as a marker that you’ve seen your update - for example an UpdatedAt field, making the query something like:
var updatedAt = DateTimeOffset.UtcNow;
data["updatedAt"] = updatedAt;
var updatedId = await MyApp.CurrentUser.Functions.CallAsync<string>("insertFunc", data);
using var token = realm.All<UserData>().Where(d => d.Id == updatedId && d.UpdateAt >= updatedAt).SubscribeForNotifications(...);