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); }
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; } }
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); } }
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(); } }
private void KillCursor(IConnectionProvider connectionProvider, long cursorId) { var connection = connectionProvider.AcquireConnection(); try { var killCursorsMessage = new MongoKillCursorsMessage(cursorId); connection.SendMessage(killCursorsMessage); } finally { connectionProvider.ReleaseConnection(connection); } }
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); } }
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); } }
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); }
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(); }
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)); }