コード例 #1
0
        private void Connect()
        {
            try
            {
                if (_serverInfo == null)
                {
                    _serverInfo = _serverDal.Get();
                }
                if (_serverInfo == null)
                {
                    return;
                }
                Uri       target   = new Uri($"ws://{_serverInfo.UrlServer}");
                IEndpoint endpoint = new URLEndpoint(target);
                ReplicatorConfiguration replicationConfig = new ReplicatorConfiguration(_dataBaseGetter.Get(), endpoint)
                {
                    Continuous     = true,
                    ReplicatorType = ReplicatorType.PushAndPull,
                    Authenticator  = new BasicAuthenticator(_serverInfo.Login, _serverInfo.Password)
                };
                _replicator = new Replicator(replicationConfig);
                if (CrossConnectivity.IsSupported && CrossConnectivity.Current.IsConnected)
                {
                    _replicator.Start();
                }
                _token = _replicator.AddChangeListener(_replicator_StatusChanged);
            }
            catch (Exception e)
            {
#if DEBUG
#endif
            }
        }
コード例 #2
0
        public void TestHttpLogic()
        {
            try {
                var targetEndpoint = new URLEndpoint(new Uri("http://192.168.0.11:4984/app"));
            } catch { }

            var logic = new HTTPLogic(new Uri("ws://192.168.0.11:4984/app"));
            var prop  = HttpLogicType.GetProperty("Credential", BindingFlags.Public | BindingFlags.Instance);

            prop.SetValue(hTTPLogic, new NetworkCredential("name", "pass"));
            var method = HttpLogicType.GetMethod("CreateAuthHeader", BindingFlags.NonPublic | BindingFlags.Instance);
            var res    = method.Invoke(hTTPLogic, null);

            prop = HttpLogicType.GetProperty("UseTls", BindingFlags.Public | BindingFlags.Instance);
            var useTle = logic.UseTls;

            prop = HttpLogicType.GetProperty("Error", BindingFlags.Public | BindingFlags.Instance);
            var error = logic.Error;

            prop = HttpLogicType.GetProperty("HttpStatus", BindingFlags.Public | BindingFlags.Instance);
            var status = logic.HttpStatus;

            prop = HttpLogicType.GetProperty("Port", BindingFlags.Public | BindingFlags.Instance);
            var port = logic.Port;

            prop = HttpLogicType.GetProperty("ShouldContinue", BindingFlags.Public | BindingFlags.Instance);
            var shouldContinue = logic.ShouldContinue;
        }
コード例 #3
0
        public void StartReplication()
        {
            try
            {
                var targetUrlEndpoint = new URLEndpoint(new Uri(_remoteSyncUrl, _databaseName));

                var configuration = new ReplicatorConfiguration(Database, targetUrlEndpoint)
                {
                    ReplicatorType = ReplicatorType.PushAndPull,
                    Continuous     = true
                };

                _replicator = new Replicator(configuration);

                _replicatorListenerToken = _replicator.AddChangeListener(OnReplicatorUpdate);

                _replicator.Start();
            }
            catch (Exception ex)
            {
                // We don't want replication errors to prevent us from
                // using the app, but we do want to know about them.
                Console.WriteLine($"Replication Exception - {ex.Message}");
            }
        }
コード例 #4
0
        private static void InitCouchBase()
        {
            NetDesktop.Activate();

            // Get the database (and create it if it doesn't exist)
            _database = new Database("db");

            // Create replicator to push and pull changes to and from the cloud
            var targetEndpoint = new URLEndpoint(new Uri("ws://localhost:4984/db"));
            var replConfig     = new ReplicatorConfiguration(_database, targetEndpoint);

            // Add authentication
            replConfig.Authenticator  = new BasicAuthenticator("sync_gateway", "password");
            replConfig.ReplicatorType = ReplicatorType.PushAndPull;
            replConfig.Continuous     = true;

            // Create replicator (make sure to add an instance or static variable
            // named _Replicator)
            _Replicator = new Replicator(replConfig);
            _Replicator.AddChangeListener((sender, args) =>
            {
                Instance.DataChanged.Invoke(sender, args);
                _log.Debug($"status={args.Status.Activity}");
                _log.Debug($"progress={args.Status.Progress.Completed}/{args.Status.Progress.Total}");
                _log.Debug($"error={args.Status.Error}");
                if (args.Status.Error != null)
                {
                    _log.Error($"Error :: {args.Status.Error}");
                }
            });

            _Replicator.Start();
        }
