public async Task ResolveWhenScriptAdded() { using (var store1 = GetDocumentStore()) using (var store2 = GetDocumentStore()) { await GenerateConflicts(store1, store2); var config = new ConflictSolver { ResolveByCollection = new Dictionary <string, ScriptResolver> { { "Users", new ScriptResolver { Script = "return {'Name':'Resolved'}" } } } }; await SetupReplicationAsync(store1, config, store2); Assert.True(WaitForDocument <User>(store1, "foo/bar", u => u.Name == "Resolved")); Assert.True(WaitForDocument <User>(store2, "foo/bar", u => u.Name == "Resolved")); } }
private void HandleConflictResolverChange(DatabaseRecord newRecord) { if (newRecord == null) { ConflictSolverConfig = null; return; } if (ConflictSolverConfig == null && newRecord.ConflictSolverConfig == null) { return; } var conflictSolverChanged = ConflictSolverConfig?.ConflictResolutionChanged(newRecord.ConflictSolverConfig) ?? true; if (conflictSolverChanged) { if (_log.IsInfoEnabled) { _log.Info("Conflict resolution was change."); } ConflictSolverConfig = newRecord.ConflictSolverConfig; ConflictResolver.RunConflictResolversOnce(); } }
/// <summary> /// Called when [activated]. /// </summary> /// <param name="disposables">The disposables.</param> protected override void OnActivated(CompositeDisposable disposables) { BindOverlay(); ReactiveUI.MessageBus.Current.Listen <NavigationEventArgs>() .Subscribe(s => { ReactiveUI.MessageBus.Current.SendMessage(new ForceClosePopulsEventArgs()); switch (s.State) { case NavigationState.ConflictSolver: ConflictSolver.SelectedModCollection = s.SelectedCollection; ConflictSolver.SelectedModsOrder = s.SelectedMods; ConflictSolver.Conflicts = s.Results; ConflictSolver.Reset(); AnimateTransitionAsync(false).ConfigureAwait(true); break; default: AnimateTransitionAsync(true).ConfigureAwait(true); Main.Reset(); break; } }).DisposeWith(disposables); writingStateOperationHandler.Message.Subscribe(s => { TriggerPreventShutdown(!s.CanShutdown); }).DisposeWith(disposables); base.OnActivated(disposables); }
public async Task CreateConflictAndResolveItIncreaseTheRevisions() { using (var storeA = GetDocumentStore()) using (var storeB = GetDocumentStore()) { await GenerateConflict(storeA, storeB); Assert.Equal(2, WaitUntilHasConflict(storeA, "foo/bar").Length); Assert.Equal(2, WaitUntilHasConflict(storeB, "foo/bar").Length); Assert.Equal(2, WaitForValue(() => storeA.Commands().GetRevisionsFor("foo/bar").Count, 2)); Assert.Equal(2, WaitForValue(() => storeB.Commands().GetRevisionsFor("foo/bar").Count, 2)); var config = new ConflictSolver { ResolveToLatest = true }; await SetupReplicationAsync(storeA, config, storeB); Assert.True(WaitForDocument(storeA, "foo/bar")); Assert.True(WaitForDocument(storeB, "foo/bar")); Assert.Equal(3, WaitForValue(() => storeA.Commands().GetRevisionsFor("foo/bar").Count, 3)); Assert.Equal(3, WaitForValue(() => storeB.Commands().GetRevisionsFor("foo/bar").Count, 3)); } }
private void WriteConflictSolver(ConflictSolver conflictSolver) { if (conflictSolver == null) { _writer.WriteNull(); return; } _context.Write(_writer, conflictSolver.ToJson()); }
private void TestBtn_Click(object sender, EventArgs e) { dd1 = new DirectoryData(CurrentPD.SourceDirectoryPath); dd2 = new DirectoryData(CurrentPD.TargetDirectoryPath); CurrentSession = ConflictSolver.FormConflictFileDataList(dd1, dd2); SyncClassifier.ClassifySyncDatas(CurrentSession, CurrentPD.StatementDataString); FillTheTable(); }
public void Initialize(DatabaseRecord record) { if (_isInitialized) //precaution -> probably not necessary, but still... { return; } ConflictSolverConfig = record.ConflictSolverConfig; ConflictResolver = new ResolveConflictOnReplicationConfigurationChange(this, _log); ConflictResolver.RunConflictResolversOnce(); _isInitialized.Raise(); }
public async Task ResolveWhenScriptAdded() { using (var store1 = GetDocumentStore(options: new Options { ModifyDatabaseRecord = record => { record.ConflictSolverConfig = new ConflictSolver { ResolveToLatest = false, ResolveByCollection = new Dictionary <string, ScriptResolver>() }; } })) using (var store2 = GetDocumentStore(options: new Options { ModifyDatabaseRecord = record => { record.ConflictSolverConfig = new ConflictSolver { ResolveToLatest = false, ResolveByCollection = new Dictionary <string, ScriptResolver>() }; } })) { await GenerateConflictsAndSetupMasterMasterReplication(store1, store2); var config = new ConflictSolver { ResolveByCollection = new Dictionary <string, ScriptResolver> { { "Users", new ScriptResolver { Script = "return {'Name':'Resolved'}" } } } }; await UpdateConflictResolver(store1, config.ResolveByCollection, config.ResolveToLatest); Assert.True(WaitForDocument <User>(store1, "foo/bar", u => u.Name == "Resolved")); Assert.True(WaitForDocument <User>(store2, "foo/bar", u => u.Name == "Resolved")); } }
public async Task ResolveWhenSettingDatabaseResolver() { using (var store1 = GetDocumentStore()) using (var store2 = GetDocumentStore()) { await GenerateConflicts(store1, store2); var storage1 = Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store1.Database).Result; var config = new ConflictSolver { DatabaseResolverId = storage1.DbBase64Id }; await SetupReplicationAsync(store1, config, store2); Assert.True(WaitForDocument <User>(store1, "foo/bar", u => u.Name == "Store1")); Assert.True(WaitForDocument <User>(store2, "foo/bar", u => u.Name == "Store1")); } }
/// <summary> /// Called when [activated]. /// </summary> /// <param name="disposables">The disposables.</param> protected override void OnActivated(CompositeDisposable disposables) { var state = NavigationState.Main; BindOverlay(); ReactiveUI.MessageBus.Current.Listen <NavigationEventArgs>() .Subscribe(s => { ReactiveUI.MessageBus.Current.SendMessage(new ForceClosePopulsEventArgs()); state = s.State; switch (s.State) { case NavigationState.ConflictSolver: ConflictSolver.SelectedModCollection = s.SelectedCollection; ConflictSolver.SelectedModsOrder = s.SelectedMods; ConflictSolver.Conflicts = s.Results; ConflictSolver.Reset(); AnimateTransitionAsync(false).ConfigureAwait(true); break; default: AnimateTransitionAsync(true).ConfigureAwait(true); Main.Reset(); break; } }).DisposeWith(disposables); writingStateOperationHandler.Subscribe(s => { TriggerPreventShutdown(!s.CanShutdown); }).DisposeWith(disposables); RegisterHotkeyCommand = ReactiveCommand.CreateFromTask(async(string key) => { if (!OverlayVisible) { await hotkeyManager.HotKeyPressedAsync(state, key); } }).DisposeWith(disposables); base.OnActivated(disposables); }
public async Task CreateConflictAndResolveItIncreaseTheRevisions(bool configureVersioning) { using (var storeA = GetDocumentStore()) using (var storeB = GetDocumentStore()) { await GenerateConflict(storeA, storeB, configureVersioning); Assert.Equal(2, WaitUntilHasConflict(storeA, "foo/bar").Length); Assert.Equal(2, WaitUntilHasConflict(storeB, "foo/bar").Length); if (configureVersioning) { using (var session = storeA.OpenSession()) { Assert.Equal(2, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 2)); } using (var session = storeB.OpenSession()) { Assert.Equal(2, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 2)); } } var config = new ConflictSolver { ResolveToLatest = true }; await SetupReplicationAsync(storeA, config, storeB); Assert.True(WaitForDocument(storeA, "foo/bar")); Assert.True(WaitForDocument(storeB, "foo/bar")); using (var session = storeA.OpenSession()) { Assert.Equal(3, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 3)); } using (var session = storeB.OpenSession()) { Assert.Equal(3, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 3)); } } }
public async Task RunConflictResolversOnce(ConflictSolver solver, long index) { // update to larger index; if (ThreadingHelper.InterlockedExchangeMax(ref _processedRaftIndex, index) == false) { return; } try { using (await RunOnceAsync()) { if (Interlocked.Read(ref _processedRaftIndex) > index) { return; } UpdateScriptResolvers(solver); if (ConflictsCount > 0 && solver?.IsEmpty() == false) { await ResolveConflictsInBackground(solver); } } } catch (OperationCanceledException) { // shutdown } catch (ObjectDisposedException) { // shutdown } catch (Exception e) { if (_log.IsInfoEnabled) { _log.Info("Failed to wait for a previous task of automatic conflict resolution", e); } } }
public async Task CreateConflictAndResolveItIncreaseTheRevisions(bool configureVersioning) { using (var storeA = GetDocumentStore(options: new Options { ModifyDatabaseRecord = record => { record.ConflictSolverConfig = new ConflictSolver { ResolveToLatest = false, ResolveByCollection = new Dictionary <string, ScriptResolver>() }; } })) using (var storeB = GetDocumentStore(options: new Options { ModifyDatabaseRecord = record => { record.ConflictSolverConfig = new ConflictSolver { ResolveToLatest = false, ResolveByCollection = new Dictionary <string, ScriptResolver>() }; } })) { await GenerateConflictAndSetupMasterMasterReplication(storeA, storeB, configureVersioning); Assert.Equal(2, WaitUntilHasConflict(storeA, "foo/bar").Length); Assert.Equal(2, WaitUntilHasConflict(storeB, "foo/bar").Length); if (configureVersioning) { using (var session = storeA.OpenSession()) { Assert.Equal(2, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 2)); } using (var session = storeB.OpenSession()) { Assert.Equal(2, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 2)); } } var config = new ConflictSolver { ResolveToLatest = true }; await UpdateConflictResolver(storeA, config.ResolveByCollection, config.ResolveToLatest); Assert.True(WaitForDocument(storeA, "foo/bar")); Assert.True(WaitForDocument(storeB, "foo/bar")); using (var session = storeA.OpenSession()) { Assert.Equal(3, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 3)); } using (var session = storeB.OpenSession()) { Assert.Equal(3, WaitForValue(() => session.Advanced.Revisions.GetMetadataFor("foo/bar").Count, 3)); } } }
protected async Task SetupReplicationAsync(DocumentStore fromStore, ConflictSolver conflictSolver, params DocumentStore[] toStores) { await UpdateConflictResolver(fromStore, conflictSolver.ResolveByCollection, conflictSolver.ResolveToLatest); await SetupReplicationAsync(fromStore, toStores); }
private async Task ResolveConflictsInBackground(ConflictSolver solver) { try { bool retry; do { retry = false; using (_database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context)) using (context.OpenReadTransaction()) { var resolvedConflicts = new List <(DocumentConflict ResolvedConflict, long MaxConflictEtag, bool ResolvedToLatest)>(); var hadConflicts = false; foreach (var conflicts in _database.DocumentsStorage.ConflictsStorage.GetAllConflictsBySameId(context)) { if (_database.DatabaseShutdown.IsCancellationRequested) { break; } hadConflicts = true; var collection = conflicts[0].Collection; var maxConflictEtag = conflicts.Max(x => x.Etag); DocumentConflict resolved; if (ScriptConflictResolversCache.TryGetValue(collection, out var scriptResolver) && scriptResolver != null) { if (TryResolveConflictByScriptInternal( context, scriptResolver, conflicts, collection, resolvedConflict: out resolved)) { resolved.Flags = resolved.Flags.Strip(DocumentFlags.FromReplication); resolvedConflicts.Add((resolved, maxConflictEtag, ResolvedToLatest: false)); //stats.AddResolvedBy(collection + " Script", conflictList.Count); continue; } } if (solver?.ResolveToLatest == true) { resolved = ResolveToLatest(conflicts); resolved.Flags = resolved.Flags.Strip(DocumentFlags.FromReplication); resolvedConflicts.Add((resolved, maxConflictEtag, ResolvedToLatest: true)); //stats.AddResolvedBy("ResolveToLatest", conflictList.Count); } } if (hadConflicts == false || _database.DatabaseShutdown.IsCancellationRequested) { return; } if (resolvedConflicts.Count > 0) { var cmd = new PutResolvedConflictsCommand(_database.DocumentsStorage.ConflictsStorage, resolvedConflicts, this); await _database.TxMerger.Enqueue(cmd); retry = cmd.RequiresRetry; } } } while (retry); } catch (Exception e) { if (_log.IsInfoEnabled) { _log.Info("Failed to run automatic conflict resolution", e); } } }