public override void SetRangeInHash(string key, IEnumerable <KeyValuePair <string, string> > keyValuePairs)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (keyValuePairs == null)
            {
                throw new ArgumentNullException(nameof(keyValuePairs));
            }

            string sql =
                $@";merge [{_storage.SchemaName}].Hash with (holdlock) as Target
using (VALUES (@key, @field, @value)) as Source ([Key], Field, Value)
on Target.[Key] = Source.[Key] and Target.Field = Source.Field
when matched then update set Value = Source.Value
when not matched then insert ([Key], Field, Value) values (Source.[Key], Source.Field, Source.Value);";

            _storage.UseTransaction(_dedicatedConnection, (connection, transaction) =>
            {
                var commandBatch = new SqlCommandBatch(preferBatching: _storage.CommandBatchMaxTimeout.HasValue);

                foreach (var keyValuePair in keyValuePairs)
                {
                    commandBatch.Append(sql,
                                        new SqlParameter("@key", key),
                                        new SqlParameter("@field", keyValuePair.Key),
                                        new SqlParameter("@value", (object)keyValuePair.Value ?? DBNull.Value));
                }

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

                commandBatch.ExecuteNonQuery();
            });
        }
        public override void Commit()
        {
            _storage.UseTransaction(_dedicatedConnectionFunc(), (connection, transaction) =>
            {
                var commandBatch = new SqlCommandBatch(preferBatching: _storage.CommandBatchMaxTimeout.HasValue);

                foreach (var lockedResource in _lockedResources)
                {
                    commandBatch.Append(
                        "set nocount on;exec sp_getapplock @Resource=@resource, @LockMode=N'Exclusive'",
                        new SqlParameter("@resource", lockedResource));
                }

                foreach (var command in _commandQueue)
                {
                    commandBatch.Append(command.Item1, command.Item2);
                }

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

                commandBatch.ExecuteNonQuery();

                foreach (var queueCommand in _queueCommandQueue)
                {
                    queueCommand(connection, transaction);
                }
            });

            foreach (var command in _afterCommitCommandQueue)
            {
                command();
            }
        }
