Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into docsp-31555-sync-…
Browse files Browse the repository at this point in the history
…data
  • Loading branch information
cbullinger committed Aug 7, 2023
2 parents 18875fc + 981919e commit b4243ba
Show file tree
Hide file tree
Showing 51 changed files with 1,057 additions and 362 deletions.
20 changes: 11 additions & 9 deletions examples/dotnet/Examples/ClientResetExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public async Task TestDiscardUnsyncedChangesHandler()
{
// :remove-start:
app = App.Create(myRealmAppId);
user = await app.LogInAsync(Credentials.Anonymous());
user = await app.LogInAsync(Credentials.Anonymous(false));
// :remove-end:
var config = new FlexibleSyncConfiguration(user);
config.ClientResetHandler = new DiscardUnsyncedChangesHandler()
Expand All @@ -55,12 +55,17 @@ public async Task TestDiscardUnsyncedChangesHandler()
// Automatic reset failed; handle the reset manually here
}
};

//:remove-start:
config.Schema = new[] { typeof(Examples.Models.Plant) };
//:remove-end:
var realm = await Realm.GetInstanceAsync(config);
try
{
var realm = await Realm.GetInstanceAsync(config);
}
catch (Exception ex)
{
Console.WriteLine($@"Error creating or opening the
realm file. {ex.Message}");
}
// :snippet-end:
await user.LogOutAsync();
}

public async Task TestManualClientReset()
Expand All @@ -85,9 +90,6 @@ public async Task TestManualClientReset()
var fsConfig = new FlexibleSyncConfiguration(fsUser);
fsConfig.ClientResetHandler =
new ManualRecoveryHandler(HandleClientResetError);
//:remove-start:
fsConfig.Schema = new[] { typeof(User) };
//:remove-end:
var fsrealm = await Realm.GetInstanceAsync(fsConfig);
}

Expand Down
88 changes: 88 additions & 0 deletions examples/dotnet/Examples/FlexibleSyncExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,95 @@ public async Task TestUseFlexibleSync()
// remove all subscriptions, including named subscriptions
realm.Subscriptions.RemoveAll(true);
});
}

