public void Publish <T>(String DocumentId, T Payload, ChangeType Type = ChangeType.CHANGE)
        {
            var interested = _subscriptions.Where(x => x.DocumentId == DocumentId && x.Document == typeof(T).FullName);

            if (Type == ChangeType.NEW)
            {
                var interestedNew = _subscriptions.Where(x => x.Document == typeof(T).FullName && x.DocumentId.IsNullOrEmpty());

                foreach (var sub in interestedNew)
                {
                    Manage <T>(sub.CacheKey, DocumentId, sub.SubscriptionId, sub.Session);
                }

                interested = interested.Concat(interestedNew);
            }
            interested = interested.Distinct(x => x.SubscriptionId);

            // Delete entries from cache (new data == old data stale)
            _cache.RemoveAll(interested.Select(x => x.CacheKey).Distinct());

            foreach (var sub in interested)
            {
                _sse.NotifySession(sub.Session,
                                   "forte.Update",
                                   new Responses.Update <T>
                {
                    Payload = Payload,
                    Type    = Type,
                    //Etag = ETag,
                    SubscriptionId = sub.SubscriptionId
                });
            }
        }
Пример #2
0
        public async Task Flush()
        {
            // Copy and empty the bag
            var updates = _updates.Values.ToList();

            _updates.Clear();


            var notifies = new Dictionary <String, IList <Responses.Update> >();


            foreach (var doc in updates)
            {
                var interested = await RetrieveInterested(doc.Document, doc.DocumentId);

                foreach (var interest in interested.Distinct(x => new { x.Session, x.SubscriptionId }))
                {
                    if (!notifies.ContainsKey(interest.Session))
                    {
                        notifies[interest.Session] = new List <Responses.Update>();
                    }

                    notifies[interest.Session].Add(new Responses.Update
                    {
                        Payload        = doc.Payload,
                        Etag           = doc.Etag,
                        Stamp          = doc.Stamp,
                        SubscriptionId = interest.SubscriptionId,
                        Type           = doc.Type
                    });
                }

                // Delete entries from cache (new data == old data stale)
                var keys = interested.Select(x => x.CacheKey).Distinct();
                if (keys.Count() != 0)
                {
                    _cache.RemoveAll(keys.ToArray());
                }
            }

            foreach (var job in notifies)
            {
                if (_logger.IsDebugEnabled)
                {
                    _logger.DebugFormat("Notifying session {0} of {1} values", job.Key, job.Value.Count);
                }
                _sse.NotifySession(job.Key, "Demo.Update", job.Value.ToArray());
            }

            await _storage.Clean();
        }
        public void Publish(Guid QueryId, Int32 Version, Object Payload)
        {
            IDictionary <String, Listener> listeners;

            if (!_subscriptions.TryGetValue(QueryId, out listeners))
            {
                return;
            }

            foreach (var listener in listeners)
            {
                if (listener.Value.Timeout < DateTime.UtcNow)
                {
                    RemoveTracked(listener.Key, QueryId);
                    return;
                }

                _sse.NotifySession(listener.Key, new { Version = Version, Payload = Payload });
            }
        }
Пример #4
0
 public static void NotifySession(this IServerEvents server, string sspid, object message, string channel = null)
 {
     server.NotifySession(sspid, Selector.Id(message.GetType()), message, channel);
 }
Пример #5
0
        public async Task Flush()
        {
            // Copy and empty the bag
            var updates = _updates.Values.ToList();
            _updates.Clear();

            var notifies = new Dictionary<string, IList<Responses.Update>>();

            foreach (var doc in updates.GroupBy(x => x.Document))
            {
                var interested = await _storage.Retreive(x => x.Document == doc.Key).ConfigureAwait(false);
                var indirect = interested.Where(x => x.DocumentId == "");
                foreach (var indv in doc)
                {
                    var all = interested.Where(x => x.DocumentId == indv.DocumentId).ToList();

                    // Don't foreach over all the indirect because indirect contains all the open list subscriptions
                    // and the doc we are looking at might already be subscribed to which would be weeded out by the Union above
                    foreach (var paged in indirect)
                    {
                        if (all.Any(x => x.Session == paged.Session && x.SubscriptionId == paged.SubscriptionId)) continue;
                        // Deserialize the original query that generated the list of data
                        // Run the dto through the query to test if the conditions are satisfied
                        // If so, add a new subscription and notify client of new element on list

                        // Todo: using a bit of reflection to call open generic IChange.Satisfied can replace once IChange is implemented more like FluentValidation than a generic interface see PUL-5

                        var queryType = Type.GetType(paged.SerializedQueryType);
                        var query = JsonConvert.DeserializeObject(paged.SerializedQuery, queryType);

                        var pagedType = queryType.GetInterfaces().Single(x => x.IsInterface && x.GetInterfaces().Contains(typeof(IPaged)));

                        var changeType = typeof(IChange<,>).MakeGenericType(indv.Payload.GetType(), pagedType);
                        var satisfiedChange = changeType.GetMethod("Satisfied", BindingFlags.Public | BindingFlags.Instance);

                        var change = _container.TryGetInstance(changeType);
                        if (query == null || change == null || !(bool)satisfiedChange.Invoke(change, new[] { indv.Payload, query })) continue;


                        var subscription = new Subscription
                        {
                            SerializedQuery = paged.SerializedQuery,
                            SubscriptionId = paged.SubscriptionId,
                            Document = indv.Document,
                            DocumentId = indv.DocumentId,
                            CacheKey = paged.CacheKey,
                            Expires = paged.Expires,
                            Session = paged.Session,
                            Type = paged.Type
                        };
                        all.Add(subscription);
                        await _storage.Store(subscription).ConfigureAwait(false);
                    }

                    foreach (var interest in all)
                    {
                        var key = interest.Session;
                        if (!notifies.ContainsKey(key))
                            notifies[key] = new List<Responses.Update>();

                        notifies[key].Add(new Responses.Update
                        {
                            Payload = indv.Payload,
                            Etag = indv.Etag,
                            Stamp = indv.Stamp,
                            SubscriptionId = interest.SubscriptionId,
                            Type = indv.Type
                        });
                    }
                }

                // Delete entries from cache (new data == old data stale)
                var keys = interested.Select(x => x.CacheKey).Distinct();
                if (keys.Count() != 0)
                    _cache.RemoveAll(keys.ToArray());
            }

            foreach (var job in notifies)
            {
                if (Logger.IsDebugEnabled)
                    Logger.DebugFormat("Notifying session {0} of {1} values", job.Key, job.Value.Count);
                _sse.NotifySession(job.Key, "Demo.Update", job.Value.ToArray());
            }

            await _storage.Clean().ConfigureAwait(false);
        }