コード例 #5
0
        private static void TestReplicatorConflictResolver()
        {
            // tag::replication-conflict-resolver[]
            var target     = new URLEndpoint(new Uri("ws://localhost:4984/mydatabase"));
            var replConfig = new ReplicatorConfiguration(database, target);

            replConfig.ConflictResolver = new LocalWinConflictResolver();

            var replicator = new Replicator(replConfig);

            replicator.Start();
            // end::replication-conflict-resolver[]
        }
コード例 #6
0
        public void StartDBConnection()
        {
            Couchbase.Lite.Support.UWP.Activate();

            // Get the database (and create it if it doesn't exist)
            this.database = new Database("einkaufsliste");

            // Create replicator to push and pull changes to and from the cloud
            var targetEndpoint = new URLEndpoint(new Uri("ws://37.252.185.24:4984/db"));
            var replConfig     = new ReplicatorConfiguration(this.database, targetEndpoint)
            {
                ReplicatorType = ReplicatorType.PushAndPull
            };

            replConfig.Channels = new List <String>();
            replConfig.Channels.Add("liste");
            replConfig.Continuous = true;

            // Add authentication
            replConfig.Authenticator = new BasicAuthenticator("UserEin", "Einkaufsliste");

            // Create replicator
            var replicator = new Replicator(replConfig);

            replicator.AddChangeListener((sender, args) =>
            {
                if (args.Status.Error != null)
                {
                    System.Diagnostics.Debug.WriteLine($"Error :: {args.Status.Error}");
                }
                System.Diagnostics.Debug.WriteLine("Test sync");

                using (var query = QueryBuilder.Select(SelectResult.All())
                                   .From(DataSource.Database(this.database)))
                {
                    // Run the query
                    var result = query.Execute();
                    var res    = result.ToArray();
                    foreach (var i in res)
                    {
                        System.Diagnostics.Debug.WriteLine("Output " + Newtonsoft.Json.JsonConvert.SerializeObject(i));
                        System.Diagnostics.Debug.WriteLine("Output " + i.GetDictionary(0).GetString("name"));
                    }

                    result = query.Execute();
                    System.Diagnostics.Debug.WriteLine("Number " + result.Count());
                }
            });

            replicator.Start();
        }
コード例 #7
0
        public void syncorder(Database syncdb)
        {
            var url = new Uri("ws://104.214.56.109:4984/order");

            var target = new URLEndpoint(url);
            var config = new ReplicatorConfiguration(syncdb, target)
            {
                ReplicatorType = ReplicatorType.Push
            };

            var replicator = new Replicator(config);

            replicator.Start();
        }
コード例 #8
0
        private static void ReplicationCustomHeaders()
        {
            var url    = new Uri("ws://localhost:4984/mydatabase");
            var target = new URLEndpoint(url);

            // tag::replication-custom-header[]
            var config = new ReplicatorConfiguration(database, target)
            {
                Headers = new Dictionary <string, string>
                {
                    ["CustomHeaderName"] = "Value"
                }
            };
            // end::replication-custom-header[]
        }
コード例 #9
0
        private static void ResetReplicatorCheckpoint()
        {
            var database = _Database;
            var url      = new Uri("ws://localhost:4984/db");
            var target   = new URLEndpoint(url);
            var config   = new ReplicatorConfiguration(database, target);

            using (var replicator = new Replicator(config)) {
                // # tag::replication-reset-checkpoint[]
                // replicator is a Replicator instance
                replicator.ResetCheckpoint();
                replicator.Start();
                // # end::replication-reset-checkpoint[]
            }
        }
コード例 #10
0
        private static void PinCertificate()
        {
            // Note: No certificate is included here, so this code is for show only
            var url    = new Uri("wss://localhost:4984/db");
            var target = new URLEndpoint(url);
            var db     = _Database;

            // # tag::certificate-pinning[]
            var certificate = new X509Certificate2("cert.cer");
            var config      = new ReplicatorConfiguration(db, target)
            {
                PinnedServerCertificate = certificate
            };
            // # end::certificate-pinning[]
        }
コード例 #11
0
        private static void EnableBasicAuth()
        {
            var database = _Database;

            // tag::basic-authentication[]
            var url    = new Uri("ws://localhost:4984/mydatabase");
            var target = new URLEndpoint(url);
            var config = new ReplicatorConfiguration(database, target);

            config.Authenticator = new BasicAuthenticator("john", "pass");

            var replicator = new Replicator(config);

            replicator.Start();
            // end::basic-authentication[]
        }