[Test]
public async Task TestOpenFSRealm()
{
// :snippet-start: open-fs-realm
// :replace-start: {
// "terms": {
// "Config.FSAppId": "\"myRealmAppId\"",
// "Credentials.Anonymous(false)": "Credentials.Anonymous()"}
// }
var app = App.Create(Config.FSAppId);
var user = await app.LogInAsync(Credentials.Anonymous(false));
Realm realm;

var config = new FlexibleSyncConfiguration(user)
{
PopulateInitialSubscriptions = (realm) =>
{
var allTasks = realm.All<MyTask>();
realm.Subscriptions.Add(allTasks, new SubscriptionOptions { Name = "allTasks" });
}
};
try
{
realm = await Realm.GetInstanceAsync(config);
// :remove-start:
var session = realm.SyncSession;
Assert.NotNull(session);
// :remove-end:
}
catch (Exception ex)
{
Console.WriteLine($@"Error creating or opening the
realm file. {ex.Message}");
}
// :replace-end:
// :snippet-end:
await user.LogOutAsync();
}

[Test]
public async Task TestOpenFSRealmOffline()
{
// :snippet-start: open-fs-realm-offline
// :replace-start: {
// "terms": {
// "Config.FSAppId": "\"myRealmAppId\"",
// "Credentials.Anonymous(false)": "Credentials.Anonymous()"
// }
// }
var app = App.Create(Config.FSAppId);
// :remove-start:
// Another app.CurrentUser was carrying over into this test
// causing issues with opening the FS realm. This resolves the
// test failure but there should probably be stronger cleanup
// between tests to negate the need for this.
if (app.CurrentUser != null) {
await app.RemoveUserAsync(app.CurrentUser);
await app.LogInAsync(Credentials.Anonymous(false));
};
// :remove-end:
Realms.Sync.User user;
FlexibleSyncConfiguration config;
Realm realm;

if (app.CurrentUser == null)
{
// App must be online for user to authenticate
user = await app.LogInAsync(Credentials.Anonymous(false));
config = new FlexibleSyncConfiguration(user);
realm = Realm.GetInstance(config);
// Go on to add or update subscriptions and use the realm
// :remove-start:
var session = realm.SyncSession;
Assert.NotNull(session);
// :remove-end:
}
else
{
// This works whether online or offline
// It requires a user to have been previously authenticated
user = app.CurrentUser;
config = new FlexibleSyncConfiguration(user);
realm = Realm.GetInstance(config);
// Go on to add or update subscriptions and use the realm
}
// :replace-end:
// :snippet-end:
}

[Test]
Expand Down
4 changes: 2 additions & 2 deletions examples/dotnet/Examples/OpenARealmExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task Setup()
//realm = await Realm.GetInstanceAsync(config);
// :uncomment-end:
}
catch (RealmFileAccessErrorException ex)
catch (Exception ex)
{
Console.WriteLine($@"Error creating or opening the
realm file. {ex.Message}");
Expand All @@ -58,7 +58,7 @@ public async Task Setup()

// :snippet-start: open-synced-realm-synchronously
// :uncomment-start:
// var synchronousRealm = await Realm.GetInstanceAsync(config);
// var synchronousRealm = Realm.GetInstance(config);
// :uncomment-end:
// :snippet-end:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package com.mongodb.realm.realmkmmapp

import io.realm.kotlin.Realm
import io.realm.kotlin.ext.query
import io.realm.kotlin.internal.platform.runBlocking
import io.realm.kotlin.mongodb.App
import io.realm.kotlin.mongodb.Credentials
import io.realm.kotlin.mongodb.sync.*
import io.realm.kotlin.mongodb.syncSession
import io.realm.kotlin.types.RealmInstant
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import org.mongodb.kbson.BsonObjectId
import org.mongodb.kbson.ObjectId
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.time.Duration.Companion.minutes


// :replace-start: {
// "terms": {
// "SyncTask": "Task"
// }
// }
class ManageSyncSession : RealmTest() {

class SyncTask : RealmObject {
@PrimaryKey
var _id: ObjectId = BsonObjectId()
var taskName: String = ""
var assignee: String? = null
var completed: Boolean = false
var progressMinutes: Int = 0
var dueDate: RealmInstant? = null
}

val app = App.create(yourFlexAppId)
val credentials = Credentials.anonymous(reuseExisting = false)
@Test
fun waitForChangesUploadAndDownload() {
runBlocking {
val user = app.login(credentials)
val config = SyncConfiguration.Builder(user, setOf(SyncTask::class))
.initialSubscriptions { it.query<SyncTask>().subscribe() }
.build()
val realm = Realm.open(config)
Log.v("Successfully opened realm: ${realm.configuration}")
// :snippet-start: wait-upload-download
// Wait to download all pending changes from Atlas
realm.syncSession.downloadAllServerChanges(1.minutes)

// Add data locally
realm.write {
this.copyToRealm(SyncTask().apply {
taskName = "Review proposal"
assignee = "Emma"
progressMinutes = 0
})
}

val upload = // :remove:
// Wait for local changes to be uploaded to Atlas
realm.syncSession.uploadAllLocalChanges(1.minutes)
// :snippet-end:
assertTrue(upload)
realm.write {
val tasks = query<SyncTask>().find()
delete(tasks)
assertEquals(0, tasks.size)
}
realm.syncSession.uploadAllLocalChanges()
user.remove()
realm.close()
}
}

@Test
fun pauseResumeSyncSession() {
runBlocking {
val user = app.login(credentials)
val config = SyncConfiguration.Builder(user, setOf(SyncTask::class))
.initialSubscriptions { it.query<SyncTask>().subscribe() }
.build()
val realm = Realm.open(config)
Log.v("Successfully opened realm: ${realm.configuration}")
// :snippet-start: pause-resume-sync
// Pause the sync session
// Data that you write while session is paused does not sync to Atlas
realm.syncSession.pause()
assertEquals(SyncSession.State.PAUSED, realm.syncSession.state) // :remove:

// Add data locally
realm.write {
this.copyToRealm(SyncTask().apply {
taskName = "Submit expense report"
assignee = "Kevin"
progressMinutes = 0
})
}

// Resume sync session
// Local changes now sync to Atlas
realm.syncSession.resume()
// :snippet-end:
assertEquals(SyncSession.State.ACTIVE, realm.syncSession.state)
realm.write {
val tasks = query<SyncTask>().find()
delete(tasks)
assertEquals(0, tasks.size)
}
realm.syncSession.uploadAllLocalChanges()
user.remove()
realm.close()
}
}

@Test
fun monitorSyncProgress() {
/*
NOTE: Kotlin does not currently support progress listeners for Flexible Sync
Requires PBS
*/
runBlocking {
val app1 = App.create(yourAppId)
val user = app1.login(credentials)
val config = SyncConfiguration.Builder(user, PARTITION, setOf(SyncTask::class))
.name(PARTITION)
.build()
val realm = Realm.open(config)
Log.v("Successfully opened realm: ${realm.configuration}")

realm.write {
this.copyToRealm(SyncTask().apply {
taskName = "Schedule appointment"
assignee = "Jane"
progressMinutes = 0
})
}
// :snippet-start: monitor-progress
val stream = realm.syncSession.progressAsFlow(
Direction.UPLOAD, ProgressMode.CURRENT_CHANGES
)
stream.collect { progress ->
if (progress.transferableBytes == progress.transferredBytes) {
Log.i("Upload complete")
}
}
// :snippet-end:
assertTrue(stream.first().isTransferComplete)
realm.write {
val tasks = query<SyncTask>().find()
delete(tasks)
assertEquals(0, tasks.size)
}
realm.syncSession.uploadAllLocalChanges()
user.remove()
realm.close()
}
}

@Test
fun monitorNetworkConnection() {
runBlocking {
val user = app.login(credentials)
val config = SyncConfiguration.Builder(user, setOf(SyncTask::class))
.initialSubscriptions { it.query<SyncTask>().subscribe() }
.build()
val realm = Realm.open(config)
Log.v("Successfully opened realm: ${realm.configuration}")
// :snippet-start: get-network-connection
if (realm.syncSession.connectionState == ConnectionState.CONNECTED) {
Log.i("Connected to network")
// ... do something
}
// :snippet-end:
val flow = CoroutineScope(Dispatchers.Default).launch {
// :snippet-start: monitor-network-connection
val connectionFlow = realm.syncSession.connectionStateAsFlow()
connectionFlow.collect { ConnectionStateChange ->
if (ConnectionStateChange.newState == ConnectionState.CONNECTED) {
Log.i("Connected to Atlas Device Sync server")
}
}
// :snippet-end:
assertEquals(ConnectionState.CONNECTED, realm.syncSession.connectionState)
}
realm.write {
this.copyToRealm(SyncTask().apply {
taskName = "Do a thing"
assignee = "Me"
progressMinutes = 0
})
}
realm.write {
val tasks = query<SyncTask>().find()
delete(tasks)
assertEquals(0, tasks.size)
}
realm.syncSession.uploadAllLocalChanges()
flow.cancel()
user.remove()
realm.close()
}
}
}
// :replace-end:

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var app = App.Create("myRealmAppId");
Realms.Sync.User user;
FlexibleSyncConfiguration config;
Realm realm;

if (app.CurrentUser == null)
{
// App must be online for user to authenticate
user = await app.LogInAsync(Credentials.Anonymous());
config = new FlexibleSyncConfiguration(user);
realm = Realm.GetInstance(config);
// Go on to add or update subscriptions and use the realm
}
else
{
// This works whether online or offline
// It requires a user to have been previously authenticated
user = app.CurrentUser;
config = new FlexibleSyncConfiguration(user);
realm = Realm.GetInstance(config);
// Go on to add or update subscriptions and use the realm
}
Loading

0 comments on commit b4243ba

Please sign in to comment.