public ScaleoutSubscription(string identity, IEnumerable <string> eventKeys, string cursor, ConcurrentDictionary <string, Linktionary <ulong, ScaleoutMapping> > streamMappings, Func <MessageResult, Task <bool> > callback, int maxMessages, IPerformanceCounterWriter counters) : base(identity, eventKeys, callback, maxMessages, counters) { _streams = streamMappings; IEnumerable <Cursor> cursors = null; if (cursor == null) { cursors = from key in _streams.Keys select new Cursor { Key = key, Id = GetCursorId(key) }; } else { cursors = Cursor.GetCursors(cursor); } _cursors = new List <Cursor>(cursors); }
public DefaultSubscription(string identity, IEnumerable <string> eventKeys, IDictionary <string, Topic> topics, string cursor, Func <MessageResult, Task <bool> > callback, int maxMessages, IPerformanceCounterWriter counters) : base(identity, eventKeys, callback, maxMessages, counters) { IEnumerable <Cursor> cursors = null; if (cursor == null) { cursors = from key in eventKeys select new Cursor { Key = key, Id = GetMessageId(topics, key) }; } else { cursors = Cursor.GetCursors(cursor); } _cursors = new List <Cursor>(cursors); _cursorTopics = new List <Topic>(); if (!String.IsNullOrEmpty(cursor)) { // Update all of the cursors so we're within the range for (int i = _cursors.Count - 1; i >= 0; i--) { Cursor c = _cursors[i]; Topic topic; if (!eventKeys.Contains(c.Key)) { _cursors.Remove(c); } else if (topics.TryGetValue(_cursors[i].Key, out topic) && _cursors[i].Id > topic.Store.GetMessageCount()) { UpdateCursor(c.Key, 0); } } } // Add dummy entries so they can be filled in for (int i = 0; i < _cursors.Count; i++) { _cursorTopics.Add(null); } }
/// <summary> /// /// </summary> /// <param name="subscriber"></param> /// <param name="cursor"></param> /// <param name="callback"></param> /// <returns></returns> public IDisposable Subscribe(ISubscriber subscriber, string cursor, Func <MessageResult, Task <bool> > callback, int messageBufferSize) { IEnumerable <Cursor> cursors = null; if (cursor == null) { cursors = from key in subscriber.EventKeys select new Cursor { Key = key, Id = GetMessageId(key) }; } else { cursors = Cursor.GetCursors(cursor); } var subscription = new Subscription(subscriber.Identity, cursors, callback, messageBufferSize); var topics = new HashSet <Topic>(); foreach (var key in subscriber.EventKeys) { Topic topic = _topics.GetOrAdd(key, _ => new Topic()); // Set the subscription for this topic subscription.SetCursorTopic(key, topic); // Add it to the list of topics topics.Add(topic); } foreach (var topic in topics) { topic.AddSubscription(subscription); } if (!String.IsNullOrEmpty(cursor)) { // Update all of the cursors so we're within the range foreach (var pair in subscription.Cursors) { Topic topic; if (_topics.TryGetValue(pair.Key, out topic) && pair.Id > topic.Store.GetMessageCount()) { subscription.UpdateCursor(pair.Key, 0); } } } Action <string, string> eventAdded = (eventKey, eventCursor) => { Topic topic = _topics.GetOrAdd(eventKey, _ => new Topic()); // Get the cursor for this event key ulong id = eventCursor == null ? 0 : UInt64.Parse(eventCursor); // Add or update the cursor (in case it already exists) subscription.AddOrUpdateCursor(eventKey, id, topic); // Add it to the list of subs topic.AddSubscription(subscription); }; Action <string> eventRemoved = eventKey => RemoveEvent(subscription, eventKey); subscriber.EventAdded += eventAdded; subscriber.EventRemoved += eventRemoved; // If there's a cursor then schedule work for this subscription if (!String.IsNullOrEmpty(cursor)) { _engine.Schedule(subscription); } return(new DisposableAction(() => { // This will stop work from continuting to happen subscription.Dispose(); subscriber.EventAdded -= eventAdded; subscriber.EventRemoved -= eventRemoved; string currentCursor = Cursor.MakeCursor(subscription.Cursors); foreach (var eventKey in subscriber.EventKeys) { RemoveEvent(subscription, eventKey); } subscription.Invoke(new MessageResult(currentCursor)); })); }