I have created a global realm for use in a Xamarin Forms app with a PrintGrade
class as follows;
public class PrintGrade : RealmObject
{
[PrimaryKey]
[MapTo("id")]
public int ID { get; set; }
[Required]
[MapTo("grade")]
public string Grade { get; set; }
[Required]
[MapTo("name")]
public string Name { get; set; }
[MapTo("active")]
public bool Active { get; set; }
}
And I use the following code to configure, open and synchronise the realm;
public static class AppConfig
{
...
public const string CommonRealm = "DriverAppCommon";
...
}
public partial class RunSheet : ContentPage
{
...
private readonly string _realmCommon = AppConfig.CommonRealm;
private Realm _commonRealm;
...
protected override async void OnAppearing()
{
...
_commonRealm = await OpenRealm(_realmCommon, _user).ConfigureAwait(true);
if (_commonRealm != null)
{
if (!await SynchroniseRealm(_commonRealm, false, true).ConfigureAwait(true))
throw new Exception("Failed to download the reference data required by the app.");
}
}
...
private async Task<Realm> OpenRealm(string realmName, User user)
{
Realm realm = null;
try
{
var config = ConnectionServices.GetRealmConfiguration(realmName, user);
realm = ConnectionServices.ConnectToSyncServer(config);
}
catch (Exception ex)
{
...
}
return realm;
}
private async Task<bool> SynchroniseRealm(Realm realm, bool upload, bool download, int timeout = 0)
{
bool synchronised = false;
try
{
var session = realm.GetSession();
Thread.Sleep(150);
using CancellationTokenSource cts = new CancellationTokenSource();
switch (timeout)
{
case -1:
// No timeout - wait until finished...
break;
default:
cts.CancelAfter(TimeSpan.FromSeconds(timeout));
break;
}
if (download)
{
if (timeout == -1)
await SynchroniseRealmData(session, download).ConfigureAwait(true);
else
await SynchroniseRealmData(session, download).CancelAfter(cts.Token).ConfigureAwait(true);
}
if (upload)
{
...
}
synchronised = true;
}
catch (OperationCanceledException)
{
Analytics.TrackEvent(nameof(SynchroniseRealm), new Dictionary<string, string> {
{"User", _userName },
{ download ? "DownLoad" : "Upload", $"Timed out after {timeout} seconds" }
});
}
catch (Realms.Exceptions.RealmException ex)
{
Crashes.TrackError(ex, new Dictionary<string, string> { { "Synchronise Realm", (IsDownloading ? "Downloading" : "Uploading") } });
}
catch (Exception ex)
{
Crashes.TrackError(ex, new Dictionary<string, string> { { "Synchronise Realm", (IsDownloading ? "Downloading" : "Uploading") } });
}
return synchronised;
}
private static async Task SynchroniseRealmData(Session session, bool download)
{
if (download)
await session.WaitForDownloadAsync().ConfigureAwait(true);
else
await session.WaitForUploadAsync().ConfigureAwait(true);
}
}
public static class ConnectionServices
{
private const string _commonRealm = "DriverAppCommon";
public static Realm ConnectToSyncServer(FullSyncConfiguration config)
{
return Realm.GetInstance(config);
}
public static FullSyncConfiguration GetRealmConfiguration(string realmName, User user)
{
FullSyncConfiguration config;
Uri serverUrl;
if (realmName == _commonRealm)
{
serverUrl = new Uri(realmName, UriKind.Relative);
config = new FullSyncConfiguration(serverUrl, user)
{
ObjectClasses = new[] { typeof(PrintGrade) }
};
}
else
{
...
}
return config;
}
}
My problem is the common realm never finishes synchronising. I have tried it with both an indefinite and a 2 minute timeout. The realm only contains 13 records so I would expect it to take seconds to synchronise.
From what I have read in the documentation a global realm is read-only for all users and the user I pass to the procedures is the same user from previous code who has been authenticated and downloaded their own realm already. Am I missing something?