コード例 #12
0
        private static void EnableSessionAuth()
        {
            var database = _Database;

            // tag::session-authentication[]
            var url    = new Uri("ws://localhost:4984/mydatabase");
            var target = new URLEndpoint(url);
            var config = new ReplicatorConfiguration(database, target);

            config.Authenticator = new SessionAuthenticator("904ac010862f37c8dd99015a33ab5a3565fd8447");

            var replicator = new Replicator(config);

            replicator.Start();
            // end::session-authentication[]
        }
コード例 #13
0
        public void TestReachability()
        {
            try {
                var status = NetworkReachabilityStatus.Unknown;
                var e      = new NetworkReachabilityChangeEventArgs(status);
                NetworkReachabilityStatus s = NetworkReachabilityStatus.Unknown;

                var _reachability = new Reachability();

                _reachability.StatusChanged += (sender, args) => s = args.Status;
                _reachability.Start();

                e.Status.Should().Be(s);

                var method = ReachabilityType.GetMethod("InvokeNetworkChangeEvent", BindingFlags.NonPublic | BindingFlags.Instance);
                var res    = method.Invoke(_reachability, new object[1] {
                    s
                });

                NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
                method = ReachabilityType.GetMethod("IsInterfaceValid", BindingFlags.NonPublic | BindingFlags.Static);
                foreach (var n in nics)
                {
                    res = method.Invoke(null, new object[1] {
                        n
                    });
                }

                var asender = new object();
                method = ReachabilityType.GetMethod("OnNetworkChange", BindingFlags.NonPublic | BindingFlags.Instance);
                res    = method.Invoke(_reachability, new object[2] {
                    asender, e
                });

                var ReplicatorType = typeof(Replicator);
                var targetEndpoint = new URLEndpoint(new Uri("ws://192.168.0.11:4984/app"));
                var config         = new ReplicatorConfiguration(Db, targetEndpoint);
                using (Replicator replicator = new Replicator(config)) {
                    method = ReplicatorType.GetMethod("ReachabilityChanged", BindingFlags.NonPublic | BindingFlags.Instance);
                    res    = method.Invoke(replicator, new object[2] {
                        asender, e
                    });
                }
            }
            catch { }
        }
コード例 #14
0
        public async Task TestReplicatorStopsWhenEndpointInvalid()
        {
            // If this IP address happens to exist, then change it.  It needs to be an address that does not
            // exist on the LAN
            var targetEndpoint = new URLEndpoint(new Uri("ws://192.168.0.11:4984/app"));
            var config         = new ReplicatorConfiguration(Db, targetEndpoint);

            using (var repl = new Replicator(config))
            {
                repl.Start();
                var count = 0;
                while (count++ <= 35 && repl.Status.Activity != ReplicatorActivityLevel.Stopped)
                {
                    WriteLine($"Replication status still {repl.Status.Activity}, waiting for stopped...");
                    await Task.Delay(500);
                }

                count.Should().BeLessThan(35, "because otherwise the replicator never stopped");
            }
        }
コード例 #15
0
ファイル: DatabaseManager.cs プロジェクト: rhedgpeth/Chatbase
        public void StartReplication(string sessionId,
                                     string[] channels,
                                     ReplicatorType replicationType = ReplicatorType.PushAndPull,
                                     bool continuous = true)
        {
            var targetUrlEndpoint = new URLEndpoint(new Uri(_remoteSyncUrl, _databaseName));

            var configuration = new ReplicatorConfiguration(Database, targetUrlEndpoint)
            {
                ReplicatorType = replicationType,
                Continuous     = continuous,
                Authenticator  = new SessionAuthenticator(sessionId),
                Channels       = channels
            };

            _replicator = new Replicator(configuration);

            _replicatorListenerToken = _replicator.AddChangeListener(OnReplicatorUpdate);

            _replicator.Start();
        }
