private int Dequeue(ITransactionalQueue <XDoc> queue, ManualResetEvent trigger) { trigger.WaitOne(); var j = 0; ITransactionalQueueEntry <XDoc> value = queue.Dequeue(); while (value != null) { bool success = queue.CommitDequeue(value.Id); if (!success) { throw new InvalidOperationException(); } j++; value = queue.Dequeue(); } return(j); }
private void TryDequeue() { _dequeueHandler(_currentItem.Value).WhenDone(r => { lock(_queue) { if(_isDisposed) { return; } if(r.HasException || !r.Value) { if(_failureWindowStart == DateTime.MinValue) { _failureWindowStart = DateTime.UtcNow; } _queueTimer.Change(_retryTime, TaskEnv.None); return; } _failureWindowStart = DateTime.MinValue; _queue.CommitDequeue(_currentItem.Id); _currentItem = _queue.Dequeue(); if(_currentItem == null) { return; } } TryDequeue(); }); }
private void Load_test(Func <TransactionalQueue <XDoc> > ctor) { var rand = new Random(); var queue = new QHandle(ctor); try { var pending = new Queue <ITransactionalQueueEntry <XDoc> >(); var n = 10000; var w = 10; var start = new int[n * w]; var end = new HashSet <int>(); var expired = 0; var dropped = 0; var enqueued = 0; bool done = false; var trigger = new ManualResetEvent(false); var results = new List <Result>(); int v = 0; for (var i = 0; i < w; i++) { var values = new List <int>(); for (var j = 0; j < n; j++) { values.Add(v); start[v] = v; v++; } results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); foreach (var vx in values) { queue.Execute(q => q.Enqueue(new XDoc("doc").Attr("id", vx).Elem("rand", StringUtil.CreateAlphaNumericKey(rand.Next(2, 8))))); Interlocked.Increment(ref enqueued); Thread.Sleep(rand.Next(0, 1)); } }, new Result())); } for (var i = 0; i < 10; i++) { results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); while (!done) { ITransactionalQueueEntry <XDoc> vx = null; queue.Execute(q => vx = q.Dequeue()); if (vx == null) { Thread.Sleep(1000); continue; } lock (pending) { pending.Enqueue(vx); } } }, new Result())); } for (var i = 0; i < 5; i++) { results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); while (!done) { ITransactionalQueueEntry <XDoc> vx = null; lock (pending) { if (pending.Count == 0) { Thread.Sleep(1); continue; } vx = pending.Dequeue(); } var success = false; queue.Execute(q => success = q.CommitDequeue(vx.Id)); if (!success) { Interlocked.Increment(ref expired); continue; } lock (end) { end.Add(vx.Value["@id"].AsInt ?? -1); } } }, new Result())); } results.Add(AsyncUtil.ForkThread(() => { trigger.WaitOne(); while (!done) { ITransactionalQueueEntry <XDoc> vx = null; lock (pending) { if (pending.Count == 0) { Thread.Sleep(1000); continue; } vx = pending.Dequeue(); } queue.Execute(q => q.RollbackDequeue(vx.Id)); Interlocked.Increment(ref dropped); Thread.Sleep(500); } }, new Result())); trigger.Set(); int waitCounter = 0; while (end.Count != start.Length) { var qcount = 0; queue.Execute(q => qcount = q.Count); Console.WriteLine("enqueued: {0}, queue size: {1}, output size: {2}, dropped items: {3}, expired items: {4}", enqueued, qcount, end.Count, dropped, expired); foreach (var r in results) { if (r.HasException) { r.Wait(); } } Thread.Sleep(1000); waitCounter++; if (waitCounter > 5) { waitCounter = 0; Console.WriteLine("refreshing queue"); queue.Refresh(); } } done = true; foreach (var r in results) { r.Wait(); } Assert.AreEqual(start, (from x in end orderby x select x).ToArray()); Console.WriteLine("total queue items expired: {0}", expired); } finally { queue.Dispose(); } }
private void Kick() { if(_currentItem != null || _dequeueHandler == null) { return; } lock(_queue) { if(_currentItem != null) { return; } _currentItem = _queue.Dequeue(); if(_currentItem == null) { return; } Async.Fork(TryDequeue); } }