internal void InitializeCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken sequenceToken) { Log(logger, "InitializeCursor: {0} to sequenceToken {1}", cursor, sequenceToken); // Nothing in cache, unset token, and wait for more data. if (cachedMessages.Count == 0) { UnsetCursor(cursor, sequenceToken); return; } // if no token is provided, set cursor to idle at end of cache if (sequenceToken == null) { UnsetCursor(cursor, cachedMessages.First?.Value?.SequenceToken); return; } // If sequenceToken is too new to be in cache, unset token, and wait for more data. if (sequenceToken.Newer(cachedMessages.First.Value.SequenceToken)) { UnsetCursor(cursor, sequenceToken); return; } LinkedListNode <SimpleQueueCacheItem> lastMessage = cachedMessages.Last; // Check to see if offset is too old to be in cache if (sequenceToken.Older(lastMessage.Value.SequenceToken)) { throw new QueueCacheMissException(sequenceToken, cachedMessages.Last.Value.SequenceToken, cachedMessages.First.Value.SequenceToken); } // Now the requested sequenceToken is set and is also within the limits of the cache. // Find first message at or below offset // Events are ordered from newest to oldest, so iterate from start of list until we hit a node at a previous offset, or the end. LinkedListNode <SimpleQueueCacheItem> node = cachedMessages.First; while (node != null && node.Value.SequenceToken.Newer(sequenceToken)) { // did we get to the end? if (node.Next == null) // node is the last message { break; } // if sequenceId is between the two, take the higher if (node.Next.Value.SequenceToken.Older(sequenceToken)) { break; } node = node.Next; } // return cursor from start. SetCursor(cursor, node); }
private void AdvanceCursor(SimpleQueueCacheCursor cursor, LinkedListNode <SimpleQueueCacheItem> item) { Log(logger, "UpdateCursor: {Cursor} to item {Item}", cursor, item.Value.Batch); cursor.Element.Value.CacheBucket.UpdateNumCursors(-1); // remove from prev bucket cursor.Set(item); cursor.Element.Value.CacheBucket.UpdateNumCursors(1); // add to next bucket }
internal void SetCursor(SimpleQueueCacheCursor cursor, LinkedListNode <SimpleQueueCacheItem> item) { if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("SetCursor: {Cursor} to item {Item}", cursor, item.Value.Batch); } cursor.Set(item); cursor.Element.Value.CacheBucket.UpdateNumCursors(1); // add to next bucket }
internal void UnsetCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken token) { Log(logger, "UnsetCursor: {Cursor}", cursor); if (cursor.IsSet) { cursor.Element.Value.CacheBucket.UpdateNumCursors(-1); } cursor.UnSet(token); }
internal void RefreshCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken sequenceToken) { Log(logger, "RefreshCursor: {RefreshCursor} to sequenceToken {SequenceToken}", cursor, sequenceToken); // set if unset if (!cursor.IsSet) { InitializeCursor(cursor, cursor.SequenceToken ?? sequenceToken); } }
internal void ResetCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken token) { Log(logger, "ResetCursor: {0} to token {1}", cursor, token); if (cursor.IsSet) { cursor.Element.Value.CacheBucket.UpdateNumCursors(-1); } cursor.Reset(token); }
private void AdvanceCursor(SimpleQueueCacheCursor cursor, LinkedListNode <SimpleQueueCacheItem> item) { if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("UpdateCursor: {Cursor} to item {Item}", cursor, item.Value.Batch); } cursor.Element.Value.CacheBucket.UpdateNumCursors(-1); // remove from prev bucket cursor.Set(item); cursor.Element.Value.CacheBucket.UpdateNumCursors(1); // add to next bucket }
internal void RefreshCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken sequenceToken) { if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("RefreshCursor: {RefreshCursor} to sequenceToken {SequenceToken}", cursor, sequenceToken); } // set if unset if (!cursor.IsSet) { InitializeCursor(cursor, cursor.SequenceToken ?? sequenceToken); } }
public virtual IQueueCacheCursor GetCacheCursor(Guid streamGuid, string streamNamespace, StreamSequenceToken token) { if (token != null && !(token is EventSequenceToken)) { // Null token can come from a stream subscriber that is just interested to start consuming from latest (the most recent event added to the cache). throw new ArgumentOutOfRangeException("token", "token must be of type EventSequenceToken"); } var cursor = new SimpleQueueCacheCursor(this, streamGuid, streamNamespace, logger); InitializeCursor(cursor, token, true); return(cursor); }
internal void UnsetCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken token) { if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("UnsetCursor: {Cursor}", cursor); } if (cursor.IsSet) { cursor.Element.Value.CacheBucket.UpdateNumCursors(-1); } cursor.UnSet(token); }
/// <summary> /// Aquires the next message in the cache at the provided cursor /// </summary> /// <param name="cursor"></param> /// <param name="batch"></param> /// <returns></returns> internal bool TryGetNextMessage(SimpleQueueCacheCursor cursor, out IBatchContainer batch) { Log(logger, "TryGetNextMessage: {0}", cursor); batch = null; if (cursor == null) { throw new ArgumentNullException("cursor"); } //if not set, try to set and then get next if (!cursor.IsSet) { InitializeCursor(cursor, cursor.SequenceToken, false); return(cursor.IsSet && TryGetNextMessage(cursor, out batch)); } // has this message been purged if (cursor.SequenceToken.Older(cachedMessages.Last.Value.SequenceToken)) { throw new QueueCacheMissException(cursor.SequenceToken, cachedMessages.Last.Value.SequenceToken, cachedMessages.First.Value.SequenceToken); } // Cursor now points to a valid message in the cache. Get it! // Capture the current element and advance to the next one. batch = cursor.Element.Value.Batch; // Advance to next: if (cursor.Element == cachedMessages.First) { // If we are at the end of the cache unset cursor and move offset one forward ResetCursor(cursor, ((EventSequenceToken)cursor.SequenceToken).NextSequenceNumber()); } else // move to next { UpdateCursor(cursor, cursor.Element.Previous); } return(true); }
/// <summary> /// Acquires the next message in the cache at the provided cursor /// </summary> /// <param name="cursor"></param> /// <param name="batch"></param> /// <returns></returns> internal bool TryGetNextMessage(SimpleQueueCacheCursor cursor, out IBatchContainer batch) { Log(logger, "TryGetNextMessage: {Cursor}", cursor); batch = null; if (!cursor.IsSet) { return(false); } // If we are at the end of the cache unset cursor and move offset one forward if (cursor.Element == cachedMessages.First) { UnsetCursor(cursor, null); } else // Advance to next: { AdvanceCursor(cursor, cursor.Element.Previous); } batch = cursor.Element?.Value.Batch; return(batch != null); }
public virtual IQueueCacheCursor GetCacheCursor(IStreamIdentity streamIdentity, StreamSequenceToken token) { if (token != null && !(token is EventSequenceToken)) { // Null token can come from a stream subscriber that is just interested to start consuming from latest (the most recent event added to the cache). throw new ArgumentOutOfRangeException("token", "token must be of type EventSequenceToken"); } var cursor = new SimpleQueueCacheCursor(this, streamIdentity, logger); InitializeCursor(cursor, token, true); return cursor; }
internal void SetCursor(SimpleQueueCacheCursor cursor, LinkedListNode<SimpleQueueCacheItem> item) { Log(logger, "SetCursor: {0} to item {1}", cursor, item.Value.Batch); cursor.Set(item); cursor.Element.Value.CacheBucket.UpdateNumCursors(1); // add to next bucket }
private void UpdateCursor(SimpleQueueCacheCursor cursor, LinkedListNode<SimpleQueueCacheItem> item) { Log(logger, "UpdateCursor: {0} to item {1}", cursor, item.Value.Batch); cursor.Element.Value.CacheBucket.UpdateNumCursors(-1); // remove from prev bucket cursor.Set(item); cursor.Element.Value.CacheBucket.UpdateNumCursors(1); // add to next bucket }
/// <summary> /// Aquires the next message in the cache at the provided cursor /// </summary> /// <param name="cursor"></param> /// <param name="batch"></param> /// <returns></returns> internal bool TryGetNextMessage(SimpleQueueCacheCursor cursor, out IBatchContainer batch) { Log(logger, "TryGetNextMessage: {0}", cursor); batch = null; if (cursor == null) throw new ArgumentNullException("cursor"); //if not set, try to set and then get next if (!cursor.IsSet) { InitializeCursor(cursor, cursor.SequenceToken, false); return cursor.IsSet && TryGetNextMessage(cursor, out batch); } // has this message been purged if (cursor.SequenceToken.Older(cachedMessages.Last.Value.SequenceToken)) { throw new QueueCacheMissException(cursor.SequenceToken, cachedMessages.Last.Value.SequenceToken, cachedMessages.First.Value.SequenceToken); } // Cursor now points to a valid message in the cache. Get it! // Capture the current element and advance to the next one. batch = cursor.Element.Value.Batch; // Advance to next: if (cursor.Element == cachedMessages.First) { // If we are at the end of the cache unset cursor and move offset one forward ResetCursor(cursor, ((EventSequenceToken)cursor.SequenceToken).NextSequenceNumber()); } else // move to next { UpdateCursor(cursor, cursor.Element.Previous); } return true; }
internal void InitializeCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken sequenceToken, bool enforceSequenceToken) { Log(logger, "InitializeCursor: {0} to sequenceToken {1}", cursor, sequenceToken); if (cachedMessages.Count == 0) // nothing in cache { StreamSequenceToken tokenToReset = sequenceToken ?? (lastSequenceTokenAddedToCache != null ? ((EventSequenceToken)lastSequenceTokenAddedToCache).NextSequenceNumber() : null); ResetCursor(cursor, tokenToReset); return; } // if offset is not set, iterate from newest (first) message in cache, but not including the irst message itself if (sequenceToken == null) { StreamSequenceToken tokenToReset = lastSequenceTokenAddedToCache != null ? ((EventSequenceToken)lastSequenceTokenAddedToCache).NextSequenceNumber() : null; ResetCursor(cursor, tokenToReset); return; } if (sequenceToken.Newer(cachedMessages.First.Value.SequenceToken)) // sequenceId is too new to be in cache { ResetCursor(cursor, sequenceToken); return; } LinkedListNode<SimpleQueueCacheItem> lastMessage = cachedMessages.Last; // Check to see if offset is too old to be in cache if (sequenceToken.Older(lastMessage.Value.SequenceToken)) { if (enforceSequenceToken) { // throw cache miss exception throw new QueueCacheMissException(sequenceToken, cachedMessages.Last.Value.SequenceToken, cachedMessages.First.Value.SequenceToken); } sequenceToken = lastMessage.Value.SequenceToken; } // Now the requested sequenceToken is set and is also within the limits of the cache. // Find first message at or below offset // Events are ordered from newest to oldest, so iterate from start of list until we hit a node at a previous offset, or the end. LinkedListNode<SimpleQueueCacheItem> node = cachedMessages.First; while (node != null && node.Value.SequenceToken.Newer(sequenceToken)) { // did we get to the end? if (node.Next == null) // node is the last message break; // if sequenceId is between the two, take the higher if (node.Next.Value.SequenceToken.Older(sequenceToken)) break; node = node.Next; } // return cursor from start. SetCursor(cursor, node); }
internal void InitializeCursor(SimpleQueueCacheCursor cursor, StreamSequenceToken sequenceToken, bool enforceSequenceToken) { Log(logger, "InitializeCursor: {0} to sequenceToken {1}", cursor, sequenceToken); if (cachedMessages.Count == 0) // nothing in cache { StreamSequenceToken tokenToReset = sequenceToken ?? (lastSequenceTokenAddedToCache != null ? ((EventSequenceToken)lastSequenceTokenAddedToCache).NextSequenceNumber() : null); ResetCursor(cursor, tokenToReset); return; } // if offset is not set, iterate from newest (first) message in cache, but not including the irst message itself if (sequenceToken == null) { StreamSequenceToken tokenToReset = lastSequenceTokenAddedToCache != null ? ((EventSequenceToken)lastSequenceTokenAddedToCache).NextSequenceNumber() : null; ResetCursor(cursor, tokenToReset); return; } if (sequenceToken.Newer(cachedMessages.First.Value.SequenceToken)) // sequenceId is too new to be in cache { ResetCursor(cursor, sequenceToken); return; } LinkedListNode <SimpleQueueCacheItem> lastMessage = cachedMessages.Last; // Check to see if offset is too old to be in cache if (sequenceToken.Older(lastMessage.Value.SequenceToken)) { if (enforceSequenceToken) { // throw cache miss exception throw new QueueCacheMissException(sequenceToken, cachedMessages.Last.Value.SequenceToken, cachedMessages.First.Value.SequenceToken); } sequenceToken = lastMessage.Value.SequenceToken; } // Now the requested sequenceToken is set and is also within the limits of the cache. // Find first message at or below offset // Events are ordered from newest to oldest, so iterate from start of list until we hit a node at a previous offset, or the end. LinkedListNode <SimpleQueueCacheItem> node = cachedMessages.First; while (node != null && node.Value.SequenceToken.Newer(sequenceToken)) { // did we get to the end? if (node.Next == null) // node is the last message { break; } // if sequenceId is between the two, take the higher if (node.Next.Value.SequenceToken.Older(sequenceToken)) { break; } node = node.Next; } // return cursor from start. SetCursor(cursor, node); }