コード例 #16
0
        private static void PinCertificate()
        {
            // Note: No certificate is included here, so this code is for show only
            var url    = new Uri("wss://localhost:4984/db");
            var target = new URLEndpoint(url);
            var db     = _Database;

            // tag::certificate-pinning[]
            // Note: `GetCertificate` is a fake method. This would be the platform-specific method
            // to find and load the certificate as an instance of `X509Certificate2`.
            // For .NET Core / .NET Framework this can be loaded from the filesystem path.
            // For UWP, from the assets directory.
            // For iOS, from the main bundle.
            // For Android, from the assets directory.
            var certificate = GetCertificate("cert.cer");
            var config      = new ReplicatorConfiguration(db, target)
            {
                PinnedServerCertificate = certificate
            };
            // end::certificate-pinning[]
        }
コード例 #17
0
        private static void StartReplication()
        {
            var db = _Database;

            /*
             * This requires Sync Gateway running with the following config, or equivalent:
             *
             * {
             *     "log":["*"],
             *     "databases": {
             *         "db": {
             *             "server":"walrus:",
             *             "users": {
             *                 "GUEST": {"disabled": false, "admin_channels": ["*"] }
             *             }
             *         }
             *     }
             * }
             */

            // # tag::replication[]
            // Note: Android emulator needs to use 10.0.2.2 for localhost (10.0.3.2 for GenyMotion)
            var url    = new Uri("ws://localhost:4984/db");
            var target = new URLEndpoint(url);
            var config = new ReplicatorConfiguration(db, target)
            {
                ReplicatorType = ReplicatorType.Pull
            };

            var replicator = new Replicator(config);

            replicator.Start();
            // # end::replication[]

            _Replicator = replicator;
        }
コード例 #18
0
        private static void PullWithFilter(Database database)
        {
            // tag::replication-pull-filter[]
            var url    = new Uri("ws://localhost:4984/mydatabase");
            var target = new URLEndpoint(url);

            var config = new ReplicatorConfiguration(database, target);

            config.PullFilter = (document, flags) => // <1>
            {
                if (document.GetString("type") == "draft")
                {
                    return(false);
                }

                return(true);
            };

            // Dispose() later
            var replicator = new Replicator(config);

            replicator.Start();
            // end::replication-pull-filter[]
        }
コード例 #19
0
        private static void PushWithFilter(Database database)
        {
            // tag::replication-push-filter[]
            var url    = new Uri("ws://localhost:4984/mydatabase");
            var target = new URLEndpoint(url);

            var config = new ReplicatorConfiguration(database, target);

            config.PushFilter = (document, flags) => // <1>
            {
                if (flags.HasFlag(DocumentFlags.Deleted))
                {
                    return(false);
                }

                return(true);
            };

            // Dispose() later
            var replicator = new Replicator(config);

            replicator.Start();
            // end::replication-push-filter[]
        }
コード例 #20
0
        private ReplicatorConfiguration CreateConfig(bool push, bool pull, bool continuous, URLEndpoint endpoint)
        {
            var retVal = new ReplicatorConfiguration(Db, endpoint);

            return(ModifyConfig(retVal, push, pull, continuous));
        }
コード例 #21
0
        private static void GettingStarted()
        {
            // # tag::getting-started[]
            // Get the database (and create it if it doesn't exist)
            var database = new Database("mydb");
            // Create a new document (i.e. a record) in the database
            string id = null;

            using (var mutableDoc = new MutableDocument()) {
                mutableDoc.SetFloat("version", 2.0f)
                .SetString("type", "SDK");

                // Save it to the database
                database.Save(mutableDoc);
                id = mutableDoc.Id;
            }

            // Update a document
            using (var doc = database.GetDocument(id))
                using (var mutableDoc = doc.ToMutable()) {
                    mutableDoc.SetString("language", "C#");
                    database.Save(mutableDoc);

                    using (var docAgain = database.GetDocument(id)) {
                        Console.WriteLine($"Document ID :: {docAgain.Id}");
                        Console.WriteLine($"Learning {docAgain.GetString("language")}");
                    }
                }

            // Create a query to fetch documents of type SDK
            // i.e. SELECT * FROM database WHERE type = "SDK"
            using (var query = QueryBuilder.Select(SelectResult.All())
                               .From(DataSource.Database(database))
                               .Where(Expression.Property("type").EqualTo(Expression.String("SDK")))) {
                // Run the query
                var result = query.Execute();
                Console.WriteLine($"Number of rows :: {result.Count()}");
            }

            // Create replicator to push and pull changes to and from the cloud
            var targetEndpoint = new URLEndpoint(new Uri("ws://localhost:4984/example_sg_db"));
            var replConfig     = new ReplicatorConfiguration(database, targetEndpoint);

            // Add authentication
            replConfig.Authenticator = new BasicAuthenticator("john", "pass");

            // Create replicator
            var replicator = new Replicator(replConfig);

            replicator.AddChangeListener((sender, args) =>
            {
                if (args.Status.Error != null)
                {
                    Console.WriteLine($"Error :: {args.Status.Error}");
                }
            });

            replicator.Start();

            // Later, stop and dispose the replicator *before* closing/disposing the database
            // # end::getting-started[]
        }
