Reputation: 721
I'm working on an App which uses Xamarin.Forms and Azure App Service. The user must explicitly execute a data sync. When the user starts a data sync a lot of this methods are executed to get the current data from the server:
await this.ISyncTable.PullAsync(queryId, query, cancellationToken).ConfigureAwait(false);
My problem: The application can get into an inconsistent state. For example when the user closes the App before the data sync is completed. In this state the App is not usable.
Edit:
To make it easier to understand: Let's assume i have a table "ToDoItem" and "ToDoCategory". The user starts a data sync. The data sync runs and the all ToDoItems are successfully retrieved . In the next step the data sync will get the ToDoCategories (another call to PullAsync) but before this the user closes the app. Now i have all ToDoItems but no ToDoCategories. But the App is not useable with no ToDoCategories. This is a really simple example. The data structure is much more complex in the real project. There are a lot of dependencies between the entities.
It is no solution to log the sync error / cancellation and prompt the user at the next app start for another sync. Assume on the next app start the user has no internet connection and cannot perform a data sync. I cannot lock the app until the next successful data sync.
Is there a way to run multiple PullAsync operations in a transaction?
Upvotes: -1
Views: 647
Reputation: 1627
Is there a way to run multiple PullAsync operations in a transaction?
Short answer is no, there isn't. Set a flag in when all your PullAsync operations are complete, or keep track of which tables have synced successfully.
It is no solution to log the sync error / cancellation and prompt the user at the next app start for another sync. Assume on the next app start the user has no internet connection and cannot perform a data sync. I cannot lock the app unitl the next successful data sync.
What is your app's expected behavior on the second run if the user started the sync but then left the app before sync completed? Finish the sync? Prompt the user to start again?
Also consider the app could probably continue syncing in the background after the user has left. In iOS you have to coordinate with the operating system using UIApplication beginBackgroundTaskWithExpirationHandler
.
Upvotes: 1
Reputation: 18465
My problem: The application can get into an inconsistent state. For example when the user closes the App before the data sync is completed. In this state the App is not usable.
If you specify the query id (non-null), then you would use the Incremental Sync for pulling operations. As the official document mentioned about Incremental Sync:
the first parameter to the pull operation is a query name that is used only on the client. If you use a non-null query name, the Azure Mobile SDK performs an incremental sync. Each time a pull operation returns a set of results, the latest updatedAt timestamp from that result set is stored in the SDK local system tables. Subsequent pull operations retrieve only records after that timestamp.
After successfully retrieve the data and update to your local data store, then the client SDK would update/insert the __config
table with the latest updatedAt timestamp from the pulled result along with the id equals deltaToken|{table-name}|{query-id}
for your SQLite db as follows:
Additionally, after retrieve the records, the client SDK would execute the following sql statement for updating your local data store:
Assuming you have retrieved 50 records for TodoItem
table.
BEGIN TRANSACTION
INSERT OR IGNORE INTO [TodoItem] ([id]) VALUES (@p0),(@p1),(@p2),(@p3),(@p4),(@p5),(@p6),(@p7),(@p8),(@p9),(@p10),(@p11),(@p12),(@p13),(@p14),(@p15),(@p16),(@p17),(@p18),(@p19),(@p20),(@p21),(@p22),(@p23),(@p24),(@p25),(@p26),(@p27),(@p28),(@p29),(@p30),(@p31),(@p32),(@p33),(@p34),(@p35),(@p36),(@p37),(@p38),(@p39),(@p40),(@p41),(@p42),(@p43),(@p44),(@p45),(@p46),(@p47),(@p48),(@p49)
UPDATE [TodoItem] SET [Text] = @p0,[UserId] = @p1 WHERE [id] = @p2
UPDATE [TodoItem] SET [Text] = @p0,[UserId] = @p1 WHERE [id] = @p2
.
.
COMMIT TRANSACTION
BEGIN TRANSACTION
INSERT OR IGNORE INTO [__config] ([id]) VALUES (@p0)
UPDATE [__config] SET [value] = @p0 WHERE [id] = @p1
COMMIT TRANSACTION
The default MaxPageSize
for pullasync
is 50, the client would automatically send multiple requests if three has more data. Note after retrieve records in page, the retrieved data would update to your local data store, then the next page request would be sent. Per my understanding, if the user closes the App before the data sync is completed, the data would not be updated to the latest, when the user open the app again, then the missing data would be updated to your data store based on the latest updatedAt timestamp.
Upvotes: 0