public async Task Execute(IDurabilityAgentStorage storage, IDurabilityAgent agent)
        {
            if (_workers.QueuedCount > _options.MaximumLocalEnqueuedBackPressureThreshold)
            {
                return;
            }

            await storage.Session.Begin();


            Envelope[] incoming = null;
            try
            {
                var gotLock = await storage.Session.TryGetGlobalLock(TransportConstants.IncomingMessageLockId);

                if (!gotLock)
                {
                    await storage.Session.Rollback();

                    return;
                }

                incoming = await storage.Incoming.LoadPageOfLocallyOwned();

                if (!incoming.Any())
                {
                    await storage.Session.Rollback();

                    return;
                }

                await storage.Incoming.Reassign(_options.UniqueNodeId, incoming);

                await storage.Session.Commit();
            }
            catch (Exception)
            {
                await storage.Session.Rollback();

                throw;
            }
            finally
            {
                await storage.Session.ReleaseGlobalLock(TransportConstants.IncomingMessageLockId);
            }

            _logger.RecoveredIncoming(incoming);

            foreach (var envelope in incoming)
            {
                envelope.OwnerId = _options.UniqueNodeId;
                await _workers.Enqueue(envelope);
            }

            if (incoming.Length == _options.Retries.RecoveryBatchSize &&
                _workers.QueuedCount < _options.MaximumLocalEnqueuedBackPressureThreshold)
            {
                agent.RescheduleIncomingRecovery();
            }
        }
Exemple #2
0
        public async Task Execute(IDurabilityAgentStorage storage, IDurabilityAgent agent)
        {
            // TODO -- enforce back pressure here on the retries listener!

            await storage.Session.Begin();


            Envelope[] incoming = null;
            try
            {
                var gotLock = await storage.Session.TryGetGlobalLock(TransportConstants.IncomingMessageLockId);

                if (!gotLock)
                {
                    await storage.Session.Rollback();

                    return;
                }

                incoming = await storage.Incoming.LoadPageOfLocallyOwned();

                if (!incoming.Any())
                {
                    await storage.Session.Rollback();

                    return;
                }

                await storage.Incoming.Reassign(_settings.UniqueNodeId, incoming);

                await storage.Session.Commit();
            }
            catch (Exception)
            {
                await storage.Session.Rollback();

                throw;
            }
            finally
            {
                await storage.Session.ReleaseGlobalLock(TransportConstants.IncomingMessageLockId);
            }

            _logger.RecoveredIncoming(incoming);

            foreach (var envelope in incoming)
            {
                envelope.OwnerId  = _settings.UniqueNodeId;
                envelope.Callback = new DurableCallback(envelope, _workers, _persistence, _logger);
                await _workers.Enqueue(envelope);
            }

            // TODO -- this should be smart enough later to check for back pressure before rescheduling
            if (incoming.Length == _settings.RecoveryBatchSize)
            {
                agent.RescheduleIncomingRecovery();
            }
        }
Exemple #3
0
        public async Task Execute(SqlConnection conn, ISchedulingAgent agent)
        {
            if (_workers.QueuedCount > _settings.MaximumLocalEnqueuedBackPressureThreshold)
            {
                return;
            }

            var tx = conn.BeginTransaction();


            List <Envelope> incoming = null;

            try
            {
                if (!await conn.TryGetGlobalTxLock(tx, IncomingMessageLockId))
                {
                    tx.Rollback();
                    return;
                }

                incoming = await conn.CreateCommand(tx, _findAtLargeEnvelopesSql)
                           .ExecuteToEnvelopes();

                if (!incoming.Any())
                {
                    tx.Rollback();
                    return;
                }

                await markOwnership(conn, tx, incoming);

                tx.Commit();
            }
            catch (Exception)
            {
                tx.Rollback();
                throw;
            }

            _logger.RecoveredIncoming(incoming);

            foreach (var envelope in incoming)
            {
                envelope.OwnerId = _settings.UniqueNodeId;
                await _workers.Enqueue(envelope);
            }

            if (incoming.Count == _settings.Retries.RecoveryBatchSize &&
                _workers.QueuedCount < _settings.MaximumLocalEnqueuedBackPressureThreshold)
            {
                agent.RescheduleIncomingRecovery();
            }
        }
Exemple #4
0
        public async Task Execute(IDocumentSession session, ISchedulingAgent agent)
        {
            if (_workers.QueuedCount > _settings.MaximumLocalEnqueuedBackPressureThreshold)
            {
                return;
            }

            if (!await session.TryGetGlobalTxLock(IncomingMessageLockId))
            {
                return;
            }

            var incoming = await session.Connection.CreateCommand(_findAtLargeEnvelopesSql)
                           .ExecuteToEnvelopes();

            if (!incoming.Any())
            {
                return;
            }

            session.MarkOwnership(_marker.Incoming, _settings.UniqueNodeId, incoming);

            await session.SaveChangesAsync();

            _logger.RecoveredIncoming(incoming);

            foreach (var envelope in incoming)
            {
                envelope.OwnerId = _settings.UniqueNodeId;
                await _workers.Enqueue(envelope);
            }

            if (incoming.Count == _settings.Retries.RecoveryBatchSize &&
                _workers.QueuedCount < _settings.MaximumLocalEnqueuedBackPressureThreshold)
            {
                agent.RescheduleIncomingRecovery();
            }
        }