コード例 #22
0
        static void Main(string[] args)
        {
            // Get the database (and create it if it doesn't exist)
            var database = new Database("mydb");
            // Create a new document (i.e. a record) in the database
            string id = null;

            using (var mutableDoc = new MutableDocument())
            {
                mutableDoc.SetFloat("version", 2.0f)
                .SetString("type", "SDK");

                // Save it to the database
                database.Save(mutableDoc);
                id = mutableDoc.Id;
            }

            // Update a document
            using (var doc = database.GetDocument(id))
                using (var mutableDoc = doc.ToMutable())
                {
                    mutableDoc.SetString("language", "python");
                    database.Save(mutableDoc);

                    using (var docAgain = database.GetDocument(id))
                    {
                        Console.WriteLine($"Document ID :: {docAgain.Id}");
                        Console.WriteLine($"Learning {docAgain.GetString("language")}");
                    }
                }

            // Create a query to fetch documents of type SDK
            // i.e. SELECT * FROM database WHERE type = "SDK"
            using (var query = QueryBuilder.Select(SelectResult.All())
                               .From(DataSource.Database(database))
                               .Where(Expression.Property("type").EqualTo(Expression.String("SDK"))))
            {
                // Run the query
                var result = query.Execute();
                Console.WriteLine($"Number of rows :: {result.Count()}");
            }


            using (var query = QueryBuilder.Select(
                       SelectResult.Expression(Meta.ID),
                       SelectResult.Property("language"))
                               .From(DataSource.Database(database)))
            {
                foreach (var result in query.Execute())
                {
                    Console.WriteLine($"Document Name :: {result.GetString("language")}");
                }
            }

            // Create replicator to push and pull changes to and from the cloud
            var targetEndpoint = new URLEndpoint(new Uri("ws://localhost:4984/getting-started-db"));
            var replConfig     = new ReplicatorConfiguration(database, targetEndpoint);

            // Add authentication
            replConfig.Authenticator = new BasicAuthenticator("john", "pass");

            // Create replicator (make sure to add an instance or static variable
            // named _Replicator)
            var _Replicator = new Replicator(replConfig);

            _Replicator.AddChangeListener((sender, args) =>
            {
                if (args.Status.Error != null)
                {
                    Console.WriteLine($"Error :: {args.Status.Error}");
                }
            });
            //Path.Combine(AppContext.BaseDirectory, "CouchbaseLite");
            _Replicator.Start();
        }
コード例 #23
0
        private static void GettingStarted()
        {
            // tag::getting-started[]
            // Get the database (and create it if it doesn't exist)
            var database = new Database("mydb");

            // Create a new document (i.e. a record) in the database
            string id = null;

            using (var mutableDoc = new MutableDocument())
            {
                mutableDoc.SetFloat("version", 2.0f)
                .SetString("type", "SDK");

                // Save it to the database
                database.Save(mutableDoc);
                id = mutableDoc.Id;
            }

            // Update a document

            // Retrieve doc from database
            using (var doc = database.GetDocument(id))

                // set the doc to mutable
                using (var mutableDoc = doc.ToMutable())
                {
                    // apply some modifications :
                    // add a field & value
                    mutableDoc.SetString("language", "C#");

                    // save the doc
                    database.Save(mutableDoc);

                    // retrieve again from Lite DB to check the updated doc
                    // with the new field
                    using (var docAgain = database.GetDocument(id))
                    {
                        Console.WriteLine($"Document ID :: {docAgain.Id}");
                        Console.WriteLine($"Learning {docAgain.GetString("language")}");
                    }
                }

            // Create a query to fetch documents of type SDK
            // i.e. SELECT * FROM database WHERE type = "SDK"

            using (var query = QueryBuilder.Select(SelectResult.All())
                               .From(DataSource.Database(database))
                               .Where(Expression.Property("type").EqualTo(Expression.String("SDK"))))
            {
                // Run the query
                var result = query.Execute();
                Console.WriteLine($"Number of rows :: {result.Count()}");
            }

            // Create replicator to push and pull changes to and from the remote couchbase DB
            // Through Sync Gateway & WebSockets (ws)

            var targetEndpoint = new URLEndpoint(new Uri("ws://localhost:4984/getting-started-db"));
            var replConfig     = new ReplicatorConfiguration(database, targetEndpoint);

            // Add authentication

            replConfig.Authenticator = new BasicAuthenticator("admin", "password");

            // Create replicator (make sure to add an instance or static variable
            // named _Replicator)

            _Replicator = new Replicator(replConfig);

            // Manage replication error handling

            _Replicator.AddChangeListener((sender, args) =>
            {
                if (args.Status.Error != null)
                {
                    Console.WriteLine($"Error :: {args.Status.Error}");
                }
            });

            _Replicator.Start();

            // Later, stop and dispose the replicator *before* closing/disposing the database
            // end::getting-started[]
        }
