예제 #1
0
        public void RemoveFromQueue()
        {
            lock (_syncRoot)
            {
                _storage.UseConnection(null, connection =>
                {
                    connection.Execute(
                        $"delete from {_storage.SchemaName}.JobQueue where Id = @id",
                        new { id = Id },
                        commandTimeout: _storage.CommandTimeout);
                });

                _removedFromQueue = true;
            }
        }
예제 #2
0
        private void UseConnectionDistributedLock(SqlServerStorage storage, Action <DbConnection> action)
        {
            try
            {
                storage.UseConnection(null, connection =>
                {
                    SqlServerDistributedLock.Acquire(connection, DistributedLockKey, DefaultLockTimeout);

                    try
                    {
                        action(connection);
                    }
                    finally
                    {
                        SqlServerDistributedLock.Release(connection, DistributedLockKey);
                    }
                });
            }
            catch (DistributedLockTimeoutException e) when(e.Resource == DistributedLockKey)
            {
                // DistributedLockTimeoutException here doesn't mean that outdated records weren't removed.
                // It just means another Hangfire server did this work.
                _logger.Log(
                    LogLevel.Debug,
                    () => $@"An exception was thrown during acquiring distributed lock on the {DistributedLockKey} resource within {DefaultLockTimeout.TotalSeconds} seconds. Outdated records were not removed.
It will be retried in {_checkInterval.TotalSeconds} seconds.",
                    e);
            }
        }
예제 #3
0
        public void Execute(CancellationToken cancellationToken)
        {
            Logger.Debug("Aggregating records in 'Counter' table...");

            int removedCount = 0;

            do
            {
                _storage.UseConnection(null, connection =>
                {
                    removedCount = connection.Execute(
                        GetAggregationQuery(_storage),
                        new { now = DateTime.UtcNow, count = NumberOfRecordsInSinglePass },
                        commandTimeout: 0);
                });

                if (removedCount >= NumberOfRecordsInSinglePass)
                {
                    cancellationToken.Wait(DelayBetweenPasses);
                    cancellationToken.ThrowIfCancellationRequested();
                }
                // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
            } while (removedCount >= NumberOfRecordsInSinglePass);

            Logger.Trace("Records from the 'Counter' table aggregated.");

            cancellationToken.Wait(_interval);
        }
예제 #4
0
        public void Execute(CancellationToken cancellationToken)
        {
            foreach (var table in ProcessedTables)
            {
                Logger.Debug($"Removing outdated records from the '{table}' table...");

                _storage.UseConnection(connection =>
                {
                    SqlServerDistributedLock.Acquire(connection, DistributedLockKey, DefaultLockTimeout);

                    try
                    {
                        ExecuteNonQuery(
                            connection,
                            GetQuery(_storage.SchemaName, table),
                            cancellationToken,
                            new SqlParameter("@count", NumberOfRecordsInSinglePass),
                            new SqlParameter("@now", DateTime.UtcNow));
                    }
                    finally
                    {
                        SqlServerDistributedLock.Release(connection, DistributedLockKey);
                    }
                });

                Logger.Trace($"Outdated records removed from the '{table}' table.");
            }

            cancellationToken.WaitHandle.WaitOne(_checkInterval);
        }
예제 #5
0
        public void RemoveFromQueue()
        {
            lock (_syncRoot)
            {
                if (!FetchedAt.HasValue)
                {
                    return;
                }

                _storage.UseConnection(null, connection =>
                {
                    connection.Execute(
                        $"delete JQ from [{_storage.SchemaName}].JobQueue JQ with ({GetTableHints()}) where Queue = @queue and Id = @id and FetchedAt = @fetchedAt",
                        new { queue = Queue, id = Id, fetchedAt = FetchedAt },
                        commandTimeout: _storage.CommandTimeout);
                });

                _removedFromQueue = true;
            }
        }
예제 #6
0
        public void Execute(CancellationToken cancellationToken)
        {
            foreach (var table in ProcessedTables)
            {
                Logger.DebugFormat("Removing outdated records from table '{0}'...", table);

                int removedCount = 0;

                do
                {
                    _storage.UseConnection(connection =>
                    {
                        SqlServerDistributedLock.Acquire(connection, DistributedLockKey, DefaultLockTimeout);

                        try
                        {
                            removedCount = connection.Execute(
                                String.Format(@"
set transaction isolation level read committed;
delete top (@count) from [{0}].[{1}] with (readpast) where ExpireAt < @now;", _storage.GetSchemaName(), table),
                                new { now = DateTime.UtcNow, count = NumberOfRecordsInSinglePass });
                        }
                        finally
                        {
                            SqlServerDistributedLock.Release(connection, DistributedLockKey);
                        }
                    });

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

                        cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses);
                        cancellationToken.ThrowIfCancellationRequested();
                    }
                } while (removedCount != 0);
            }

            cancellationToken.WaitHandle.WaitOne(_checkInterval);
        }
