internal async Task <HttpMessageSendChangesResponse> GetEstimatedChangesCountAsync(HttpMessageSendChangesRequest httpMessage, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { // Get context from request message var ctx = httpMessage.SyncContext; // Set the context coming from the client this.SetContext(ctx); var changes = await base.GetEstimatedChangesCountAsync(httpMessage.Scope, cancellationToken, progress); var changesResponse = new HttpMessageSendChangesResponse(syncContext); changesResponse.ServerChangesSelected = changes.ServerChangesSelected; changesResponse.ClientChangesApplied = new DatabaseChangesApplied(); changesResponse.ServerStep = HttpStep.GetMoreChanges; changesResponse.ConflictResolutionPolicy = this.Options.ConflictResolutionPolicy; changesResponse.Changes = new ContainerSet(); changesResponse.BatchIndex = 0; changesResponse.IsLastBatch = true; changesResponse.RemoteClientTimestamp = changes.RemoteClientTimestamp; // Get the firt response to send back to client return(changesResponse); }
public HttpSendingServerChangesArgs(HttpMessageSendChangesResponse response, string host, SessionCache sessionCache, bool isSnapshot) : base(response.SyncContext, null, null) { this.Response = response; this.Host = host; this.SessionCache = sessionCache; this.IsSnapshot = isSnapshot; }
public HttpGettingServerChangesResponseArgs(HttpMessageSendChangesResponse response, string host) : base(response.SyncContext, null, null) { this.BatchIndex = response.BatchIndex; this.BatchCount = response.BatchCount; this.IsLastBatch = response.IsLastBatch; this.Changes = response.Changes; this.RemoteClientTimestamp = response.RemoteClientTimestamp; this.ServerChangesSelected = response.ServerChangesSelected; this.ClientChangesApplied = response.ClientChangesApplied; this.Host = host; }
internal async Task <HttpMessageSendChangesResponse> GetSnapshotAsync(HttpMessageSendChangesRequest httpMessage, SessionCache sessionCache, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { // TODO : check Snapshot with version and scopename // Check schema. // If client has stored the schema, the EnsureScope will not be called on server. if (this.Schema == null || !this.Schema.HasTables || !this.Schema.HasColumns) { var serverScopeInfo = await this.EnsureSchemaAsync(cancellationToken, progress).ConfigureAwait(false); this.Schema = serverScopeInfo.Schema; this.Schema.EnsureSchema(); } // Get context from request message var ctx = httpMessage.SyncContext; // Set the context coming from the client this.SetContext(ctx); // get changes var snap = await this.GetSnapshotAsync(this.Schema, cancellationToken, progress).ConfigureAwait(false); // if no snapshot, return empty response if (snap.ServerBatchInfo == null) { var changesResponse = new HttpMessageSendChangesResponse(ctx); changesResponse.ServerStep = HttpStep.GetSnapshot; changesResponse.BatchIndex = 0; changesResponse.IsLastBatch = true; changesResponse.RemoteClientTimestamp = 0; changesResponse.Changes = null; return(changesResponse); } sessionCache.RemoteClientTimestamp = snap.RemoteClientTimestamp; sessionCache.ServerBatchInfo = snap.ServerBatchInfo; // Get the firt response to send back to client return(await GetChangesResponseAsync(ctx, snap.RemoteClientTimestamp, snap.ServerBatchInfo, null, null, 0)); }
/// <summary> /// Get changes from /// </summary> internal async Task <HttpMessageSendChangesResponse> GetSnapshotAsync( HttpMessageSendChangesRequest httpMessage, SessionCache sessionCache, CancellationToken cancellationToken) { // Check schema. // If client has stored the schema, the EnsureScope will not be called on server. if (this.Schema == null || !this.Schema.HasTables || !this.Schema.HasColumns) { var(_, newSchema) = await this.EnsureSchemaAsync( httpMessage.SyncContext, this.Setup, cancellationToken).ConfigureAwait(false); newSchema.EnsureSchema(); this.Schema = newSchema; } // get changes var snap = await this.GetSnapshotAsync(httpMessage.SyncContext, httpMessage.Scope, this.Schema, this.Options.SnapshotsDirectory, this.Options.BatchDirectory, cancellationToken).ConfigureAwait(false); sessionCache.RemoteClientTimestamp = snap.remoteClientTimestamp; sessionCache.ServerBatchInfo = snap.serverBatchInfo; // if no snapshot, return empty response if (snap.serverBatchInfo == null) { var changesResponse = new HttpMessageSendChangesResponse(snap.context); changesResponse.ServerStep = HttpStep.GetSnapshot; changesResponse.BatchIndex = 0; changesResponse.IsLastBatch = true; changesResponse.RemoteClientTimestamp = snap.remoteClientTimestamp; changesResponse.Changes = new ContainerSet(); return(changesResponse); } // Get the firt response to send back to client return(GetChangesResponse(snap.context, snap.remoteClientTimestamp, snap.serverBatchInfo, null, 0, ConflictResolutionPolicy.ServerWins)); }
/// <summary> /// Create a response message content based on a requested index in a server batch info /// </summary> private HttpMessageSendChangesResponse GetChangesResponse(SyncContext syncContext, long remoteClientTimestamp, BatchInfo serverBatchInfo, DatabaseChangesSelected serverChangesSelected, int batchIndexRequested, ConflictResolutionPolicy policy) { // 1) Create the http message content response var changesResponse = new HttpMessageSendChangesResponse(syncContext); changesResponse.ChangesSelected = serverChangesSelected; changesResponse.ServerStep = HttpStep.GetChanges; changesResponse.ConflictResolutionPolicy = policy; // If nothing to do, just send back if (serverBatchInfo.InMemory || serverBatchInfo.BatchPartsInfo.Count == 0) { if (this.ClientConverter != null && serverBatchInfo.InMemoryData.HasRows) { BeforeSerializeRows(serverBatchInfo.InMemoryData, this.ClientConverter); } changesResponse.Changes = serverBatchInfo.InMemoryData.GetContainerSet(); changesResponse.BatchIndex = 0; changesResponse.IsLastBatch = true; changesResponse.RemoteClientTimestamp = remoteClientTimestamp; return(changesResponse); } // Get the batch part index requested var batchPartInfo = serverBatchInfo.BatchPartsInfo.First(d => d.Index == batchIndexRequested); // if we are not in memory, we set the BI in session, to be able to get it back on next request // create the in memory changes set var changesSet = new SyncSet(Schema.ScopeName); foreach (var table in Schema.Tables) { DbSyncAdapter.CreateChangesTable(Schema.Tables[table.TableName, table.SchemaName], changesSet); } batchPartInfo.LoadBatch(changesSet, serverBatchInfo.GetDirectoryFullPath()); // if client request a conversion on each row, apply the conversion if (this.ClientConverter != null && batchPartInfo.Data.HasRows) { BeforeSerializeRows(batchPartInfo.Data, this.ClientConverter); } changesResponse.Changes = batchPartInfo.Data.GetContainerSet(); changesResponse.BatchIndex = batchIndexRequested; changesResponse.IsLastBatch = batchPartInfo.IsLastBatch; changesResponse.RemoteClientTimestamp = remoteClientTimestamp; changesResponse.ServerStep = batchPartInfo.IsLastBatch ? HttpStep.GetChanges : HttpStep.GetChangesInProgress; // If we have only one bpi, we can safely delete it if (batchPartInfo.IsLastBatch) { // delete the folder (not the BatchPartInfo, because we have a reference on it) if (this.Options.CleanFolder) { var shouldDeleteFolder = true; if (!string.IsNullOrEmpty(this.Options.SnapshotsDirectory)) { var dirInfo = new DirectoryInfo(serverBatchInfo.DirectoryRoot); var snapInfo = new DirectoryInfo(this.Options.SnapshotsDirectory); shouldDeleteFolder = dirInfo.FullName != snapInfo.FullName; } if (shouldDeleteFolder) { serverBatchInfo.TryRemoveDirectory(); } } } return(changesResponse); }