コード例 #24
0
    void Start()
    {
        Database.SetLogLevel(LogDomain.All, LogLevel.Verbose);

        // Get the database (and create it if it doesn't exist)
        database = new Database(databaseName, new DatabaseConfiguration()
        {
            Directory = Path.Combine(Application.persistentDataPath, "CouchBase")
        });

        // Create a new document (i.e. a record) in the database
        string id = null;

        using (MutableDocument mutableDoc = new MutableDocument("meta")) {
            mutableDoc.SetFloat("version", 2.0f)
            .SetString("type", "SDK");

            // Save it to the database
            database.Save(mutableDoc);
            id = mutableDoc.Id;
        }

        statusLabel.text += "\n- Saved meta doc";

        // Update a document
        using (Document doc = database.GetDocument("meta"))
            using (MutableDocument mutableDoc = doc.ToMutable()) {
                mutableDoc.SetFloat("version", 2.0f);
                database.Save(mutableDoc);

                using (Document docAgain = database.GetDocument("meta")) {
                    Debug.Log($"Document ID :: {docAgain.Id}");
                    Debug.Log($"Version {docAgain.GetFloat("version")}");
                    statusLabel.text += $"\n- Retrieved: {docAgain.Id}";
                }
            }

        // Create a query to fetch documents of type SDK
        // i.e. SELECT * FROM database WHERE type = "SDK"
        using (IWhere query = QueryBuilder.Select(SelectResult.All())
                              .From(DataSource.Database(database))
                              .Where(Expression.Property("version").EqualTo(Expression.Float(2.0f)))) {
            // Run the query
            IResultSet result = query.Execute();
            int        count  = result.AllResults().Count;
            Debug.Log($"Number of rows :: {count}");
            statusLabel.text += $"\n- Query result: {count}";
        }

#if UNITY_EDITOR
        Debug.LogWarning("CouchBase: In Unity Editor – Not replicating!");
        return;
#endif
        // Create replicator to push and pull changes to and from the cloud
        // NOTE: if Continuous is set to true, make sure to stop it and to clean up everything before exiting the application!
        URLEndpoint             targetEndpoint = new URLEndpoint(new Uri(syncUrl));
        ReplicatorConfiguration replConfig     = new ReplicatorConfiguration(database, targetEndpoint)
        {
            // Add authentication
            Authenticator  = new BasicAuthenticator(username, password),
            ReplicatorType = ReplicatorType.PushAndPull,
            Continuous     = false
        };

        // Create replicator
        replicator = new Replicator(replConfig);
        replicator.AddChangeListener((sender, args) => {
            if (args.Status.Error != null)
            {
                Debug.Log($"Error :: {args.Status.Error}");
            }
            else
            {
                if (replicator.Status.Activity != ReplicatorActivityLevel.Busy && replicator.Status.Activity != ReplicatorActivityLevel.Connecting)
                {
                    syncing = false;
                    Debug.Log($"Done syncing: {replicator.Status.Activity}");
                    doneSyncing = true;
                }
                else
                {
                    Debug.Log($"Progress: {args.Status.Progress.Completed} / {args.Status.Progress.Total}");
                }
            }
        });

        Debug.Log("Starting syncing...");
        statusLabel.text += "\n- Starting syncing...";
        replicator.Start();

        syncing = true;
        // Later, stop and dispose the replicator *before* closing/disposing the database
    }