예제 #7
0
        public void Execute(CancellationToken cancellationToken)
        {
            foreach (var table in ProcessedTables)
            {
                Logger.Debug($"Removing outdated records from table '{table}'...");

                int removedCount = 0;

                do
                {
                    _storage.UseConnection(connection =>
                    {
                        SqlServerDistributedLock.Acquire(connection, DistributedLockKey, DefaultLockTimeout);

                        try
                        {
                            removedCount = connection.Execute(
                                $@"set transaction isolation level read committed;
delete top (@count) from [{_storage.SchemaName}].[{table}] with (readpast) where ExpireAt < @now;",
                                new { now = DateTime.UtcNow, count = NumberOfRecordsInSinglePass });
                        }
                        finally
                        {
                            SqlServerDistributedLock.Release(connection, DistributedLockKey);
                        }
                    });

                    if (removedCount > 0)
                    {
                        Logger.Trace($"Removed {removedCount} outdated record(s) from '{table}' table.");

                        cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses);
                        cancellationToken.ThrowIfCancellationRequested();
                    }
                    // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
                } while (removedCount != 0);
            }

            cancellationToken.WaitHandle.WaitOne(_checkInterval);
        }
예제 #8
0
        public void Execute(CancellationToken cancellationToken)
        {
            Logger.DebugFormat("Aggregating records in 'Counter' table...");

            int removedCount = 0;

            do
            {
                _storage.UseConnection(connection =>
                {
                    removedCount = connection.Execute(
                        GetAggregationQuery(_storage),
                        new { now = DateTime.UtcNow, count = NumberOfRecordsInSinglePass });
                });

                if (removedCount >= NumberOfRecordsInSinglePass)
                {
                    cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            } while (removedCount >= NumberOfRecordsInSinglePass);

            cancellationToken.WaitHandle.WaitOne(_interval);
        }
예제 #9
0
        public override string CreateExpiredJob(
            Job job,
            IDictionary <string, string> parameters,
            DateTime createdAt,
            TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            string createJobSql =
                $@"insert into [{_storage.SchemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt)
output inserted.Id
values (@invocationData, @arguments, @createdAt, @expireAt)";

            var invocationData = InvocationData.Serialize(job);

            return(_storage.UseConnection(_dedicatedConnection, connection =>
            {
                var jobId = connection.ExecuteScalar <long>(
                    createJobSql,
                    new
                {
                    invocationData = JobHelper.ToJson(invocationData),
                    arguments = invocationData.Arguments,
                    createdAt = createdAt,
                    expireAt = createdAt.Add(expireIn)
                },
                    commandTimeout: _storage.CommandTimeout).ToString();

                if (parameters.Count > 0)
                {
                    string insertParameterSql =
                        $@"insert into [{_storage.SchemaName}].JobParameter (JobId, Name, Value)
values (@jobId, @name, @value)";

                    var commandBatch = new SqlCommandBatch(preferBatching: _storage.CommandBatchMaxTimeout.HasValue);

                    foreach (var parameter in parameters)
                    {
                        commandBatch.Append(insertParameterSql,
                                            new SqlParameter("@jobId", long.Parse(jobId)),
                                            new SqlParameter("@name", parameter.Key),
                                            new SqlParameter("@value", (object)parameter.Value ?? DBNull.Value));
                    }

                    commandBatch.Connection = connection;
                    commandBatch.CommandTimeout = _storage.CommandTimeout;
                    commandBatch.CommandBatchMaxTimeout = _storage.CommandBatchMaxTimeout;

                    commandBatch.ExecuteNonQuery();
                }

                return jobId;
            }));
        }
예제 #10
0
        public override string CreateExpiredJob(
            Job job,
            IDictionary <string, string> parameters,
            DateTime createdAt,
            TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            string createJobSql =
                $@"insert into [{_storage.SchemaName}].Job (Id, InvocationData, Arguments, CreatedAt, ExpireAt)
output inserted.Id
values (@id, @invocationData, @arguments, @createdAt, @expireAt)";

            var invocationData = InvocationData.Serialize(job);

            return(_storage.UseConnection(connection =>
            {
                var jobId = Guid.NewGuid();
                connection.Execute(
                    createJobSql,
                    new
                {
                    id = jobId,
                    invocationData = JobHelper.ToJson(invocationData),
                    arguments = invocationData.Arguments,
                    createdAt = createdAt,
                    expireAt = createdAt.Add(expireIn)
                },
                    commandTimeout: _storage.CommandTimeout).ToString();

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

                    string insertParameterSql =
                        $@"insert into [{_storage.SchemaName}].JobParameter (Id, JobId, Name, Value)
values (@id, @jobId, @name, @value)";

                    connection.Execute(insertParameterSql, parameterArray, commandTimeout: _storage.CommandTimeout);
                }

                return jobId.ToString();
            }));
        }
예제 #11
0
 private T UseConnection <T>(Func <DbConnection, T> action)
 {
     return(_storage.UseConnection(action));
 }
        public override string CreateExpiredJob(
            Job job,
            IDictionary <string, string> parameters,
            DateTime createdAt,
            TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            string createJobSql =
                $@"insert into [{_storage.SchemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt)
values (@invocationData, @arguments, @createdAt, @expireAt);
SELECT CAST(SCOPE_IDENTITY() as int)";

            var invocationData = InvocationData.Serialize(job);

            return(_storage.UseConnection(connection =>
            {
                var jobId = connection.Query <int>(
                    createJobSql,
                    new
                {
                    invocationData = JobHelper.ToJson(invocationData),
                    arguments = invocationData.Arguments,
                    createdAt = createdAt,
                    expireAt = createdAt.Add(expireIn)
                }).Single().ToString();

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

                    string insertParameterSql =
                        $@"insert into [{_storage.SchemaName}].JobParameter (JobId, Name, Value)
values (@jobId, @name, @value)";

                    connection.Execute(insertParameterSql, parameterArray);
                }

                return jobId;
            }));
        }