Exemple #1
0
        public T Receive()
        {
            // for reading, we give the impression to the client that we provide a single message at a time
            // which means we maintain a cursor and enumerator in the background and hide it from the caller

            if (_enumerator == null)
            {
                _enumerator = InitializeCursor();
            }

            // there is no end when you need to sit and wait for messages to arrive
            while (true)
            {
                try
                {
                    // do we have a message waiting?
                    // this may block on the server for a few seconds but will return as soon as something is available
                    if (_enumerator.MoveNext())
                    {
                        // yes - record the current position and return it to the client
                        _startedReading = true;
                        _lastId         = _enumerator.Current.Id;
                        _position.Update(_positionQuery, Update.Set("last", _lastId), UpdateFlags.Upsert, SafeMode.False);

                        var message = _enumerator.Current.Message;
                        var delay   = DateTime.UtcNow - _enumerator.Current.Enqueued;
                        Log.Debug(m => m("Received {0} after {1}", _queueName, delay));
                        return(message);
                    }

                    if (!_startedReading)
                    {
                        // for an empty collection, we'll need to re-query to be notified of new records
                        Log.Debug("Cursor Empty");
                        Thread.Sleep(100);
                        _enumerator.Dispose();
                        _enumerator = InitializeCursor();
                    }
                    else
                    {
                        // if the cursor is dead then we need to re-query, otherwise we just go back to iterating over it
                        if (_enumerator.IsDead)
                        {
                            Log.Debug("Cursor Dead");
                            _enumerator.Dispose();
                            _enumerator = InitializeCursor();
                        }
                    }
                }
                catch (Exception ex)
                {
                    // cursor died or was killed
                    _enumerator.Dispose();
                    _enumerator = InitializeCursor();
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Receives an event (or action) from queue. Does not change the message state. Used for PubSub (1 to Many - all gets the same messages) use cases
        /// </summary>
        /// <returns></returns>
        private T ReceiveEvent()
        {
            if (_enumerator == null)
            {
                _enumerator = InitializeCursor();
            }

            // running untill we have something to return
            while (true)
            {
                var t1 = DateTime.UtcNow;
                try
                {
                    // do we have a message waiting?
                    // this may block on the server for a few seconds but will return as soon as something is available

                    if (_enumerator.MoveNext())
                    {
                        // yes - record the current position and return it to the client
                        Interlocked.Increment(ref _totalReceived);
                        _lastId = _enumerator.Current.Id;

                        var current = _enumerator.Current;
                        var message = current.Message;
                        var delay   = DateTime.UtcNow - _enumerator.Current.Enqueued;
                        Log.Debug(m => m("Received {0} after {1}", _queueName, delay));
                        return(message);
                    }

                    // if the cursor is dead then we need to re-query, otherwise we just go back to iterating over it
                    if (_enumerator.IsDead)
                    {
                        Log.Debug("Cursor Dead");
                        _enumerator.Dispose();
                        _enumerator = InitializeCursor();
                    }

                    // If we are here it means that the server returned without items, usually it sits in a 2 seconds block on the server, but if initial request is empty then return immedietly.
                    //This is a safety mechanism to protect the mongo server from our DOS...(due to this cursor behavior, and from unknown bugs / 'behaviors')
                    var iterationTime = DateTime.UtcNow - t1;
                    if (iterationTime.TotalMilliseconds < SHORT_SLEEP_INTERVAL) // minimal polling interval : TODO - move to Config
                    {
                        Thread.Sleep(SHORT_SLEEP_INTERVAL);
                    }
                }
                catch (Exception ex)
                {
                    Log.Warn("[ReceiveEvents inside while true] Got exception. Will reinitialize and continue. Ex={0}", ex);
                    // cursor died or was killed
                    if (_enumerator != null)
                    {
                        _enumerator.Dispose();
                    }
                    _enumerator = InitializeCursor();

                    //This is a safety mechanism to protect the mongo server from our DOS...
                    var iterationTime = DateTime.UtcNow - t1;
                    if (iterationTime.TotalMilliseconds < SHORT_SLEEP_INTERVAL) // minimal polling interval : TODO - move to Config
                    {
                        Thread.Sleep(SHORT_SLEEP_INTERVAL);
                    }
                }
            }
        }