예제 #3
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));
            }

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

            var invocationData = InvocationData.SerializeJob(job);
            var payload        = invocationData.SerializePayload(excludeArguments: true);

            var queryParameters = new DynamicParameters();

            queryParameters.Add("@invocationData", payload, DbType.String, size: -1);
            queryParameters.Add("@arguments", invocationData.Arguments, DbType.String, size: -1);
            queryParameters.Add("@createdAt", createdAt, DbType.DateTime);
            queryParameters.Add("@expireAt", createdAt.Add(expireIn), DbType.DateTime);

            var parametersArray = parameters.ToArray();

            if (parametersArray.Length <= 4)
            {
                if (parametersArray.Length == 1)
                {
                    queryString = $@"
set xact_abort on; set nocount on; declare @jobId bigint;
begin tran;
insert into [{_storage.SchemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt) values (@invocationData, @arguments, @createdAt, @expireAt);
select @jobId = scope_identity(); select @jobId;
insert into [{_storage.SchemaName}].JobParameter (JobId, Name, Value) values (@jobId, @name, @value);
commit tran;";
                    queryParameters.Add("@name", parametersArray[0].Key, DbType.String, size: 40);
                    queryParameters.Add("@value", parametersArray[0].Value, DbType.String, size: -1);
                }
                else if (parametersArray.Length == 2)
                {
                    queryString = $@"
set xact_abort on; set nocount on; declare @jobId bigint;
begin tran;
insert into [{_storage.SchemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt) values (@invocationData, @arguments, @createdAt, @expireAt);
select @jobId = scope_identity(); select @jobId;
insert into [{_storage.SchemaName}].JobParameter (JobId, Name, Value) values (@jobId, @name1, @value1), (@jobId, @name2, @value2);
commit tran;";
                    queryParameters.Add("@name1", parametersArray[0].Key, DbType.String, size: 40);
                    queryParameters.Add("@value1", parametersArray[0].Value, DbType.String, size: -1);
                    queryParameters.Add("@name2", parametersArray[1].Key, DbType.String, size: 40);
                    queryParameters.Add("@value2", parametersArray[1].Value, DbType.String, size: -1);
                }
                else if (parametersArray.Length == 3)
                {
                    queryString = $@"
set xact_abort on; set nocount on; declare @jobId bigint;
begin tran;
insert into [{_storage.SchemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt) values (@invocationData, @arguments, @createdAt, @expireAt);
select @jobId = scope_identity(); select @jobId;
insert into [{_storage.SchemaName}].JobParameter (JobId, Name, Value) values (@jobId, @name1, @value1), (@jobId, @name2, @value2), (@jobId, @name3, @value3);
commit tran;";
                    queryParameters.Add("@name1", parametersArray[0].Key, DbType.String, size: 40);
                    queryParameters.Add("@value1", parametersArray[0].Value, DbType.String, size: -1);
                    queryParameters.Add("@name2", parametersArray[1].Key, DbType.String, size: 40);
                    queryParameters.Add("@value2", parametersArray[1].Value, DbType.String, size: -1);
                    queryParameters.Add("@name3", parametersArray[2].Key, DbType.String, size: 40);
                    queryParameters.Add("@value3", parametersArray[2].Value, DbType.String, size: -1);
                }
                else if (parametersArray.Length == 4)
                {
                    queryString = $@"
set xact_abort on; set nocount on; declare @jobId bigint;
begin tran;
insert into [{_storage.SchemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt) values (@invocationData, @arguments, @createdAt, @expireAt);
select @jobId = scope_identity(); select @jobId;
insert into [{_storage.SchemaName}].JobParameter (JobId, Name, Value) values (@jobId, @name1, @value1), (@jobId, @name2, @value2), (@jobId, @name3, @value3), (@jobId, @name4, @value4);
commit tran;";
                    queryParameters.Add("@name1", parametersArray[0].Key, DbType.String, size: 40);
                    queryParameters.Add("@value1", parametersArray[0].Value, DbType.String, size: -1);
                    queryParameters.Add("@name2", parametersArray[1].Key, DbType.String, size: 40);
                    queryParameters.Add("@value2", parametersArray[1].Value, DbType.String, size: -1);
                    queryParameters.Add("@name3", parametersArray[2].Key, DbType.String, size: 40);
                    queryParameters.Add("@value3", parametersArray[2].Value, DbType.String, size: -1);
                    queryParameters.Add("@name4", parametersArray[3].Key, DbType.String, size: 40);
                    queryParameters.Add("@value4", parametersArray[3].Value, DbType.String, size: -1);
                }

                return(_storage.UseConnection(_dedicatedConnection, connection => connection
                                              .ExecuteScalar <long>(queryString, queryParameters, commandTimeout: _storage.CommandTimeout)
                                              .ToString()));
            }

            return(_storage.UseTransaction(_dedicatedConnection, (connection, transaction) =>
            {
                var jobId = connection.ExecuteScalar <long>(
                    queryString,
                    queryParameters,
                    transaction,
                    commandTimeout: _storage.CommandTimeout).ToString();

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

                using (var commandBatch = new SqlCommandBatch(connection, transaction, preferBatching: _storage.CommandBatchMaxTimeout.HasValue))
                {
                    commandBatch.CommandTimeout = _storage.CommandTimeout;
                    commandBatch.CommandBatchMaxTimeout = _storage.CommandBatchMaxTimeout;

                    foreach (var parameter in parametersArray)
                    {
                        commandBatch.Append(insertParameterSql,
                                            new SqlCommandBatchParameter("@jobId", DbType.Int64)
                        {
                            Value = long.Parse(jobId)
                        },
                                            new SqlCommandBatchParameter("@name", DbType.String, 40)
                        {
                            Value = parameter.Key
                        },
                                            new SqlCommandBatchParameter("@value", DbType.String, -1)
                        {
                            Value = (object)parameter.Value ?? DBNull.Value
                        });
                    }

                    commandBatch.ExecuteNonQuery();
                }

                return jobId;
            }, null));
        }
예제 #4
0
        public override void SetRangeInHash(string key, IEnumerable <KeyValuePair <string, string> > keyValuePairs)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (keyValuePairs == null)
            {
                throw new ArgumentNullException(nameof(keyValuePairs));
            }

            var sql = $@"
set xact_abort off;
begin try
  insert into [{_storage.SchemaName}].Hash ([Key], Field, Value) values (@key, @field, @value);
  if @@ROWCOUNT = 0 update [{_storage.SchemaName}].Hash set Value = @value where [Key] = @key and Field = @field;
end try
begin catch
  declare @em nvarchar(4000), @es int, @est int;
  select @em=error_message(),@es=error_severity(),@est=error_state();
  IF ERROR_NUMBER() not in (2601, 2627) raiserror(@em, @es, @est);
  update [{_storage.SchemaName}].Hash set Value = @value where [Key] = @key and Field = @field;
end catch";

            var lockResourceKey = $"{_storage.SchemaName}:Hash:Lock";

            _storage.UseTransaction(_dedicatedConnection, (connection, transaction) =>
            {
                using (var commandBatch = new SqlCommandBatch(connection, transaction, preferBatching: _storage.CommandBatchMaxTimeout.HasValue))
                {
                    if (!_storage.Options.DisableGlobalLocks)
                    {
                        commandBatch.Append(
                            "SET XACT_ABORT ON;exec sp_getapplock @Resource=@resource, @LockMode=N'Exclusive', @LockOwner=N'Transaction', @LockTimeout=-1;",
                            new SqlCommandBatchParameter("@resource", DbType.String, 255)
                        {
                            Value = lockResourceKey
                        });
                    }

                    foreach (var keyValuePair in keyValuePairs)
                    {
                        commandBatch.Append(sql,
                                            new SqlCommandBatchParameter("@key", DbType.String)
                        {
                            Value = key
                        },
                                            new SqlCommandBatchParameter("@field", DbType.String, 100)
                        {
                            Value = keyValuePair.Key
                        },
                                            new SqlCommandBatchParameter("@value", DbType.String, -1)
                        {
                            Value = (object)keyValuePair.Value ?? DBNull.Value
                        });
                    }

                    if (!_storage.Options.DisableGlobalLocks)
                    {
                        commandBatch.Append(
                            "exec sp_releaseapplock @Resource=@resource, @LockOwner=N'Transaction';",
                            new SqlCommandBatchParameter("@resource", DbType.String, 255)
                        {
                            Value = lockResourceKey
                        });
                    }

                    commandBatch.CommandTimeout         = _storage.CommandTimeout;
                    commandBatch.CommandBatchMaxTimeout = _storage.CommandBatchMaxTimeout;

                    commandBatch.ExecuteNonQuery();
                }
            });
        }
예제 #5
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;
            }));
        }
