Exemplo n.º 1
0
        private void Initialize()
        {
            var sleepTime          = 50;
            var lockAcquiringWatch = Stopwatch.StartNew();

            do
            {
                using (var connectionHolder = _connectionProvider.AcquireConnection())
                {
                    const string query        = @"
INSERT INTO lock(resource, acquired) 
VALUES (@resource, current_timestamp at time zone 'UTC')
ON CONFLICT (resource) DO NOTHING
;";
                    var          parameters   = new { resource = _resource };
                    var          rowsAffected = connectionHolder.Connection.Execute(query, parameters);

                    if (rowsAffected > 0)
                    {
                        return;
                    }
                }
            } while (IsNotTimeouted(lockAcquiringWatch.Elapsed, ref sleepTime));

            throw new DistributedLockTimeoutException(_resource);
        }
Exemplo n.º 2
0
        public void RemoveFromQueue()
        {
            const string query = @"
DELETE FROM jobqueue
WHERE id = @id;
";

            using (var connectionHolder = _connectionProvider.AcquireConnection())
            {
                connectionHolder.Connection.Execute(query, new { id = Id });
                _removedFromQueue = true;
            }
        }
Exemplo n.º 3
0
        public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken)
        {
            Guard.ThrowIfCollectionIsNullOrEmpty(queues, nameof(queues));

            var queuesList  = string.Join(",", queues.Select(x => $"'{x}'"));
            var queuesOrder = string.Join(",", queues.Select(x => $@"queue='{x}'"));

            var fetchJobSqlTemplate = $@"
UPDATE jobqueue AS jobqueue
SET fetchedat = NOW() AT TIME ZONE 'UTC'
WHERE jobqueue.id = (
    SELECT id
    FROM jobqueue
    WHERE queue IN ({queuesList})
    AND (fetchedat IS NULL OR fetchedat < NOW() AT TIME ZONE 'UTC' - @timeout)
    ORDER BY ({queuesOrder}) DESC
    LIMIT 1
    FOR UPDATE SKIP LOCKED)
RETURNING jobqueue.id AS Id, jobid AS JobId, queue AS Queue, fetchedat AS FetchedAt;
";

            FetchedJobDto fetchedJobDto;

            do
            {
                cancellationToken.ThrowIfCancellationRequested();

                using (var connectionHolder = _connectionProvider.AcquireConnection())
                {
                    fetchedJobDto = connectionHolder.Connection.Query <FetchedJobDto>(
                        fetchJobSqlTemplate,
                        new { queues = queues, timeout = _options.InvisibilityTimeout })
                                    .SingleOrDefault();
                }

                if (fetchedJobDto == null)
                {
                    cancellationToken.WaitHandle.WaitOne(_options.QueuePollInterval);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            } while (fetchedJobDto == null);

            return(new FetchedJob(
                       _connectionProvider,
                       fetchedJobDto.Id,
                       fetchedJobDto.JobId.ToString(CultureInfo.InvariantCulture),
                       fetchedJobDto.Queue));
        }
        private void AggregateCounter(string counterName)
        {
            using (var connectionHolder = _connectionProvider.AcquireConnection())
                using (var transaction = connectionHolder.Connection.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    const string aggregateQuery = @"
WITH counters AS (
DELETE FROM counter
WHERE key = @counterName
AND expireat IS NULL
RETURNING *
)

SELECT SUM(value) FROM counters;
";

                    var aggregatedValue = connectionHolder.Connection.ExecuteScalar <long>(aggregateQuery, new { counterName }, transaction);
                    transaction.Commit();

                    if (aggregatedValue > 0)
                    {
                        const string query = @"INSERT INTO counter (key, value) VALUES (@key, @value);";
                        connectionHolder.Connection.Execute(query, new { key = counterName, value = aggregatedValue });
                    }
                    Logger.InfoFormat("Aggregated counter \'{0}\', value: {1}", counterName, aggregatedValue);
                }
        }
Exemplo n.º 5
0
        private MongoReplyMessage <TDocument> GetNextBatch()
        {
            var connection = _connectionProvider.AcquireConnection();

            try
            {
                int numberToReturn;
                if (_limit == 0)
                {
                    numberToReturn = _batchSize;
                }
                else
                {
                    var numberToHitLimit = _limit - _count;
                    numberToReturn = (int)Math.Min(_batchSize, numberToHitLimit);
                }

                var getMoreMessage = new MongoGetMoreMessage(_collectionFullName, numberToReturn, _cursorId);
                connection.SendMessage(getMoreMessage);
                return(connection.ReceiveMessage <TDocument>(_readerSettings, _serializer, _serializationOptions));
            }
            finally
            {
                _connectionProvider.ReleaseConnection(connection);
            }
        }
 public override void Commit()
 {
     using (var connectionHolder = _connectionProvider.AcquireConnection())
         using (var transaction = connectionHolder.Connection.BeginTransaction(IsolationLevel.RepeatableRead))
         {
             foreach (var command in _commandQueue)
             {
                 command(connectionHolder.Connection, transaction);
             }
             transaction.Commit();
         }
 }
Exemplo n.º 7
0
        private void KillCursor(IConnectionProvider connectionProvider, long cursorId)
        {
            var connection = connectionProvider.AcquireConnection();

            try
            {
                var killCursorsMessage = new MongoKillCursorsMessage(cursorId);
                connection.SendMessage(killCursorsMessage);
            }
            finally
            {
                connectionProvider.ReleaseConnection(connection);
            }
        }
Exemplo n.º 8
0
        private MongoReplyMessage <TDocument> GetNextBatch(IConnectionProvider connectionProvider, long cursorId)
        {
            var connection = connectionProvider.AcquireConnection();

            try
            {
                var readerSettings = GetNodeAdjustedReaderSettings(connection.ServerInstance);
                var getMoreMessage = new MongoGetMoreMessage(CollectionFullName, _batchSize, cursorId);
                connection.SendMessage(getMoreMessage);
                return(connection.ReceiveMessage <TDocument>(readerSettings, _serializer, _serializationOptions));
            }
            finally
            {
                connectionProvider.ReleaseConnection(connection);
            }
        }
Exemplo n.º 9
0
        private MongoReplyMessage <TDocument> GetFirstBatch(IConnectionProvider connectionProvider)
        {
            // some of these weird conditions are necessary to get commands to run correctly
            // specifically numberToReturn has to be 1 or -1 for commands
            int numberToReturn;

            if (_limit < 0)
            {
                numberToReturn = _limit;
            }
            else if (_limit == 0)
            {
                numberToReturn = _batchSize;
            }
            else if (_batchSize == 0)
            {
                numberToReturn = _limit;
            }
            else if (_limit < _batchSize)
            {
                numberToReturn = _limit;
            }
            else
            {
                numberToReturn = _batchSize;
            }

            var connection = connectionProvider.AcquireConnection();

            try
            {
                var readerSettings = GetNodeAdjustedReaderSettings(connection.ServerInstance);
                var writerSettings = GetNodeAdjustedWriterSettings(connection.ServerInstance);
                var forShardRouter = connection.ServerInstance.InstanceType == MongoServerInstanceType.ShardRouter;
                var wrappedQuery   = WrapQuery(_query, _options, _readPreference, forShardRouter);
                var queryMessage   = new MongoQueryMessage(writerSettings, CollectionFullName, _flags, _skip, numberToReturn, wrappedQuery, _fields);
                connection.SendMessage(queryMessage);
                return(connection.ReceiveMessage <TDocument>(readerSettings, _serializer, _serializationOptions));
            }
            finally
            {
                connectionProvider.ReleaseConnection(connection);
            }
        }
Exemplo n.º 10
0
        public void Execute(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using (var connectionHolder = _connectionProvider.AcquireConnection())
            {
                const string query = @"
DELETE FROM lock
WHERE acquired < current_timestamp at time zone 'UTC' - @timeout";

                var parameters = new
                {
                    timeout = _lockTimeOut
                };
                connectionHolder.Connection.Execute(query, parameters);
            }

            cancellationToken.WaitHandle.WaitOne(_lockTimeOut);
        }
Exemplo n.º 11
0
        public void Initialize()
        {
            Log.Info("Start installing Hangfire SQL objects...");

            using (var connectionHolder = _connectionProvider.AcquireConnection())
            {
                var connection = connectionHolder.Connection;
                var locked     = LockDatabase(connection);
                if (!locked)
                {
                    return;
                }

                TryCreateSchema(connection);
                var installedVersion    = GetInstalledVersion(connection);
                var availableMigrations = GetMigrations().Where(x => x.Version > installedVersion).ToArray();
                if (availableMigrations.Length == 0)
                {
                    return;
                }

                using (var transaction = connection.BeginTransaction(IsolationLevel.Serializable))
                {
                    var lastMigration = default(MigrationInfo);
                    foreach (var migration in availableMigrations)
                    {
                        connection.Execute(migration.Script, transaction: transaction);
                        lastMigration = migration;
                    }

                    connection.Execute(
                        @"UPDATE schema SET version = @version WHERE version = @installedVersion",
                        new { lastMigration.Version, installedVersion },
                        transaction);

                    transaction.Commit();
                }

                UnlockDatabase(connection);
            }

            Log.Info("Hangfire SQL objects installed.");
        }
        public void Execute(CancellationToken cancellationToken)
        {
            foreach (var table in ProcessedTables)
            {
                Logger.DebugFormat("Removing outdated records from table '{0}'...", table);

                int removedCount;
                do
                {
                    using (var connectionHolder = _connectionProvider.AcquireConnection())
                        using (var transaction = connectionHolder.Connection.BeginTransaction(IsolationLevel.ReadCommitted))
                        {
                            // Pgsql doesn't support parameters for table names that's why you're going this 'awful' sql query interpolation
                            var query = $@"
DELETE FROM {table}
WHERE id IN (
    SELECT id
    FROM {table}
    WHERE expireat < NOW() AT TIME ZONE 'UTC' 
    LIMIT {Convert.ToString(NumberOfRecordsInSinglePass, CultureInfo.InvariantCulture)}
)";
                            removedCount = connectionHolder.Connection.Execute(query, transaction: transaction);
                            transaction.Commit();
                        }

                    if (removedCount > 0)
                    {
                        Logger.InfoFormat("Removed {0} outdated record(s) from '{1}' table.", removedCount, table);

                        cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses);
                        cancellationToken.ThrowIfCancellationRequested();
                    }
                } while (removedCount != 0);
            }
            cancellationToken.WaitHandle.WaitOne(_checkInterval);
            cancellationToken.ThrowIfCancellationRequested();
        }
