#if AWS_ASYNC_API using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; using Amazon.CognitoSync.Model; namespace Amazon.CognitoSync.SyncManager.Internal { /// /// Remote data storage using Cognito Sync service on which we can invoke /// actions like creating a dataset or record. /// public partial class CognitoSyncStorage : IDisposable { #region ListDataset /// /// Gets a list of /// /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// public async Task> ListDatasetMetadataAsync(CancellationToken cancellationToken) { return await PopulateListDatasetMetadata(null, new List(), cancellationToken).ConfigureAwait(false); } private async Task> PopulateListDatasetMetadata(string nextToken, List datasets, CancellationToken cancellationToken) { ListDatasetsRequest request = new ListDatasetsRequest(); // a large enough number to reduce # of requests request.MaxResults = 64; request.NextToken = nextToken; ListDatasetsResponse response = await client.ListDatasetsAsync(request, cancellationToken).ConfigureAwait(false); foreach (Amazon.CognitoSync.Model.Dataset dataset in response.Datasets) { datasets.Add(ModelToDatasetMetadata(dataset)); } nextToken = response.NextToken; if (nextToken != null) { await PopulateListDatasetMetadata(nextToken, datasets, cancellationToken).ConfigureAwait(false); } return datasets; } #endregion #region ListUpdates /// /// Gets a list of records which have been updated since lastSyncCount /// (inclusive). If the value of a record equals null, then the record is /// deleted. If you pass 0 as lastSyncCount, the full list of records will be /// returned. /// /// A list of records which have been updated since lastSyncCount. /// Dataset name. /// Last sync count. /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// public async Task ListUpdatesAsync(string datasetName, long lastSyncCount, CancellationToken cancellationToken) { return await PopulateListUpdatesAsync(datasetName, lastSyncCount, new List(), null, cancellationToken).ConfigureAwait(false); } private async Task PopulateListUpdatesAsync(string datasetName, long lastSyncCount, List records, string nextToken, CancellationToken cancellationToken) { ListRecordsRequest request = new ListRecordsRequest(); request.IdentityPoolId = identityPoolId; request.IdentityId = this.GetCurrentIdentityId(); request.DatasetName = datasetName; request.LastSyncCount = lastSyncCount; // mark it large enough to reduce # of requests request.MaxResults = 1024; request.NextToken = nextToken; ListRecordsResponse listRecordsResponse = await client.ListRecordsAsync(request, cancellationToken).ConfigureAwait(false); foreach (Amazon.CognitoSync.Model.Record remoteRecord in listRecordsResponse.Records) { records.Add(ModelToRecord(remoteRecord)); } // update last evaluated key nextToken = listRecordsResponse.NextToken; if (nextToken != null) await PopulateListUpdatesAsync(datasetName, lastSyncCount, records, nextToken, cancellationToken).ConfigureAwait(false); DatasetUpdates updates = new DatasetUpdates( datasetName, records, listRecordsResponse.DatasetSyncCount, listRecordsResponse.SyncSessionToken, listRecordsResponse.DatasetExists, listRecordsResponse.DatasetDeletedAfterRequestedSyncCount, listRecordsResponse.MergedDatasetNames ); return updates; } #endregion #region PutRecords /// /// Post updates to remote storage. Each record has a sync count. If the sync /// count doesn't match what's on the remote storage, i.e. the record is /// modified by a different device, this operation throws ConflictException. /// Otherwise it returns a list of records that are updated successfully. /// /// The records. /// Dataset name. /// Records. /// Sync session token. /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// /// public async Task> PutRecordsAsync(string datasetName, List records, string syncSessionToken, CancellationToken cancellationToken) { UpdateRecordsRequest request = new UpdateRecordsRequest(); request.DatasetName = datasetName; request.IdentityPoolId = identityPoolId; request.IdentityId = this.GetCurrentIdentityId(); request.SyncSessionToken = syncSessionToken; // create patches List patches = new List(); foreach (Record record in records) { patches.Add(RecordToPatch(record)); } request.RecordPatches = patches; List updatedRecords = new List(); try { UpdateRecordsResponse updateRecordsResponse = await client.UpdateRecordsAsync(request, cancellationToken).ConfigureAwait(false); foreach (Amazon.CognitoSync.Model.Record remoteRecord in updateRecordsResponse.Records) { updatedRecords.Add(ModelToRecord(remoteRecord)); } return updatedRecords; } catch (Exception ex) { throw HandleException(ex, "Failed to update records in dataset: " + datasetName); } } #endregion #region DeleteDataset /// /// Deletes a dataset. /// /// Dataset name. /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// public async Task DeleteDatasetAsync(string datasetName, CancellationToken cancellationToken) { DeleteDatasetRequest request = new DeleteDatasetRequest(); request.IdentityPoolId = identityPoolId; request.IdentityId = this.GetCurrentIdentityId(); request.DatasetName = datasetName; try { await client.DeleteDatasetAsync(request, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { throw HandleException(ex, "Failed to delete dataset: " + datasetName); } } #endregion #region GetDatasetMetadata /// /// Retrieves the metadata of a dataset. /// /// Dataset name. /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// /// public async Task GetDatasetMetadataAsync(string datasetName, CancellationToken cancellationToken) { DescribeDatasetRequest request = new DescribeDatasetRequest(); request.IdentityPoolId = identityPoolId; request.IdentityId = this.GetCurrentIdentityId(); request.DatasetName = datasetName; try { DescribeDatasetResponse describeDatasetResponse = await client.DescribeDatasetAsync(request, cancellationToken).ConfigureAwait(false); return ModelToDatasetMetadata(describeDatasetResponse.Dataset); } catch (Exception ex) { throw new DataStorageException("Failed to get metadata of dataset: " + datasetName, ex); } } #endregion } } #endif