public async Task InitializeAsync(IMobileServiceLocalStore store, IMobileServiceSyncHandler handler, StoreTrackingOptions trackingOptions) { if (store == null) { throw new ArgumentNullException("store"); } handler = handler ?? new MobileServiceSyncHandler(); this.initializeTask = new TaskCompletionSource <object>(); using (await this.storeQueueLock.WriterLockAsync()) { this.Handler = handler; this.Store = store; this.storeTrackingOptions = trackingOptions; this.syncQueue = new ActionBlock(); await this.Store.InitializeAsync(); this.opQueue = await OperationQueue.LoadAsync(store); this.settings = new MobileServiceSyncSettingsManager(store); this.localOperationsStore = StoreChangeTrackerFactory.CreateTrackedStore(store, StoreOperationSource.Local, trackingOptions, this.client.EventManager, this.settings); this.initializeTask.SetResult(null); } }
public Task CancelAndDiscardItemAsync(MobileServiceTableOperationError error) { string itemId = error.Item.Value <string>(MobileServiceSystemColumns.Id); return(this.ExecuteOperationSafeAsync(itemId, error.TableName, async() => { await this.TryCancelOperation(error); using (var trackedStore = StoreChangeTrackerFactory.CreateTrackedStore(this.Store, StoreOperationSource.LocalConflictResolution, this.storeTrackingOptions, this.client.EventManager, this.settings)) { await trackedStore.DeleteAsync(error.TableName, itemId); } })); }
public async Task PurgeAsync(string tableName, MobileServiceTableKind tableKind, string queryId, string query, bool force, CancellationToken cancellationToken) { await this.EnsureInitializedAsync(); var table = await this.GetTable(tableName); var queryDescription = MobileServiceTableQueryDescription.Parse(tableName, query); using (var trackedStore = StoreChangeTrackerFactory.CreateTrackedStore(this.Store, StoreOperationSource.LocalPurge, this.storeTrackingOptions, this.client.EventManager, this.settings)) { var action = new PurgeAction(table, tableKind, queryId, queryDescription, force, this, this.opQueue, this.client.EventManager, this.settings, this.Store, cancellationToken); await this.ExecuteSyncAction(action); } }
public Task UpdateOperationAsync(MobileServiceTableOperationError error, JObject item) { string itemId = error.Item.Value <string>(MobileServiceSystemColumns.Id); return(this.ExecuteOperationSafeAsync(itemId, error.TableName, async() => { await this.TryUpdateOperation(error, item); if (error.OperationKind != MobileServiceTableOperationKind.Delete) { using (var trackedStore = StoreChangeTrackerFactory.CreateTrackedStore(this.Store, StoreOperationSource.LocalConflictResolution, this.storeTrackingOptions, this.client.EventManager, this.settings)) { await trackedStore.UpsertAsync(error.TableName, item, fromServer: true); } } })); }
public async Task PushAsync(CancellationToken cancellationToken, MobileServiceTableKind tableKind, params string[] tableNames) { await this.EnsureInitializedAsync(); // use empty handler if its not a standard table push var handler = tableKind == MobileServiceTableKind.Table ? this.Handler : new MobileServiceSyncHandler(); using (var trackedStore = StoreChangeTrackerFactory.CreateTrackedStore(this.Store, StoreOperationSource.ServerPush, this.storeTrackingOptions, this.client.EventManager, this.settings)) { var action = new PushAction(this.opQueue, trackedStore, tableKind, tableNames, handler, this.client, this, cancellationToken); await this.ExecuteSyncAction(action); } }
/// <summary> /// Pulls all items that match the given query from the associated remote table. /// </summary> /// <param name="tableName">The name of table to pull</param> /// <param name="tableKind">The kind of table</param> /// <param name="queryId">A string that uniquely identifies this query and is used to keep track of its sync state.</param> /// <param name="query">An OData query that determines which items to /// pull from the remote table.</param> /// <param name="options">An instance of <see cref="MobileServiceRemoteTableOptions"/></param> /// <param name="parameters">A dictionary of user-defined parameters and values to include in /// the request URI query string.</param> /// <param name="relatedTables"> /// List of tables that may have related records that need to be push before this table is pulled down. /// When no table is specified, all tables are considered related. /// </param> /// <param name="reader">An instance of <see cref="MobileServiceObjectReader"/></param> /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken"/> token to observe /// </param> /// <param name="pullOptions"> /// PullOptions that determine how to pull data from the remote table /// </param> /// <returns> /// A task that completes when pull operation has finished. /// </returns> public async Task PullAsync(string tableName, MobileServiceTableKind tableKind, string queryId, string query, MobileServiceRemoteTableOptions options, IDictionary <string, string> parameters, IEnumerable <string> relatedTables, MobileServiceObjectReader reader, CancellationToken cancellationToken, PullOptions pullOptions) { await this.EnsureInitializedAsync(); if (parameters != null) { if (parameters.Keys.Any(k => k.Equals(MobileServiceTable.IncludeDeletedParameterName, StringComparison.OrdinalIgnoreCase))) { throw new ArgumentException("The key '{0}' is reserved and cannot be specified as a query parameter.".FormatInvariant(MobileServiceTable.IncludeDeletedParameterName)); } } var table = await this.GetTable(tableName); var queryDescription = MobileServiceTableQueryDescription.Parse(this.client.MobileAppUri, tableName, query); // local schema should be same as remote schema otherwise push can't function if (queryDescription.Selection.Any() || queryDescription.Projections.Any()) { throw new ArgumentException("Pull query with select clause is not supported.", "query"); } bool isIncrementalSync = !String.IsNullOrEmpty(queryId); if (isIncrementalSync) { if (queryDescription.Ordering.Any()) { throw new ArgumentException("Incremental pull query must not have orderby clause.", "query"); } if (queryDescription.Top.HasValue || queryDescription.Skip.HasValue) { throw new ArgumentException("Incremental pull query must not have skip or top specified.", "query"); } } if (!options.HasFlag(MobileServiceRemoteTableOptions.OrderBy) && queryDescription.Ordering.Any()) { throw new ArgumentException("The supported table options does not include orderby.", "query"); } if (!options.HasFlag(MobileServiceRemoteTableOptions.Skip) && queryDescription.Skip.HasValue) { throw new ArgumentException("The supported table options does not include skip.", "query"); } if (!options.HasFlag(MobileServiceRemoteTableOptions.Top) && queryDescription.Top.HasValue) { throw new ArgumentException("The supported table options does not include top.", "query"); } // let us not burden the server to calculate the count when we don't need it for pull queryDescription.IncludeTotalCount = false; using (var store = StoreChangeTrackerFactory.CreateTrackedStore(this.Store, StoreOperationSource.ServerPull, this.storeTrackingOptions, this.client.EventManager, this.settings)) { var action = new PullAction(table, tableKind, this, queryId, queryDescription, parameters, relatedTables, this.opQueue, this.settings, store, options, pullOptions, reader, cancellationToken); await this.ExecuteSyncAction(action); } }