Exemplo n.º 13
0
 private long GetLong(string queue, string query)
 {
     using (var connectionHolder = _connectionProvider.AcquireConnection())
     {
         var result = connectionHolder.Connection.ExecuteScalar <long>(query, new { queue = queue });
         return(result);
     }
 }
        public override string CreateExpiredJob(
            Job job,
            IDictionary <string, string> parameters,
            DateTime createdAt,
            TimeSpan expireIn)
        {
            Guard.ThrowIfNull(job, nameof(job));
            Guard.ThrowIfNull(parameters, nameof(parameters));

            const string createJobSql   = @"
INSERT INTO job (invocationdata, arguments, createdat, expireat)
VALUES (@invocationData, @arguments, @createdAt, @expireAt) 
RETURNING id;
";
            var          invocationData = InvocationData.Serialize(job);

            int jobId;

            using (var connectionHolder = _connectionProvider.AcquireConnection())
            {
                var connection = connectionHolder.Connection;
                jobId = connection.Query <int>(
                    createJobSql,
                    new
                {
                    invocationData = JobHelper.ToJson(invocationData),
                    arguments      = invocationData.Arguments,
                    createdAt      = createdAt,
                    expireAt       = createdAt.Add(expireIn)
                }).Single();
            }

            if (parameters.Count > 0)
            {
                var parameterArray = new object[parameters.Count];
                var parameterIndex = 0;
                foreach (var parameter in parameters)
                {
                    parameterArray[parameterIndex++] = new
                    {
                        jobId = jobId,
                        name  = parameter.Key,
                        value = parameter.Value
                    };
                }

                const string insertParameterSql = @"
INSERT INTO jobparameter (jobid, name, value)
VALUES (@jobId, @name, @value);
";
                using (var connectionHolder = _connectionProvider.AcquireConnection())
                {
                    connectionHolder.Connection.Execute(insertParameterSql, parameterArray);
                }
            }
            return(jobId.ToString(CultureInfo.InvariantCulture));
        }