Example #1
0
        public PublishSubscribeDistributedCache(string cacheGroup,
                                                IPublishSubscribe publishSubscribe)
        {
            _publishSubscribe = publishSubscribe ?? throw new ArgumentNullException(nameof(publishSubscribe));

            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions
            {
                CompactionPercentage = 0.1
            });

            _getTopic    = cacheGroup + "_get";
            _setTopic    = cacheGroup + "_set";
            _removeTopic = cacheGroup + "_remove";

            publishSubscribe
            .Observe <byte[]>(_setTopic)
            .Subscribe(_ =>
            {
                CacheEntry cacheEntry = CacheEntry.Parser.ParseFrom(_.Data);
                memoryCache.Set(cacheEntry.Key, cacheEntry);
            }, CancellationToken);

            publishSubscribe
            .Observe <string>(_removeTopic)
            .Subscribe(_ => { memoryCache.Remove(_.Data); }, CancellationToken);

            publishSubscribe
            .Observe <byte[]>(_getTopic)
            .Subscribe(_ =>
            {
                CacheRequest cacheRequest = CacheRequest.Parser.ParseFrom(_.Data);
                CacheEntry value          = memoryCache.Get <CacheEntry>(cacheRequest.Key) ?? new CacheEntry
                {
                    Key = cacheRequest.Key
                };
                publishSubscribe.Publish(cacheRequest.TopicResponse, value.ToByteArray());
            }, CancellationToken);

            _selfTopic = Guid.NewGuid().ToString();
            publishSubscribe
            .Observe <byte[]>(_selfTopic)
            .Subscribe(_ =>
            {
                CacheEntry cacheEntry = CacheEntry.Parser.ParseFrom(_.Data);
                if (_completionSources.TryRemove(cacheEntry.Key, out TaskCompletionSource <byte[]> taskCompletionSource))
                {
                    taskCompletionSource.TrySetResult(cacheEntry.Value.ToByteArray());
                }
            }, CancellationToken);
        }
        public Task Initialize(TimeSpan timeout)
        {
            _subscription?.Dispose();
            _subscription = _publishSubscribe
                            .Observe <MessageData>(_queueId.ToString(), _queueId.ToString())
                            .Subscribe(tuple =>
            {
                switch (tuple.Data)
                {
                case MessageData messageData:
                    messageData.SerializationManager = _serializationManager;
                    break;
                }

                _batchContainers.Enqueue(tuple.Data);
            });

            return(Task.CompletedTask);
        }
Example #3
0
        public static IDisposable EnableDistributedBackplane(this IWampHostedRealm realm,
                                                             IPublishSubscribe publishSubscribe)
        {
            ConcurrentDictionary <string, IDisposable> disposables = new ConcurrentDictionary <string, IDisposable>();

            AtomicBoolean disableInternalPublishAtomicBoolean = new AtomicBoolean();
            string        forwarderPubSubTopic = $"DistributedRealm_{realm.Name}";
            string        selfId = $"{System.Diagnostics.Process.GetCurrentProcess().Id}_{Environment.MachineName}";

            void TopicCreated(object sender, WampTopicCreatedEventArgs args)
            {
                IDisposable subscription = args.Topic
                                           .Subscribe(new PubSubForwarderWampRawTopicRouterSubscriber(selfId, forwarderPubSubTopic, args.Topic, publishSubscribe, disableInternalPublishAtomicBoolean));

                disposables.TryAdd(args.Topic.TopicUri, subscription);
            }

            void TopicRemoved(object sender, WampTopicRemovedEventArgs args)
            {
                if (disposables.TryGetValue(args.Topic.TopicUri, out IDisposable subscription))
                {
                    subscription.Dispose();
                }
            }

            realm.TopicContainer.TopicCreated += TopicCreated;
            realm.TopicContainer.TopicRemoved += TopicRemoved;

            PublishOptions defaultPublishOptions = new PublishOptions();
            IDisposable    pubSubSubscription    = publishSubscribe
                                                   .Observe <ForwardedWampMessage>(forwarderPubSubTopic)
                                                   .Where(tuple => !selfId.Equals(tuple.Data.PublisherId))
                                                   .Subscribe(_ =>
            {
                disableInternalPublishAtomicBoolean.FalseToTrue();
                try
                {
                    if (_.Data.ArgumentsKeywords == null &&
                        _.Data.Arguments == null)
                    {
                        realm.TopicContainer.Publish(WampObjectFormatter.Value, defaultPublishOptions, _.Data.WampTopic);
                    }
                    else
                    {
                        if (_.Data.ArgumentsKeywords == null)
                        {
                            realm.TopicContainer.Publish(WampObjectFormatter.Value,
                                                         defaultPublishOptions,
                                                         _.Data.WampTopic,
                                                         _.Data.Arguments);
                        }
                        else
                        {
                            realm.TopicContainer.Publish(WampObjectFormatter.Value,
                                                         defaultPublishOptions,
                                                         _.Data.WampTopic,
                                                         _.Data.Arguments,
                                                         _.Data.ArgumentsKeywords);
                        }
                    }
                }
                finally
                {
                    disableInternalPublishAtomicBoolean.TrueToFalse();
                }
            });

            return(new AnonymousDisposable(() =>
            {
                pubSubSubscription.Dispose();
                realm.TopicContainer.TopicCreated -= TopicCreated;
                realm.TopicContainer.TopicRemoved -= TopicRemoved;
                foreach (KeyValuePair <string, IDisposable> pair in disposables)
                {
                    pair.Value.Dispose();
                }
            }));
        }
        public PublishSusbcribeCacheManagerBackplane(
            IPublishSubscribe publishSubscribe,
            ILoggerFactory loggerFactory,
            ICacheManagerConfiguration configuration) : base(configuration)
        {
            NotNull(configuration, nameof(publishSubscribe));
            NotNull(loggerFactory, nameof(loggerFactory));
            NotNull(loggerFactory, nameof(loggerFactory));

            _publishSubscribe = publishSubscribe;
            _channelName      = configuration.BackplaneChannelName ?? "CacheManagerBackplane";
            _identifier       = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());

            ILogger logger = loggerFactory.CreateLogger(this);

            _subscription = publishSubscribe
                            .Observe <byte[]>(_channelName)
                            .SelectMany(serializedBackplaneMessage => BackplaneMessage.Deserialize(serializedBackplaneMessage.Data, _identifier))
                            .Subscribe(message =>
            {
                if (logger.IsEnabled(LogLevel.Information))
                {
                    logger.LogInfo("Backplane got notified with new message.");
                }

                switch (message.Action)
                {
                case BackplaneAction.Clear:
                    TriggerCleared();
                    break;

                case BackplaneAction.ClearRegion:
                    TriggerClearedRegion(message.Region);
                    break;

                case BackplaneAction.Changed:
                    if (string.IsNullOrWhiteSpace(message.Region))
                    {
                        TriggerChanged(message.Key, message.ChangeAction);
                    }
                    else
                    {
                        TriggerChanged(message.Key, message.Region, message.ChangeAction);
                    }

                    break;

                case BackplaneAction.Removed:
                    if (string.IsNullOrWhiteSpace(message.Region))
                    {
                        TriggerRemoved(message.Key);
                    }
                    else
                    {
                        TriggerRemoved(message.Key, message.Region);
                    }

                    break;
                }
            });
        }