Last active
June 3, 2019 20:35
-
-
Save ramonsmits/4d893c41cb6de4dd4acd95d434d83a73 to your computer and use it in GitHub Desktop.
NServiceBus in memory least recently used gateway deduplication
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Configuration; | |
using System.Runtime.CompilerServices; | |
using NServiceBus; | |
using NServiceBus.Features; | |
using NServiceBus.Gateway.Deduplication; | |
using NServiceBus.Persistence; | |
/// <remarks>All collection operations are O(1)</remarks> | |
class InMemoryLRUGatewayDeduplication : IDeduplicateMessages | |
{ | |
public InMemoryLRUGatewayDeduplication() | |
{ | |
if (!int.TryParse(ConfigurationManager.AppSettings[MaxSizeKey], out MaxSize)) | |
{ | |
MaxSize = MaxSizeDefault; | |
} | |
} | |
[MethodImpl(MethodImplOptions.Synchronized)] | |
public bool DeduplicateMessage(string clientId, DateTime timeReceived) | |
{ | |
// Return FALSE if item EXISTS, TRUE if ADDED | |
if (set.TryGetValue(clientId, out var existingNode)) // O(1) | |
{ | |
list.Remove(existingNode); // O(1) operation, because we got the node reference | |
list.AddLast(clientId); // O(1) operation | |
return false; | |
} | |
else | |
{ | |
if (set.Count == MaxSize) | |
{ | |
var id = list.First.Value; | |
set.Remove(id); // O(1) | |
list.RemoveFirst(); // O(1) | |
} | |
var node = list.AddLast(clientId); // O(1) | |
set.Add(clientId, node); // O(1) | |
return true; | |
} | |
} | |
const string MaxSizeKey = "NServiceBus/InMemoryLRUGatewayDeduplication/MaxSize"; | |
const int MaxSizeDefault = 1000; | |
readonly int MaxSize; | |
readonly LinkedList<string> list = new LinkedList<string>(); | |
readonly Dictionary<string, LinkedListNode<string>> set = new Dictionary<string, LinkedListNode<string>>(); | |
} | |
class InMemoryLRUGatewayDeduplicationPersistence : PersistenceDefinition | |
{ | |
internal InMemoryLRUGatewayDeduplicationPersistence() | |
{ | |
Supports<StorageType.GatewayDeduplication>(s => s.EnableFeatureByDefault<InMemoryLRUGatewayPersistence>()); | |
} | |
} | |
class InMemoryLRUGatewayPersistence : Feature | |
{ | |
internal InMemoryLRUGatewayPersistence() | |
{ | |
DependsOn("Gateway"); | |
} | |
/// <summary> | |
/// See <see cref="Feature.Setup"/> | |
/// </summary> | |
protected override void Setup(FeatureConfigurationContext context) | |
{ | |
context.Container.ConfigureComponent<InMemoryLRUGatewayDeduplication>(DependencyLifecycle.SingleInstance); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Configuration; | |
using System.Runtime.CompilerServices; | |
using System.Threading.Tasks; | |
using NServiceBus; | |
using NServiceBus.Extensibility; | |
using NServiceBus.Features; | |
using NServiceBus.Gateway.Deduplication; | |
using NServiceBus.Persistence; | |
/// <remarks>All collection operations are O(1)</remarks> | |
class InMemoryLRUGatewayDeduplication : IDeduplicateMessages | |
{ | |
public InMemoryLRUGatewayDeduplication() | |
{ | |
if (!int.TryParse(ConfigurationManager.AppSettings[MaxSizeKey], out MaxSize)) | |
{ | |
MaxSize = MaxSizeDefault; | |
} | |
} | |
[MethodImpl(MethodImplOptions.Synchronized)] | |
public Task<bool> DeduplicateMessage(string clientId, DateTime timeReceived, ContextBag context) | |
{ | |
// Return FALSE if item EXISTS, TRUE if ADDED | |
if (set.TryGetValue(clientId, out var existingNode)) // O(1) | |
{ | |
list.Remove(existingNode); // O(1) operation, because we got the node reference | |
list.AddLast(clientId); // O(1) operation | |
return FalseTask; | |
} | |
else | |
{ | |
if (set.Count == MaxSize) | |
{ | |
var id = list.First.Value; | |
set.Remove(id); // O(1) | |
list.RemoveFirst(); // O(1) | |
} | |
var node = list.AddLast(clientId); // O(1) | |
set.Add(clientId, node); // O(1) | |
return TrueTask; | |
} | |
} | |
static readonly Task<bool> TrueTask = Task.FromResult(true); | |
static readonly Task<bool> FalseTask = Task.FromResult(false); | |
const string MaxSizeKey = "NServiceBus/InMemoryLRUGatewayDeduplication/MaxSize"; | |
const int MaxSizeDefault = 1000; | |
readonly int MaxSize; | |
readonly LinkedList<string> list = new LinkedList<string>(); | |
readonly Dictionary<string, LinkedListNode<string>> set = new Dictionary<string, LinkedListNode<string>>(); | |
} | |
class InMemoryLRUGatewayDeduplicationPersistence : PersistenceDefinition | |
{ | |
internal InMemoryLRUGatewayDeduplicationPersistence() | |
{ | |
Supports<StorageType.GatewayDeduplication>(s => s.EnableFeatureByDefault<InMemoryLRUGatewayPersistence>()); | |
} | |
} | |
class InMemoryLRUGatewayPersistence : Feature | |
{ | |
internal InMemoryLRUGatewayPersistence() | |
{ | |
DependsOn("Gateway"); | |
} | |
/// <summary> | |
/// See <see cref="Feature.Setup"/> | |
/// </summary> | |
protected internal override void Setup(FeatureConfigurationContext context) | |
{ | |
context.Container.ConfigureComponent<InMemoryLRUGatewayDeduplication>(DependencyLifecycle.SingleInstance); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment