public void FromRecord_Result() { TrackedChangeRecord record = new TrackedChangeRecord() { Id = Guid.NewGuid(), ActorName = "actor", AggregateId = Guid.NewGuid(), AggregateClassId = Guid.NewGuid(), EntityId = Guid.NewGuid(), EntityClassId = Guid.NewGuid(), ChangeDataClassName = "TestChangeData", ChangeDataJson = "{\"Foo\":\"bar\"}", ChangeTime = DateTime.Now }; TrackedChange change = sut.FromRecord(record); Assert.Equal(record.Id, change.Id); Assert.Equal(record.ActorName, change.ActorName); Assert.Equal(record.AggregateId, change.AggregateId); Assert.Equal(record.AggregateClassId, change.AggregateClassId); Assert.Equal(record.EntityId, change.EntityId); Assert.Equal(record.EntityClassId, change.EntityClassId); Assert.Equal(typeof(TestChangeData), change.ChangeData.GetType()); Assert.Equal("bar", ((TestChangeData)change.ChangeData).Foo); Assert.Equal(record.ChangeTime, change.ChangeTime); }
public async Task AddChange_And_SaveChanges_PublishesEvents() { TestChangeData changeData = new TestChangeData(); trackedChangeRecordConverter.ToRecord(null).ReturnsForAnyArgs(ci => { TrackedChange x = ci.ArgAt <TrackedChange>(0); return(new TrackedChangeRecord() { Id = x.Id, AggregateId = x.AggregateId, AggregateClassId = x.AggregateClassId, EntityId = x.EntityId, EntityClassId = x.EntityClassId }); }); TrackedChange tc = sut.AddChange(changeData, aggregateId, aggregateClassId, entityId, entityClassId); await sut.SaveChangesAsync(); eventBus.Received(1).PublishAsync(Arg.Is <IEventMessage <TrackedChangeAdded> >( x => x.Event.AggregateId == aggregateId && x.Event.EntityClassId == entityClassId && x.Event.EntityId == entityId && x.Event.TrackedChangeId == tc.Id)); }
public void FindChanges_ReturnsChanges() { TrackedChangeRecord record = new TrackedChangeRecord(); TrackedChange change = new TrackedChange(Guid.NewGuid(), new TestChangeData(), "", null, null, null, null, null, DateTimeOffset.Now); trackedChangeRecordConverter.FromRecord(record).Returns(change); crudRepository.Attach(record); List <TrackedChange> changes = sut.FindChanges().ToList(); Assert.Equal(1, changes.Count); Assert.Contains(change, changes); }
public async Task CommitChangesAsync(TrackedChange trackedChange) { if (this.Config.LatestDeltaToken == trackedChange.State) { Logger.Debug("Delta token is already up to date"); return; } Logger.Debug("OneDriveAdapter committing tracked change " + trackedChange.State); this.Config.LatestDeltaToken = trackedChange.State; await this.Relationship.SaveAsync().ConfigureAwait(false); }
public async Task GetChangeAsync_ReturnsChange() { TrackedChangeRecord record = new TrackedChangeRecord() { Id = Guid.NewGuid() }; TrackedChange change = new TrackedChange(record.Id, new TestChangeData(), "", null, null, null, null, null, DateTimeOffset.Now); trackedChangeRecordConverter.FromRecord(record).Returns(change); crudRepository.Attach(record); TrackedChange change2 = await sut.GetChangeAsync(change.Id); Assert.Equal(change, change2); }
public void AddChange_ReturnsChange() { TestChangeData changeData = new TestChangeData(); TrackedChange change = sut.AddChange(changeData, aggregateId, aggregateClassId, entityId, entityClassId); trackedChangeRecordConverter.ToRecord(null).ReturnsForAnyArgs( new TrackedChangeRecord()); Assert.Equal(aggregateId, change.AggregateId); Assert.Equal(aggregateClassId, change.AggregateClassId); Assert.Equal(entityId, change.EntityId); Assert.Equal(entityClassId, change.EntityClassId); Assert.Equal(changeData, change.ChangeData); Assert.Equal(actorContext.CurrentActorName, change.ActorName); Assert.Equal(FakeClock.Now, change.ChangeTime); }
private async Task ChangeNotificationThreadMain() { while (!this.changeNotificationCancellationTokenSource.IsCancellationRequested) { TrackedChange changes = null; try { changes = await this.GetChangesAsync().ConfigureAwait(false); } catch (Exception exception) { Logger.LogException(exception, "Failed to pull changes from OneDrive"); } if (changes != null && changes.Changes.Any() && !string.Equals(changes.State, this.Config.LatestDeltaToken, StringComparison.Ordinal)) { ItemsChangedEventArgs eventArgs = new ItemsChangedEventArgs(); foreach (IChangeTrackedAdapterItem change in changes.Changes) { eventArgs.Changes.Add( new ItemChange( change.FullName, ItemChangeType.None)); } this.ItemChanged?.Invoke(this, eventArgs); } Logger.Debug("OneDriveAdapter.ChangeNotificationThreadMain delay for " + OneDriveChangeNotificationPollingInterval); this.nextNotificationPollTime = DateTime.Now.Add( OneDriveChangeNotificationPollingInterval); await Task.Delay( OneDriveChangeNotificationPollingInterval, this.changeNotificationCancellationTokenSource.Token) .ConfigureAwait(false); } }
public void ToRecord_Result() { TrackedChange change = new TrackedChange(Guid.NewGuid(), new TestChangeData() { Foo = "bar" }, "actor", Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), DateTimeOffset.Now); TrackedChangeRecord record = sut.ToRecord(change); Assert.Equal(change.Id, record.Id); Assert.Equal(change.ActorName, record.ActorName); Assert.Equal(change.UserId, record.UserId); Assert.Equal(change.AggregateId, record.AggregateId); Assert.Equal(change.AggregateClassId, record.AggregateClassId); Assert.Equal(change.EntityId, record.EntityId); Assert.Equal(change.EntityClassId, record.EntityClassId); Assert.Equal("TestChangeData", record.ChangeDataClassName); Assert.Equal("bar", JObject.Parse(record.ChangeDataJson)["Foo"]); Assert.Equal(change.ChangeTime, record.ChangeTime); }
public async Task <TrackedChange> GetChangesAsync() { if (!this.Config.TargetPath.StartsWith("OneDrive", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("Expected TargetPath to start with 'OneDrive/'"); } // TargetPath has the form OneDrive/path/to/folder. We need the actual path /path/to/folder, so strip off the // first 8 characters of the path. string rootPath = this.Config.TargetPath.Substring(8); OneDriveDeltaView deltaView; try { deltaView = await this.oneDriveClient.GetDeltaView(rootPath, this.Config.LatestDeltaToken).ConfigureAwait(false); } catch (OneDriveHttpException httpException) when(httpException.ErrorResponse != null && httpException.ErrorResponse.Code == "resyncRequired") { Logger.Warning("Change tracking for adapter {0} failed and a full resync is required.", this.Configuration.Id); // If the delta token is stale (or possibly some other condition), the service may reject the delta token and // require that a resync be performed using a new delta view. When this occurs, the Location header of the // response will contain the new link for acquiring the new delta view. KeyValuePair <string, IList <string> > locationHeader = httpException.ResponseHeaders.FirstOrDefault( h => string.Equals(h.Key, "Location", StringComparison.OrdinalIgnoreCase)); // Verify that the location header is present if (string.IsNullOrEmpty(locationHeader.Key) || !locationHeader.Value.Any()) { throw new OneDriveHttpException("A location was not provided by the service during a delta token refresh.", httpException); } // Get the new delta view try { deltaView = await this.oneDriveClient.GetDeltaView(locationHeader.Value.First()).ConfigureAwait(false); } catch (Exception exception) { throw new OneDriveHttpException("Exception thrown during a delta token refresh.", exception); } } Logger.Debug( "OneDriveAdapter successfully retrieved tracked change {0} with {1} changes.", deltaView.Token, deltaView.Items.Count); TrackedChange trackedChange = new TrackedChange(deltaView.Token); // Per https://dev.onedrive.com/items/view_delta.htm // The same item may appear more than once in a delta feed, for various reasons. You should use the last // occurrence you see. foreach (Item item in deltaView.Items) { var existingItemIndex = trackedChange.Changes.FindIndex(c => c.UniqueId == item.Id); if (existingItemIndex > -1) { trackedChange.Changes[existingItemIndex] = new OneDriveAdapterItem(item, null, this); } else { trackedChange.Changes.Add(new OneDriveAdapterItem(item, null, this)); } } return(trackedChange); }