Esempio n. 1
0
        public async Task ShouldCreatePendingTaskForCreate()
        {
            //given
            await FHClient.Init();

            const string taskName = "task1";
            var          dataset1 = FHSyncDataset <TaskModel> .Build <TaskModel>("set", new FHSyncConfig(), null, null);

            var task = new TaskModel
            {
                TaksName = taskName
            };
            var dataset = dataset1;

            //when
            var savedTask = dataset.Create(task);

            //then
            Assert.IsNotNull(savedTask.UID);
            Assert.AreEqual(1, dataset.GetPendingRecords().List().Count);

            var taskRead = dataset.Read(savedTask.UID);

            Assert.IsNotNull(taskRead);
            Assert.AreEqual(taskName, taskRead.TaksName);
        }
Esempio n. 2
0
        /// <summary>
        ///     Manage the specified sync data model that implements the IFHSyncModel.
        /// </summary>
        /// <param name="datasetId">
        ///     Dataset identifier. The datasetId needs to be unique for your app and will be used to name the
        ///     database collection in the cloud.
        /// </param>
        /// <param name="syncConfig">Sync config. If this is null, the global syncConfig will be used.</param>
        /// <param name="qp">A query parameter that will be passed to the cloud when initialise the dataset.</param>
        /// <typeparam name="T"> It should be a type that implements IFHSyncModel.</typeparam>
        public FHSyncDataset <T> Manage <T>(string datasetId, FHSyncConfig syncConfig, IDictionary <string, string> qp)
            where T : IFHSyncModel
        {
            FHSyncDataset <T> dataset;

            if (!_datasets.ContainsKey(datasetId))
            {
                dataset = FHSyncDataset <T> .Build <T>(datasetId,
                                                       null == syncConfig?_globalSyncConfig.Clone() : syncConfig.Clone(), qp, null);

                dataset.SyncNotificationHandler += (sender, e) => { OnSyncNotification(e); };
                _datasets[datasetId]             = dataset;
                _datasetsDelegates[datasetId]    = dataset.RunSyncLoop;
            }
            else
            {
                dataset = (FHSyncDataset <T>)_datasets[datasetId];
                if (null != syncConfig)
                {
                    dataset.SyncConfig = syncConfig;
                }
                if (null != qp)
                {
                    dataset.QueryParams = qp;
                }
            }

            return(dataset);
        }
        public async void TestDatasetSync()
        #endif
        {
            //clear db
            var setupRes = await FH.Cloud(string.Format("/syncTest/{0}", DatasetId), "DELETE", null, null);

            Assert.IsTrue(HttpStatusCode.OK.Equals(setupRes.StatusCode));

            var syncConfig = new FHSyncConfig();

            syncConfig.SyncFrequency        = 1;
            syncConfig.AutoSyncLocalUpdates = true;
            syncConfig.SyncCloud            = FHSyncConfig.SyncCloudType.Mbbas;
            syncConfig.CrashedCountWait     = 0;
            syncConfig.ResendCrashedUpdated = true;

            //make sure no existing data file exist
            _metaDataFilePath = FHSyncUtils.GetDataFilePath(DatasetId, ".sync.json");
            _dataFilePath     = FHSyncUtils.GetDataFilePath(DatasetId, ".data.json");
            _pendingFilePath  = FHSyncUtils.GetDataFilePath(DatasetId, ".pendings.json");

            TestUtils.DeleteFileIfExists(_metaDataFilePath);
            TestUtils.DeleteFileIfExists(_dataFilePath);
            TestUtils.DeleteFileIfExists(_pendingFilePath);

            Assert.IsFalse(File.Exists(_metaDataFilePath));
            Assert.IsFalse(File.Exists(_dataFilePath));
            Assert.IsFalse(File.Exists(_pendingFilePath));


            var tasksDataset = FHSyncDataset <TaskModel> .Build <TaskModel>(DatasetId, syncConfig, null, null);

            //since the dataset is saved on creation, make sure the data files exist
            TestUtils.AssertFileExists(_metaDataFilePath);
            TestUtils.AssertFileExists(_dataFilePath);
            TestUtils.AssertFileExists(_pendingFilePath);

            //Try to create a new Task
            var taskName = "task1";
            var task     = new TaskModel
            {
                TaksName  = taskName,
                Completed = false
            };

            task = tasksDataset.Create(task);

            var taskId = task.UID;

            Debug.WriteLine("Created Task Id = {0}", taskId);
            Assert.IsNotNull(taskId);

            //Now there should be one pending record
            var pendings            = tasksDataset.GetPendingRecords();
            var pendingRecordsCount = pendings.List().Count;

            Assert.AreEqual(1, pendingRecordsCount);

            var taskRead = tasksDataset.Read(taskId);

            Assert.IsNotNull(taskRead);
            Assert.IsTrue(taskRead.TaksName.Equals(taskName));

            Assert.IsTrue(tasksDataset.ShouldSync());

            var updatedTaskName = "updatedTask1";

            task.TaksName = updatedTaskName;
            tasksDataset.Update(task);

            //verify data is updated
            var readUpdated = tasksDataset.Read(taskId);

            Assert.IsNotNull(readUpdated);
            Assert.IsTrue(readUpdated.TaksName.Equals(updatedTaskName));

            //test data list
            var tasks = tasksDataset.List();

            Assert.AreEqual(1, tasks.Count);
            var listedTask = tasks[0];

            Assert.IsTrue(listedTask.TaksName.Equals(updatedTaskName));
            Assert.IsTrue(listedTask.Completed == false);
            Assert.IsTrue(listedTask.UID.Equals(taskId));


            pendings = tasksDataset.GetPendingRecords();
            var pendingsList = pendings.List();

            //updating an existing pending, so there should be still only 1 pending record
            Assert.AreEqual(1, pendingsList.Count);

            var pending = pendingsList.First().Value;
            //verify the pendingRecord's postData is the new updated data
            var postData = pending.PostData;

            Assert.IsTrue(updatedTaskName.Equals(postData.Data.TaksName));

            //run the syncLoop
            await tasksDataset.StartSyncLoop();

            //verify the data is created in the remote db
            var cloudRes = await FH.Cloud(string.Format("/syncTest/{0}", DatasetId), "GET", null, null);

            Debug.WriteLine("Got response " + cloudRes.RawResponse);
            Assert.IsNull(cloudRes.Error);
            var dbData = cloudRes.GetResponseAsJObject();

            Assert.AreEqual(1, (int)dbData["count"]);
            var taskNameInDb = (string)dbData["list"][0]["fields"]["taskName"];

            Assert.IsTrue(taskNameInDb.Equals(updatedTaskName));

            //there should be no pending data
            pendings = tasksDataset.GetPendingRecords();
            Assert.AreEqual(0, pendings.List().Count);

            var newTaskUid = (string)dbData["list"][0]["guid"];

            Assert.IsFalse(newTaskUid.Equals(taskId));
            var tasklistAfterUpdate = tasksDataset.List();

            Debug.WriteLine(tasklistAfterUpdate[0].ToString());

            //since the data is now created in db, the uid should be updated
            var readUpdatedAfterSync = tasksDataset.Read(newTaskUid);

            Assert.IsNotNull(readUpdatedAfterSync);
            Debug.WriteLine("readUpdatedAfterSync = " + readUpdatedAfterSync);

            //create a new record in remote db
            var taskToCreate = new TaskModel
            {
                TaksName  = "anotherTask",
                Completed = false
            };
            var createRecordReq = await FH.Cloud(string.Format("/syncTest/{0}", DatasetId), "POST", null, taskToCreate);

            Debug.WriteLine("Got response for creating new record: {0}", createRecordReq.RawResponse);
            Assert.IsNull(createRecordReq.Error);

            Thread.Sleep(1500);
            Assert.IsTrue(tasksDataset.ShouldSync());

            //run a sync loop
            await tasksDataset.StartSyncLoop();

            Thread.Sleep(9000);

            await tasksDataset.StartSyncLoop();

            //now we should see the new record is created locally
            var updatedTaskList = tasksDataset.List();

            Assert.AreEqual(2, updatedTaskList.Count);
            Debug.WriteLine("updatedTaskList[0] = " + updatedTaskList[0]);
            Debug.WriteLine("updatedTaskList[1] = " + updatedTaskList[1]);

            //verify that the saved files can be loaded again and will construct the same dataset
            var anotherDataset = FHSyncDataset <TaskModel> .Build <TaskModel>(DatasetId, syncConfig, null, null);

            Assert.IsNotNull(anotherDataset.HashValue);
            var tasksListInAnotherDataset = anotherDataset.List();

            Assert.AreEqual(2, tasksListInAnotherDataset.Count);
            foreach (var taskInAnotherDataset in tasksListInAnotherDataset)
            {
                Assert.IsNotNull(taskInAnotherDataset.UID);
                Assert.IsTrue(taskInAnotherDataset.TaksName.Equals("updatedTask1") ||
                              taskInAnotherDataset.TaksName.Equals("anotherTask"));
            }

            //test some failure cases
            var taskToUpdate = updatedTaskList[0];

            taskToUpdate.Completed = true;

            tasksDataset.Update(taskToUpdate);

            //make sure the next syncLoop will fail
            var setFailureRes = await FH.Cloud("/setFailure/true", "GET", null, null);

            Assert.IsNull(setFailureRes.Error);
            Assert.IsTrue((bool)setFailureRes.GetResponseAsJObject()["current"]);

            //run the syncloop again, this time it will fail
            await tasksDataset.StartSyncLoop();

            pendings = tasksDataset.GetPendingRecords();
            Assert.AreEqual(1, pendings.List().Count);

            var pendingRecord = pendings.List().Values.First();

            Assert.IsTrue(pendingRecord.Crashed);

            setFailureRes = await FH.Cloud("/setFailure/false", "GET", null, null);

            Assert.IsNull(setFailureRes.Error);
            Assert.IsFalse((bool)setFailureRes.GetResponseAsJObject()["current"]);

            //run another sync loop, this time there will be no pendings sent as the current update is crashed
            await tasksDataset.StartSyncLoop();

            //at the end of last loop, since we set the crashCountWait to be 0, the updates should be marked as not-crashed and will be sent in next loop
            await tasksDataset.StartSyncLoop();

            //there should be no more pendings
            pendings = tasksDataset.GetPendingRecords();
            Assert.AreEqual(0, pendings.List().Count);

            //verify the update is sent to the cloud
            var verifyUpdateRes =
                await FH.Cloud(string.Format("/syncTest/{0}/{1}", DatasetId, taskToUpdate.UID), "GET", null, null);

            var taskInDBJson = verifyUpdateRes.GetResponseAsJObject();

            Assert.IsTrue((bool)taskInDBJson["fields"]["completed"]);
        }