public void A_LWWDictionary_should_be_able_to_remove_entry() { var m1 = LWWDictionary.Create( Tuple.Create(_node1, "a", 1), Tuple.Create(_node2, "b", 2)); var m2 = LWWDictionary.Create(_node2, "c", 3); var merged1 = m1.Merge(m2); var m3 = merged1.Remove(_node1, "b"); Assert.Equal(merged1.Merge(m3).Entries, ImmutableDictionary.CreateRange(new[] { new KeyValuePair <string, int>("a", 1), new KeyValuePair <string, int>("c", 3) })); // but if there is a conflicting update the entry is not removed var m4 = merged1.SetItem(_node2, "b", 22); Assert.Equal(m3.Merge(m4).Entries, ImmutableDictionary.CreateRange(new[] { new KeyValuePair <string, int>("a", 1), new KeyValuePair <string, int>("b", 22), new KeyValuePair <string, int>("c", 3) })); }
public PerformanceMonitor(TimeSpan updateInterval) { // schedule periodical updates this.cancelUpdates = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(updateInterval, updateInterval, Self, CollectMetrics.Instance, ActorRefs.NoSender); var cluster = Cluster.Get(Context.System); // create and start performance counters for a local node this.cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); this.memCounter = new PerformanceCounter("Memory", "Available MBytes"); cpuCounter.NextValue(); memCounter.NextValue(); // assign to a distributed store of performance metrics var perfCounterKey = new LWWDictionaryKey <UniqueAddress, PerformanceMetrics>("perf-counters"); var replicator = DistributedData.DistributedData.Get(Context.System).Replicator; replicator.Tell(Dsl.Subscribe(perfCounterKey, Self)); Receive <Replicator.Changed>(changed => { lastResult = lastResult.Merge(changed.Get(perfCounterKey)); }); Receive <CollectMetrics>(_ => { var cpuUsage = cpuCounter.NextValue(); var memUsage = memCounter.NextValue(); lastResult = lastResult.SetItem(cluster, cluster.SelfUniqueAddress, new PerformanceMetrics(cpuUsage, memUsage)); replicator.Tell(Dsl.Update(perfCounterKey, lastResult, WriteLocal.Instance, null, map => lastResult.Merge(map))); }); }
public void A_LWWDictionary_should_be_able_to_set_entries() { var m = LWWDictionary.Create( Tuple.Create(_node1, "a", 1), Tuple.Create(_node2, "b", 2)); Assert.Equal(m.Entries, ImmutableDictionary.CreateRange(new[] { new KeyValuePair <string, int>("a", 1), new KeyValuePair <string, int>("b", 2) })); }
/// <summary> /// TBD /// </summary> /// <param name="other">TBD</param> /// <returns>TBD</returns> public bool Equals(LWWDictionary <TKey, TValue> other) { if (ReferenceEquals(other, null)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } return(Underlying.Equals(other.Underlying)); }
protected Update CreateUpdateStateCompletedCommand(string innerKey, IWriteConsistency writeConsistency = null) { return(Dsl.Update( key: new LWWDictionaryKey <string, DeduplicationState>( _receiver.ReplicatorKey), initial: LWWDictionary.Create(node: _receiver.SelfUniqueAddress, key: innerKey, value: new DeduplicationState() { NumberAttempts = 0, ProcessingState = DeduplicationProcessingState.Processed, PruneAfter = _receiver.PruningConfiguration .PruneAttemptedAfter != null ? DateTime.UtcNow + _receiver .PruningConfiguration.PruneAttemptedAfter : null }) , consistency: writeConsistency, modify: dds => { if (dds.TryGetValue(innerKey, out DeduplicationState state)) { state.ProcessingState = DeduplicationProcessingState.Processed; state.PruneAfter = DateTime.UtcNow + _receiver .PruningConfiguration.PruneCompletedAfter; return dds.SetItem(_receiver.SelfUniqueAddress, innerKey, state); } else { return dds.SetItem(_receiver.SelfUniqueAddress, innerKey, new DeduplicationState() { NumberAttempts = 0, ProcessingState = DeduplicationProcessingState .Processed, PruneAfter = DateTime.UtcNow + _receiver .PruningConfiguration .PruneCompletedAfter }); } })); }
public void A_LWWDictionary_should_be_able_to_have_its_entries_correctly_merged_with_another_LWWMap_with_other_entries() { var m1 = LWWDictionary.Create( Tuple.Create(_node1, "a", 1), Tuple.Create(_node1, "b", 2)); var m2 = LWWDictionary.Create(_node2, "c", 3); var expected = ImmutableDictionary.CreateRange(new[] { new KeyValuePair <string, int>("a", 1), new KeyValuePair <string, int>("b", 2), new KeyValuePair <string, int>("c", 3), }); // merge both ways Assert.Equal(expected, m1.Merge(m2).Entries); Assert.Equal(expected, m2.Merge(m1).Entries); }
/// <summary> /// TBD /// </summary> /// <param name="other">TBD</param> /// <returns>TBD</returns> public LWWDictionary <TKey, TValue> Merge(LWWDictionary <TKey, TValue> other) => new LWWDictionary <TKey, TValue>(Underlying.Merge(other.Underlying));
protected Update CreateAdvanceAndGetStateCommand(string innerKey, IWriteConsistency writeConsistency) { return(Dsl.Update( key: new LWWDictionaryKey <string, DeduplicationState>( _receiver.ReplicatorKey), initial: LWWDictionary.Create(node: _receiver.SelfUniqueAddress, key: innerKey, value: new DeduplicationState() { NumberAttempts = 0, ProcessingState = DeduplicationProcessingState.NotAttempted, PruneAfter = _receiver.PruningConfiguration .PruneNotAttemptedAfter != null ? DateTime.UtcNow + _receiver .PruningConfiguration.PruneNotAttemptedAfter : (DateTime?)null } ) , consistency: writeConsistency, modify: dds => { if (dds.TryGetValue(innerKey, out DeduplicationState state)) { if (state.ProcessingState == DeduplicationProcessingState.Error || state.ProcessingState == DeduplicationProcessingState.Processed) { return dds; } else if (state.NumberAttempts < _receiver.MaxAttempts) { state.NumberAttempts = state.NumberAttempts + 1; state.ProcessingState = DeduplicationProcessingState .Attempted; state.PruneAfter = _receiver.PruningConfiguration .PruneAttemptedAfter != null ? DateTime.UtcNow + _receiver .PruningConfiguration.PruneAttemptedAfter : (DateTime?)null; return dds.SetItem(_receiver.SelfUniqueAddress, innerKey, state); } else { state.ProcessingState = DeduplicationProcessingState.Error; state.PruneAfter = DateTime.UtcNow + _receiver .PruningConfiguration.PruneErroredAfter; return dds.SetItem(_receiver.SelfUniqueAddress, innerKey, state); } } else { return dds.SetItem(_receiver.SelfUniqueAddress, innerKey, new DeduplicationState() { NumberAttempts = 0, ProcessingState = DeduplicationProcessingState .NotAttempted, PruneAfter = _receiver.PruningConfiguration .PruneNotAttemptedAfter != null ? DateTime.UtcNow + _receiver .PruningConfiguration.PruneNotAttemptedAfter : (DateTime?)null }); } })); }
/// <summary> /// TBD /// </summary> /// <param name="cluster">TBD</param> /// <param name="crdt">TBD</param> public LocalLWWDictionary(Cluster.Cluster cluster, LWWDictionary <TKey, TVal> crdt) : this(cluster.SelfUniqueAddress, crdt) { }
/// <summary> /// TBD /// </summary> /// <param name="currentNode">TBD</param> /// <param name="crdt">TBD</param> internal LocalLWWDictionary(UniqueAddress currentNode, LWWDictionary <TKey, TVal> crdt) : this() { _currentNode = currentNode; _crdt = crdt; }
/// <summary> /// TBD /// </summary> /// <param name="dictionary">TBD</param> public Surrogate(LWWDictionary <TKey, TVal> dictionary) { _dictionary = dictionary; }
/// <summary> /// Merges data from provided <see cref="LWWDictionary{TKey,TValue}"/> into current CRDT, /// creating new immutable instance in a result. /// </summary> /// <param name="dictionary">TBD</param> /// <returns>TBD</returns> public LocalLWWDictionary <TKey, TVal> Merge(LWWDictionary <TKey, TVal> dictionary) => new LocalLWWDictionary <TKey, TVal>(_currentNode, _crdt.Merge(dictionary));
/// <summary> /// Creates an instance of an LWWDictionary scoped to a current cluster. /// </summary> /// <typeparam name="TKey">TBD</typeparam> /// <typeparam name="TVal">TBD</typeparam> /// <param name="cluster">TBD</param> /// <param name="dictionary">TBD</param> /// <returns>TBD</returns> public static LocalLWWDictionary <TKey, TVal> LWWDictionary <TKey, TVal>(this Cluster.Cluster cluster, LWWDictionary <TKey, TVal> dictionary) => new LocalLWWDictionary <TKey, TVal>(cluster, dictionary);