예제 #6
0
        public override void SetRangeInHash(string key, IEnumerable <KeyValuePair <string, string> > keyValuePairs)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (keyValuePairs == null)
            {
                throw new ArgumentNullException(nameof(keyValuePairs));
            }

            var sql =
                $@";merge [{_storage.SchemaName}].Hash with (holdlock, forceseek) as Target
using (VALUES (@key, @field, @value)) as Source ([Key], Field, Value)
on Target.[Key] = Source.[Key] and Target.Field = Source.Field
when matched then update set Value = Source.Value
when not matched then insert ([Key], Field, Value) values (Source.[Key], Source.Field, Source.Value);";

            var lockResourceKey = $"{_storage.SchemaName}:Hash:Lock";

            _storage.UseTransaction(_dedicatedConnection, (connection, transaction) =>
            {
                using (var commandBatch = new SqlCommandBatch(connection, transaction, preferBatching: _storage.CommandBatchMaxTimeout.HasValue))
                {
                    if (!_storage.Options.DisableGlobalLocks)
                    {
                        commandBatch.Append(
                            "SET XACT_ABORT ON;exec sp_getapplock @Resource=@resource, @LockMode=N'Exclusive', @LockOwner=N'Transaction', @LockTimeout=-1;",
                            new SqlCommandBatchParameter("@resource", DbType.String, 255)
                        {
                            Value = lockResourceKey
                        });
                    }

                    foreach (var keyValuePair in keyValuePairs)
                    {
                        commandBatch.Append(sql,
                                            new SqlCommandBatchParameter("@key", DbType.String, 100)
                        {
                            Value = key
                        },
                                            new SqlCommandBatchParameter("@field", DbType.String, 100)
                        {
                            Value = keyValuePair.Key
                        },
                                            new SqlCommandBatchParameter("@value", DbType.String, -1)
                        {
                            Value = (object)keyValuePair.Value ?? DBNull.Value
                        });
                    }

                    if (!_storage.Options.DisableGlobalLocks)
                    {
                        commandBatch.Append(
                            "exec sp_releaseapplock @Resource=@resource, @LockOwner=N'Transaction';",
                            new SqlCommandBatchParameter("@resource", DbType.String, 255)
                        {
                            Value = lockResourceKey
                        });
                    }

                    commandBatch.CommandTimeout         = _storage.CommandTimeout;
                    commandBatch.CommandBatchMaxTimeout = _storage.CommandBatchMaxTimeout;

                    commandBatch.ExecuteNonQuery();
                }
            });
        }