Skip to content

Commit

Permalink
(#38) PullAsync complete (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianhall authored Aug 26, 2024
1 parent 08482b3 commit a71f713
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 15 deletions.
61 changes: 61 additions & 0 deletions src/CommunityToolkit.Datasync.Client/Offline/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,67 @@ namespace CommunityToolkit.Datasync.Client.Offline;
/// </summary>
public static class Extensions
{
/// <summary>
/// Pulls the changes from the remote service for the specified dataset
/// </summary>
/// <param name="dataset">The dataset to pull from the remote service.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
/// <returns>The results of the pull operation.</returns>
public static Task<PullResult> PullAsync<TEntity>(this DbSet<TEntity> dataset, CancellationToken cancellationToken = default) where TEntity : class
=> dataset.PullAsync(new PullOptions(), cancellationToken);

/// <summary>
/// Pulls the changes from the remote service for the specified dataset
/// </summary>
/// <param name="dataset">The dataset to pull from the remote service.</param>
/// <param name="options">The options to use on this pull request.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
/// <returns>The results of the pull operation.</returns>
public static Task<PullResult> PullAsync<TEntity>(this DbSet<TEntity> dataset, PullOptions options, CancellationToken cancellationToken = default) where TEntity : class
{
DbContext context = dataset.GetService<ICurrentDbContext>().Context;
if (context is OfflineDbContext offlineContext)
{
return offlineContext.PullAsync([typeof(TEntity)], options, cancellationToken);
}
else
{
throw new DatasyncException($"Provided dataset is not a part of an {nameof(OfflineDbContext)}");
}
}

/// <summary>
/// Pulls the changes from the remote service for all synchronizable entities.
/// </summary>
/// <param name="context">The offline database context to use.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
/// <returns>The results of the pull operation.</returns>
[ExcludeFromCodeCoverage]
public static Task<PullResult> PullAsync(this OfflineDbContext context, CancellationToken cancellationToken = default)
=> context.PullAsync(context.QueueManager.GetSynchronizableEntityTypes(), new PullOptions(), cancellationToken);

/// <summary>
/// Pulls the changes from the remote service for all synchronizable entities.
/// </summary>
/// <param name="context">The offline database context to use.</param>
/// <param name="options">The options to use on this pull request.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
/// <returns>The results of the pull operation.</returns>
[ExcludeFromCodeCoverage]
public static Task<PullResult> PullAsync(this OfflineDbContext context, PullOptions options, CancellationToken cancellationToken = default)
=> context.PullAsync(context.QueueManager.GetSynchronizableEntityTypes(), options, cancellationToken);

/// <summary>
/// Pulls the changes from the remote service for the specified synchronizable entities.
/// </summary>
/// <param name="context">The offline database context to use.</param>
/// <param name="entityTypes">The list of entity types to pull.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
/// <returns>The results of the pull operation.</returns>
[ExcludeFromCodeCoverage]
public static Task<PullResult> PullAsync(this OfflineDbContext context, IEnumerable<Type> entityTypes, CancellationToken cancellationToken = default)
=> context.PullAsync(entityTypes, new PullOptions(), cancellationToken);

/// <summary>
/// Pushes the pending operations against the remote service for the provided dataset
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public Task<PullResult> PullAsync(IEnumerable<Type> entityTypes, PullOptions pul
return new PullRequest()
{
EntityType = type,
QueryId = PullRequestBuilder.GetQueryIdFromQuery(type, entityOptions.QueryDescription),
QueryId = PullRequestBuilder.GetQueryIdFromQuery(string.Empty, type, entityOptions.QueryDescription),
HttpClient = entityOptions.HttpClient,
Endpoint = entityOptions.Endpoint,
QueryDescription = entityOptions.QueryDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ public async Task<PullResult> ExecuteAsync(IEnumerable<PullRequest> requests, Pu

foreach (PullRequest request in requests)
{
request.QueryId = !string.IsNullOrEmpty(request.QueryId) ? request.QueryId : PullRequestBuilder.GetQueryIdFromQuery(request.EntityType, request.QueryDescription);
DateTimeOffset lastSynchronization = await context.DeltaTokenStore.GetDeltaTokenAsync(request.QueryId, cancellationToken).ConfigureAwait(false);
PrepareQueryDescription(request.QueryDescription, lastSynchronization);
serviceRequestQueue.Enqueue(request);
Expand Down
29 changes: 23 additions & 6 deletions src/CommunityToolkit.Datasync.Client/Offline/PullRequestBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ public PullRequestBuilder SetParallelOperations(int parallelOperations)
return this;
}

/// <summary>
/// Determines whether to save the delta-token after every service request, or just after all the requests
/// are completed.
/// </summary>
/// <param name="enabled">If true, save after every request.</param>
/// <returns>The builder for chaining</returns>
public PullRequestBuilder SaveAfterEveryServiceRequest(bool enabled)
{
this.pullOptions.SaveAfterEveryServiceRequest = enabled;
return this;
}

/// <summary>
/// Adds a pull request for the default query as setup in the <see cref="OfflineDbContext.OnDatasyncInitialization(DatasyncOfflineOptionsBuilder)"/>
/// method of your database context.
Expand All @@ -60,7 +72,7 @@ public PullRequestBuilder AddPullRequest<TEntity>() where TEntity : class
EntityType = typeof(TEntity),
HttpClient = options.HttpClient,
QueryDescription = options.QueryDescription,
QueryId = GetQueryIdFromQuery(typeof(TEntity), options.QueryDescription)
QueryId = GetQueryIdFromQuery(string.Empty, typeof(TEntity), options.QueryDescription)
};
this.requests[request.QueryId] = request;
return this;
Expand Down Expand Up @@ -96,7 +108,7 @@ public PullRequestBuilder AddPullRequest<TEntity>(Action<PullRequest<TEntity>> c
EntityType = request.EntityType,
HttpClient = request.HttpClient,
QueryDescription = queryDescription,
QueryId = string.IsNullOrEmpty(request.QueryId) ? GetQueryIdFromQuery(request.EntityType, queryDescription) : request.QueryId
QueryId = GetQueryIdFromQuery(request.QueryId, request.EntityType, queryDescription)
};
this.requests[storedRequest.QueryId] = storedRequest;
return this;
Expand All @@ -106,20 +118,25 @@ public PullRequestBuilder AddPullRequest<TEntity>(Action<PullRequest<TEntity>> c
/// Obtain a query ID from the query and entity type. This is used when the developer does
/// not specify a query ID.
/// </summary>
/// <param name="queryId">The specified query ID</param>
/// <param name="entityType">The entity type.</param>
/// <param name="query">The query,</param>
/// <returns></returns>
internal static string GetQueryIdFromQuery(Type entityType, QueryDescription query)
internal static string GetQueryIdFromQuery(string queryId, Type entityType, QueryDescription query)
{
string odataQuery = query.ToODataQueryString();
if (string.IsNullOrEmpty(odataQuery))
{
return entityType.FullName!;
}

byte[] bytes = Encoding.UTF8.GetBytes(odataQuery);
byte[] hashBytes = MD5.HashData(bytes);
string queryId = BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLower();
if (string.IsNullOrEmpty(queryId))
{
byte[] bytes = Encoding.UTF8.GetBytes(odataQuery);
byte[] hashBytes = MD5.HashData(bytes);
queryId = BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLower();
}

return $"q-{entityType.FullName!}-{queryId}";
}

Expand Down
Loading

0 comments on commit a71f713

Please sign in to comment.