public Task <MessageResult> GetMessages(IEnumerable <string> eventKeys, string id, CancellationToken cancellationToken) { TimeSpan timeout = TimeSpan.FromSeconds(55); int maxMessages = 100; // let's make sure we've got the message pump into the caches running this.EnsureOpen(); var compositeCursor = new CompositeCursor(id, this.NumberOfTopics); // grab what we can synchronously from the cache var messages = this.FetchAvailableMessagesFromCache(compositeCursor, eventKeys, maxMessages); if (messages.Count == 0) { // cache is drained for this client, so we'll have to wait for new messages return(new TaskFactory <MessageResult>().FromAsync( (cb, s) => this.BeginGetMessagesFromCache(eventKeys, compositeCursor, maxMessages, cancellationToken, cb, s), this.EndGetMessagesFromCache, null)); } // got a batch of messages, let's return it as a synchronous result var r = new TaskCompletionSource <MessageResult>(); if (cancellationToken.IsCancellationRequested) { r.SetCanceled(); } else { r.SetResult(new MessageResult(messages, compositeCursor.Cookie)); } return(r.Task); }
IList <Message> FetchAvailableMessagesFromCache(CompositeCursor compositeCursor, IEnumerable <string> eventKeys, int maxMessages) { var messages = new List <Message>(); bool gotAny; do { gotAny = false; for (var i = 0; i < this.NumberOfTopics; i++) { if (compositeCursor.CursorInitFlags[i]) { var hwmi = compositeCursor.Cursors[i]; Message msg; if (this.caches[i].TryGetNext(eventKeys, ref hwmi, out msg)) { gotAny = true; messages.Add(msg); compositeCursor.Cursors[i] = hwmi; if (messages.Count >= maxMessages) { // have enough? // cheat to get out of the outer loop gotAny = false; // and GTFO break; } } else { // try does advance the cursor compositeCursor.Cursors[i] = hwmi; } } else { ushort cursor; if (caches[i].TryGetTopOfSequenceCursor(out cursor)) { compositeCursor.CursorInitFlags[i] = true; compositeCursor.Cursors[i] = cursor; } } } }while (gotAny); messages.Sort((m1, m2) => m1.Created.CompareTo(m2.Created)); return(messages); }
public GetMessagesFromCacheAsyncResult( ServiceBusMessageBus that, IEnumerable <string> keys, CompositeCursor compositeCursor, int maxMessages, CancellationToken cancellationToken, AsyncCallback callback, object state) : base(callback, state) { this.that = that; this.keys = keys; this.compositeCursor = compositeCursor; this.maxMessages = maxMessages; this.cancellationToken = cancellationToken; this.mad = new MessageAvailableDispatcher(this.MessageAvailable, that.caches, keys, cancellationToken); this.cancellationToken.Register(Cancel); }
public Task<MessageResult> GetMessages(IEnumerable<string> eventKeys, string id, CancellationToken cancellationToken) { TimeSpan timeout = TimeSpan.FromSeconds(55); int maxMessages = 100; // let's make sure we've got the message pump into the caches running this.EnsureOpen(); var compositeCursor = new CompositeCursor(id, this.NumberOfTopics); // grab what we can synchronously from the cache var messages = this.FetchAvailableMessagesFromCache(compositeCursor, eventKeys, maxMessages); if (messages.Count == 0) { // cache is drained for this client, so we'll have to wait for new messages return new TaskFactory<MessageResult>().FromAsync( (cb, s) => this.BeginGetMessagesFromCache(eventKeys, compositeCursor, maxMessages, cancellationToken, cb, s), this.EndGetMessagesFromCache, null); } // got a batch of messages, let's return it as a synchronous result var r = new TaskCompletionSource<MessageResult>(); if (cancellationToken.IsCancellationRequested) { r.SetCanceled(); } else { r.SetResult(new MessageResult(messages, compositeCursor.Cookie)); } return r.Task; }
IAsyncResult BeginGetMessagesFromCache(IEnumerable<string> eventKeys, CompositeCursor id, int maxMessages, CancellationToken cancellationToken, AsyncCallback callback, object state) { return new GetMessagesFromCacheAsyncResult(this, eventKeys, id, maxMessages, cancellationToken, callback, state); }
IList<Message> FetchAvailableMessagesFromCache(CompositeCursor compositeCursor, IEnumerable<string> eventKeys, int maxMessages) { var messages = new List<Message>(); bool gotAny; do { gotAny = false; for (var i = 0; i < this.NumberOfTopics; i++) { if (compositeCursor.CursorInitFlags[i]) { var hwmi = compositeCursor.Cursors[i]; Message msg; if (this.caches[i].TryGetNext(eventKeys, ref hwmi, out msg)) { gotAny = true; messages.Add(msg); compositeCursor.Cursors[i] = hwmi; if (messages.Count >= maxMessages) { // have enough? // cheat to get out of the outer loop gotAny = false; // and GTFO break; } } else { // try does advance the cursor compositeCursor.Cursors[i] = hwmi; } } else { ushort cursor; if (caches[i].TryGetTopOfSequenceCursor(out cursor)) { compositeCursor.CursorInitFlags[i] = true; compositeCursor.Cursors[i] = cursor; } } } } while (gotAny); messages.Sort((m1, m2) => m1.Created.CompareTo(m2.Created)); return messages; }
IAsyncResult BeginGetMessagesFromCache(IEnumerable <string> eventKeys, CompositeCursor id, int maxMessages, CancellationToken cancellationToken, AsyncCallback callback, object state) { return(new GetMessagesFromCacheAsyncResult(this, eventKeys, id, maxMessages, cancellationToken, callback, state)); }