예제 #1
0
        public PostgreSqlDistributedLock(string resource, TimeSpan timeout, IDbConnection connection,
                                         PostgreSqlStorageOptions options)
        {
            if (string.IsNullOrEmpty(resource))
            {
                throw new ArgumentNullException(nameof(resource));
            }
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _resource   = resource;
            _connection = connection;
            _options    = options;

            if (_options.UseNativeDatabaseTransactions)
            {
                PostgreSqlDistributedLock_Init_Transaction(resource, timeout, connection, options);
            }
            else
            {
                PostgreSqlDistributedLock_Init_UpdateCount(resource, timeout, connection, options);
            }
        }
 public PostgreSqlConnection(
     NpgsqlConnection connection,
     PersistentJobQueueProviderCollection queueProviders,
     PostgreSqlStorageOptions options)
     : this(connection, queueProviders, options, true)
 {
 }
        /// <summary>
        /// Initializes PostgreSqlStorage from the provided PostgreSqlStorageOptions and either the provided connection
        /// string or the connection string with provided name pulled from the application config file.
        /// </summary>
        /// <param name="nameOrConnectionString">Either a SQL Server connection string or the name of
        /// a SQL Server connection string located in the connectionStrings node in the application config</param>
        /// <param name="connectionSetup">Optional setup action to apply to created connections</param>
        /// <param name="options"></param>
        /// <exception cref="ArgumentNullException"><paramref name="nameOrConnectionString"/> argument is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="options"/> argument is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="nameOrConnectionString"/> argument is neither
        /// a valid SQL Server connection string nor the name of a connection string in the application
        /// config file.</exception>
        public PostgreSqlStorage(string nameOrConnectionString, Action <NpgsqlConnection> connectionSetup,
                                 PostgreSqlStorageOptions options)
        {
            if (nameOrConnectionString == null)
            {
                throw new ArgumentNullException(nameof(nameOrConnectionString));
            }

            _options = options ?? throw new ArgumentNullException(nameof(options));

            if (IsConnectionString(nameOrConnectionString))
            {
                _connectionString = nameOrConnectionString;
            }
            else
            {
                throw new ArgumentException(
                          $"Could not find connection string with name '{nameOrConnectionString}' in application config file");
            }

            _connectionSetup = connectionSetup;

            if (options.PrepareSchemaIfNecessary)
            {
                using (var connection = CreateAndOpenConnection())
                {
                    PostgreSqlObjectsInstaller.Install(connection, options.SchemaName);
                }
            }

            InitializeQueueProviders();
        }
예제 #4
0
        public PostgreSqlFetchedJob(
            IDbConnection connection,
            PostgreSqlStorageOptions options,
            int id,
            string jobId,
            string queue)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }
            if (jobId == null)
            {
                throw new ArgumentNullException("jobId");
            }
            if (queue == null)
            {
                throw new ArgumentNullException("queue");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            _connection = connection;
            _options    = options;

            Id    = id;
            JobId = jobId;
            Queue = queue;
        }
		/// <summary>
		/// Initializes PostgreSqlStorage from the provided PostgreSqlStorageOptions and either the provided connection
		/// string or the connection string with provided name pulled from the application config file.       
		/// </summary>
		/// <param name="nameOrConnectionString">Either a SQL Server connection string or the name of 
		/// a SQL Server connection string located in the connectionStrings node in the application config</param>
		/// <param name="options"></param>
		/// <exception cref="ArgumentNullException"><paramref name="nameOrConnectionString"/> argument is null.</exception>
		/// <exception cref="ArgumentNullException"><paramref name="options"/> argument is null.</exception>
		/// <exception cref="ArgumentException"><paramref name="nameOrConnectionString"/> argument is neither 
		/// a valid SQL Server connection string nor the name of a connection string in the application
		/// config file.</exception>
		public PostgreSqlStorage(string nameOrConnectionString, PostgreSqlStorageOptions options)
		{
			if (nameOrConnectionString == null) throw new ArgumentNullException(nameof(nameOrConnectionString));
			if (options == null) throw new ArgumentNullException(nameof(options));

			_options = options;

			if (IsConnectionString(nameOrConnectionString))
			{
				_connectionString = nameOrConnectionString;
			}
			else if (IsConnectionStringInConfiguration(nameOrConnectionString))
			{
				_connectionString = ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString;
			}
			else
			{
				throw new ArgumentException(
					$"Could not find connection string with name '{nameOrConnectionString}' in application config file");
			}

			if (options.PrepareSchemaIfNecessary)
			{
				using (var connection = CreateAndOpenConnection())
				{
					PostgreSqlObjectsInstaller.Install(connection, options.SchemaName);
				}
			}

			InitializeQueueProviders();
		}
 /// <summary>
 ///     Tells the bootstrapper to use PostgreSQL as a job storage
 ///     with the given options, that can be accessed using the specified
 ///     connection string or its name.
 /// </summary>
 /// <param name="configuration">Configuration</param>
 /// <param name="nameOrConnectionString">Connection string or its name</param>
 /// <param name="options">Advanced options</param>
 public static IGlobalConfiguration <PostgreSqlStorage> UsePostgreSqlStorage(
     this IGlobalConfiguration configuration,
     string nameOrConnectionString,
     PostgreSqlStorageOptions options)
 {
     return(configuration.UsePostgreSqlStorage(nameOrConnectionString, null, options));
 }
 public PostgreSqlConnection(
     NpgsqlConnection connection,
     PersistentJobQueueProviderCollection queueProviders,
     PostgreSqlStorageOptions options)
     : this(connection, queueProviders, options, true)
 {
 }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PostgreSqlStorage"/> class with
        /// explicit instance of the <see cref="NpgsqlConnection"/> class that will be used
        /// to query the data.
        /// </summary>
        /// <param name="existingConnection">Existing connection</param>
        /// <param name="options">PostgreSqlStorageOptions</param>
        public PostgreSqlStorage(NpgsqlConnection existingConnection, PostgreSqlStorageOptions options)
        {
            if (existingConnection == null)
            {
                throw new ArgumentNullException(nameof(existingConnection));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            var connectionStringBuilder = new NpgsqlConnectionStringBuilder(existingConnection.ConnectionString);

            if (!options.EnableTransactionScopeEnlistment)
            {
                if (connectionStringBuilder.Enlist)
                {
                    throw new ArgumentException(
                              $"TransactionScope enlistment must be enabled by setting {nameof(PostgreSqlStorageOptions)}.{nameof(options.EnableTransactionScopeEnlistment)} to `true`.");
                }
            }

            _existingConnection = existingConnection;
            _options            = options;

            InitializeQueueProviders();
        }
        private static void PostgreSqlDistributedLock_Init_Transaction(string resource, TimeSpan timeout,
            IDbConnection connection, PostgreSqlStorageOptions options)
        {
            var lockAcquiringTime = Stopwatch.StartNew();

            bool tryAcquireLock = true;

            while (tryAcquireLock)
            {
                TryRemoveDeadlock(resource, connection, options);

                try
                {
                    int rowsAffected = -1;
                    using (var trx = connection.BeginTransaction(IsolationLevel.RepeatableRead))
                    {
                        rowsAffected = connection.Execute($@"
INSERT INTO ""{options.SchemaName}"".""lock""(""resource"", ""acquired"") 
SELECT @resource, @acquired
WHERE NOT EXISTS (
    SELECT 1 FROM ""{options.SchemaName}"".""lock"" 
    WHERE ""resource"" = @resource
);
",
                            new
                            {
                                resource = resource,
                                acquired = DateTime.UtcNow
                            }, trx);
                        trx.Commit();
                    }
                    if (rowsAffected > 0) return;
                }
                catch
                {
                }

                if (lockAcquiringTime.ElapsedMilliseconds > timeout.TotalMilliseconds)
                {
                    tryAcquireLock = false;
                }
                else
                {
                    int sleepDuration = (int)(timeout.TotalMilliseconds - lockAcquiringTime.ElapsedMilliseconds);
                    if (sleepDuration > 1000) sleepDuration = 1000;
                    if (sleepDuration > 0)
                    {
                        Thread.Sleep(sleepDuration);
                    }
                    else
                    {
                        tryAcquireLock = false;
                    }
                }
            }

            throw new PostgreSqlDistributedLockException(
                $"Could not place a lock on the resource \'{resource}\': Lock timeout.");
        }
예제 #10
0
        public JobQueue(IConnectionProvider connectionProvider, PostgreSqlStorageOptions options)
        {
            Guard.ThrowIfNull(connectionProvider, nameof(connectionProvider));
            Guard.ThrowIfNull(options, nameof(options));

            _connectionProvider = connectionProvider;
            _options            = options;
        }
        public PostgreSqlJobQueue(IDbConnection connection, PostgreSqlStorageOptions options)
        {
            if (options == null) throw new ArgumentNullException("options");
            if (connection == null) throw new ArgumentNullException("connection");

            _options = options;
            _connection = connection;
        }
예제 #12
0
 public PostgreSqlJobQueueProvider(PostgreSqlStorageOptions options)
 {
     if (options == null)
     {
         throw new ArgumentNullException("options");
     }
     _options = options;
 }
        public ExpirationManager(PostgreSqlStorage storage,  PostgreSqlStorageOptions options, TimeSpan checkInterval)
        {
            if (storage == null) throw new ArgumentNullException("storage");
            if (options == null) throw new ArgumentNullException("options");

            _options = options;
            _storage = storage;
            _checkInterval = checkInterval;
        }
 public PostgreSqlWriteOnlyTransaction(
     NpgsqlConnection connection,
     PostgreSqlStorageOptions options,
     PersistentJobQueueProviderCollection queueProviders)
 {
     _connection     = connection ?? throw new ArgumentNullException(nameof(connection));
     _options        = options ?? throw new ArgumentNullException(nameof(options));
     _queueProviders = queueProviders ?? throw new ArgumentNullException(nameof(queueProviders));
 }
예제 #15
0
 public PostgreSqlMonitoringApi(
     PostgreSqlStorage storage,
     PostgreSqlStorageOptions options,
     PersistentJobQueueProviderCollection queueProviders)
 {
     _storage        = storage ?? throw new ArgumentNullException(nameof(storage));
     _options        = options ?? throw new ArgumentNullException(nameof(options));
     _queueProviders = queueProviders ?? throw new ArgumentNullException(nameof(queueProviders));
 }
        /// <summary>
        ///     Tells the bootstrapper to use PostgreSQL as a job storage
        ///     with the given options, that can be accessed using the specified
        ///     connection string or its name.
        /// </summary>
        /// <param name="configuration">Configuration</param>
        /// <param name="nameOrConnectionString">Connection string or its name</param>
        /// <param name="options">Advanced options</param>
        public static IGlobalConfiguration <PostgreSqlStorage> UsePostgreSqlStorage(
            this IGlobalConfiguration configuration,
            string nameOrConnectionString,
            PostgreSqlStorageOptions options)
        {
            DapperNodaTimeHelpers.AddDapperNodaTime();

            return(configuration.UsePostgreSqlStorage(nameOrConnectionString, null, options));
        }
예제 #17
0
 public PostgreSqlMonitoringApi(
     string connectionString,
     PostgreSqlStorageOptions options,
     PersistentJobQueueProviderCollection queueProviders)
 {
     _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
     _options          = options ?? throw new ArgumentNullException(nameof(options));
     _queueProviders   = queueProviders ?? throw new ArgumentNullException(nameof(queueProviders));
 }
        /// <summary>
        ///     Tells the bootstrapper to use PostgreSQL as a job storage
        ///     with the given options, that can be accessed using the specified
        ///     connection string or its name.
        /// </summary>
        /// <param name="configuration">Configuration</param>
        /// <param name="nameOrConnectionString">Connection string or its name</param>
        /// <param name="connectionSetup">Optional setup action to apply to created connections</param>
        /// <param name="options">Advanced options</param>
        public static IGlobalConfiguration <PostgreSqlStorage> UsePostgreSqlStorage(
            this IGlobalConfiguration configuration,
            string nameOrConnectionString,
            Action <NpgsqlConnection> connectionSetup,
            PostgreSqlStorageOptions options)
        {
            var storage = new PostgreSqlStorage(nameOrConnectionString, connectionSetup, options);

            return(configuration.UseStorage(storage));
        }
예제 #19
0
        /// <summary>
        /// Tells the bootstrapper to use PostgreSQL as a job storage
        /// with the given options, that can be accessed using the specified
        /// connection string or its name.
        /// </summary>
        /// <param name="configuration">Configuration</param>
        /// <param name="nameOrConnectionString">Connection string or its name</param>
        /// <param name="options">Advanced options</param>
        public static PostgreSqlStorage UsePostgreSqlStorage(
            this IGlobalConfiguration configuration,
            string nameOrConnectionString,
            PostgreSqlStorageOptions options)
        {
            var storage = new PostgreSqlStorage(nameOrConnectionString, options);

            configuration.UseStorage(storage);

            return(storage);
        }
        public StorageConnection(
            IConnectionProvider connectionProvider,
            IJobQueue queue,
            PostgreSqlStorageOptions options)
        {
            Guard.ThrowIfNull(connectionProvider, nameof(connectionProvider));
            Guard.ThrowIfNull(queue, nameof(queue));
            Guard.ThrowIfNull(options, nameof(options));

            _connectionProvider = connectionProvider;
            _queue = queue;
        }
        public void PostgreSqlDistributedLock_Init_Transaction(string resource, TimeSpan timeout, IDbConnection connection, PostgreSqlStorageOptions options)
        {

            Stopwatch lockAcquiringTime = new Stopwatch();
            lockAcquiringTime.Start();

            bool tryAcquireLock = true;

            while (tryAcquireLock)
            {
                try
                {
                    int rowsAffected = -1;
                    using (var trx = _connection.BeginTransaction(IsolationLevel.RepeatableRead))
                    {
                        rowsAffected = _connection.Execute(@"
INSERT INTO """ + _options.SchemaName + @""".""lock""(""resource"") 
SELECT @resource
WHERE NOT EXISTS (
    SELECT 1 FROM """ + _options.SchemaName + @""".""lock"" 
    WHERE ""resource"" = @resource
);
", new
                        {
                            resource = resource
                        }, trx);
                        trx.Commit();
                    }
                    if (rowsAffected > 0) return;
                }
                catch (Exception)
                {
                }

                if (lockAcquiringTime.ElapsedMilliseconds > timeout.TotalMilliseconds)
                    tryAcquireLock = false;
                else
                {
                    int sleepDuration = (int) (timeout.TotalMilliseconds - lockAcquiringTime.ElapsedMilliseconds);
                    if (sleepDuration > 1000) sleepDuration = 1000;
                    if (sleepDuration > 0)
                        Thread.Sleep(sleepDuration);
                    else
                        tryAcquireLock = false;
                }
            }

            throw new PostgreSqlDistributedLockException(
                String.Format(
                "Could not place a lock on the resource '{0}': {1}.",
                _resource,
                "Lock timeout"));
        }
예제 #22
0
        public PostgreSqlFetchedJob(
            PostgreSqlStorage storage,
            PostgreSqlStorageOptions options,
            long id,
            string jobId,
            string queue)
        {
            _storage = storage ?? throw new ArgumentNullException(nameof(storage));
            _options = options ?? throw new ArgumentNullException(nameof(options));

            Id    = id;
            JobId = jobId ?? throw new ArgumentNullException(nameof(jobId));
            Queue = queue ?? throw new ArgumentNullException(nameof(queue));
        }
        public PostgreSqlWriteOnlyTransaction(
            NpgsqlConnection connection,
            PostgreSqlStorageOptions options,
            PersistentJobQueueProviderCollection queueProviders)
        {
            if (connection == null) throw new ArgumentNullException("connection");
            if (queueProviders == null) throw new ArgumentNullException("queueProviders");
            if (options == null) throw new ArgumentNullException("options");

            _connection = connection;
;
            _options = options;
            _queueProviders = queueProviders;
        }
예제 #24
0
        public PostgreSqlJobQueueMonitoringApi(IDbConnection connection, PostgreSqlStorageOptions options)
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _connection = connection;
            _options    = options;
        }
        public PostgreSqlMonitoringApi(
            string connectionString,
            PostgreSqlStorageOptions options,
            PersistentJobQueueProviderCollection queueProviders)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            _connectionString = connectionString;
            _queueProviders   = queueProviders;
            _options          = options;
        }
예제 #26
0
        public PostgreSqlJobQueue(IDbConnection connection, PostgreSqlStorageOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            _options    = options;
            _connection = connection;
        }
        public PostgreSqlConnection(
            NpgsqlConnection connection, 
            PersistentJobQueueProviderCollection queueProviders,
            PostgreSqlStorageOptions options,
            bool ownsConnection)
        {
            if (connection == null) throw new ArgumentNullException("connection");
            if (queueProviders == null) throw new ArgumentNullException("queueProviders");
            if (options == null) throw new ArgumentNullException("options");

            _connection = connection;
            _queueProviders = queueProviders;
            _options = options;
            OwnsConnection = ownsConnection;
        }
예제 #28
0
        public ExpirationManager(PostgreSqlStorage storage, PostgreSqlStorageOptions options, TimeSpan checkInterval)
        {
            if (storage == null)
            {
                throw new ArgumentNullException("storage");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            _options       = options;
            _storage       = storage;
            _checkInterval = checkInterval;
        }
        public PostgreSqlDistributedLock(string resource, TimeSpan timeout, IDbConnection connection,
            PostgreSqlStorageOptions options)
        {
            if (string.IsNullOrEmpty(resource)) throw new ArgumentNullException(nameof(resource));
            if (connection == null) throw new ArgumentNullException(nameof(connection));
            if (options == null) throw new ArgumentNullException(nameof(options));

            _resource = resource;
            _connection = connection;
            _options = options;

            if (_options.UseNativeDatabaseTransactions)
                PostgreSqlDistributedLock_Init_Transaction(resource, timeout, connection, options);
            else
                PostgreSqlDistributedLock_Init_UpdateCount(resource, timeout, connection, options);
        }
        public PostgreSqlStorage(NpgsqlConnection existingConnection)
        {
            if (existingConnection == null)
            {
                throw new ArgumentNullException(nameof(existingConnection));
            }
            var connectionStringBuilder = new NpgsqlConnectionStringBuilder(existingConnection.ConnectionString);

            if (connectionStringBuilder.Enlist)
            {
                throw new ArgumentException(
                          "Npgsql is not fully compatible with TransactionScope yet, only connections without Enlist = true are accepted.");
            }

            _existingConnection = existingConnection;
            _options            = new PostgreSqlStorageOptions();

            InitializeQueueProviders();
        }
        public PostgreSqlFetchedJob(
            IDbConnection connection, 
            PostgreSqlStorageOptions options,
            int id, 
            string jobId, 
            string queue)
        {
            if (connection == null) throw new ArgumentNullException("connection");
            if (jobId == null) throw new ArgumentNullException("jobId");
            if (queue == null) throw new ArgumentNullException("queue");
            if (options == null) throw new ArgumentNullException("options");

            _connection = connection;
            _options = options;

            Id = id;
            JobId = jobId;
            Queue = queue;
        }
예제 #32
0
        /// <summary>
        /// Initializes PostgreSqlStorage with the provided connection string and the provided PostgreSqlStorageOptions.
        /// </summary>
        /// <param name="connectionString">A Postgres connection string</param>
        /// <param name="options"></param>
        /// <exception cref="ArgumentNullException"><paramref name="connectionString"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="options"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="connectionString"/> is not valid PostgreSql connection string.</exception>
        public PostgreSqlStorage(string connectionString, PostgreSqlStorageOptions options)
        {
            Guard.ThrowIfNull(connectionString, nameof(connectionString));
            Guard.ThrowIfNull(options, nameof(options));
            Guard.ThrowIfConnectionStringIsInvalid(connectionString);

            _options = options;

            var builder = new NpgsqlConnectionStringBuilder(connectionString);

            _connectionProvider = CreateConnectionProvider(connectionString, builder);

            var queue = new JobQueue(_connectionProvider, _options);

            _storageConnection = new StorageConnection(_connectionProvider, queue, _options);
            _monitoringApi     = new MonitoringApi(_connectionProvider);
            _storageInfo       = $"PostgreSQL Server: Host: {builder.Host}, DB: {builder.Database}, Schema: {builder.SearchPath}, Pool: {_connectionProvider.GetType().Name}";

            PrepareSchemaIfNecessary(builder.SearchPath);
        }
        /// <summary>
        /// Initializes PostgreSqlStorage from the provided PostgreSqlStorageOptions and either the provided connection
        /// string or the connection string with provided name pulled from the application config file.
        /// </summary>
        /// <param name="nameOrConnectionString">Either a SQL Server connection string or the name of
        /// a SQL Server connection string located in the connectionStrings node in the application config</param>
        /// <param name="options"></param>
        /// <exception cref="ArgumentNullException"><paramref name="nameOrConnectionString"/> argument is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="options"/> argument is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="nameOrConnectionString"/> argument is neither
        /// a valid SQL Server connection string nor the name of a connection string in the application
        /// config file.</exception>
        public PostgreSqlStorage(string nameOrConnectionString, PostgreSqlStorageOptions options)
        {
            if (nameOrConnectionString == null)
            {
                throw new ArgumentNullException(nameof(nameOrConnectionString));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _options = options;

            if (IsConnectionString(nameOrConnectionString))
            {
                _connectionString = nameOrConnectionString;
            }
#if (NETSTANDARD2_0)
#else
            else if (IsConnectionStringInConfiguration(nameOrConnectionString))
            {
                _connectionString = ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString;
            }
#endif
            else
            {
                throw new ArgumentException(
                          $"Could not find connection string with name '{nameOrConnectionString}' in application config file");
            }

            if (options.PrepareSchemaIfNecessary)
            {
                using (var connection = CreateAndOpenConnection())
                {
                    PostgreSqlObjectsInstaller.Install(connection, options.SchemaName);
                }
            }

            InitializeQueueProviders();
        }
예제 #34
0
        /// <summary>
        /// Initializes PostgreSqlStorage from the provided PostgreSqlStorageOptions and either the provided connection
        /// string or the connection string with provided name pulled from the application config file.
        /// </summary>
        /// <param name="nameOrConnectionString">Either a SQL Server connection string or the name of
        /// a SQL Server connection string located in the connectionStrings node in the application config</param>
        /// <param name="options"></param>
        /// <exception cref="ArgumentNullException"><paramref name="nameOrConnectionString"/> argument is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="options"/> argument is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="nameOrConnectionString"/> argument is neither
        /// a valid SQL Server connection string nor the name of a connection string in the application
        /// config file.</exception>
        public PostgreSqlStorage(string nameOrConnectionString, PostgreSqlStorageOptions options)
        {
            if (nameOrConnectionString == null)
            {
                throw new ArgumentNullException("nameOrConnectionString");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            _options = options;

            if (IsConnectionString(nameOrConnectionString))
            {
                _connectionString = nameOrConnectionString;
            }
            else if (IsConnectionStringInConfiguration(nameOrConnectionString))
            {
                _connectionString = ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString;
            }
            else
            {
                throw new ArgumentException(
                          string.Format("Could not find connection string with name '{0}' in application config file",
                                        nameOrConnectionString));
            }

            if (options.PrepareSchemaIfNecessary)
            {
                using (var connection = CreateAndOpenConnection())
                {
                    PostgreSqlObjectsInstaller.Install(connection);
                }
            }

            var defaultQueueProvider = new PostgreSqlJobQueueProvider(options);

            QueueProviders = new PersistentJobQueueProviderCollection(defaultQueueProvider);
        }
예제 #35
0
        public PostgreSqlWriteOnlyTransaction(
            NpgsqlConnection connection,
            PostgreSqlStorageOptions options,
            PersistentJobQueueProviderCollection queueProviders)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }
            if (queueProviders == null)
            {
                throw new ArgumentNullException("queueProviders");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            _connection = connection;
            ;
            _options        = options;
            _queueProviders = queueProviders;
        }
        public PostgreSqlConnection(
            NpgsqlConnection connection,
            PersistentJobQueueProviderCollection queueProviders,
            PostgreSqlStorageOptions options,
            bool ownsConnection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }
            if (queueProviders == null)
            {
                throw new ArgumentNullException(nameof(queueProviders));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _connection     = connection;
            _queueProviders = queueProviders;
            _options        = options;
            OwnsConnection  = ownsConnection;
        }
예제 #37
0
        private static void PostgreSqlDistributedLock_Init_Transaction(string resource, TimeSpan timeout,
                                                                       IDbConnection connection, PostgreSqlStorageOptions options)
        {
            var lockAcquiringTime = Stopwatch.StartNew();

            bool tryAcquireLock = true;

            while (tryAcquireLock)
            {
                TryRemoveDeadlock(resource, connection, options);

                try
                {
                    int rowsAffected = -1;
                    using (var trx = connection.BeginTransaction(IsolationLevel.RepeatableRead))
                    {
                        rowsAffected = connection.Execute($@"
INSERT INTO ""{options.SchemaName}"".""lock""(""resource"", ""acquired"") 
SELECT @resource, @acquired
WHERE NOT EXISTS (
    SELECT 1 FROM ""{options.SchemaName}"".""lock"" 
    WHERE ""resource"" = @resource
);
",
                                                          new
                        {
                            resource = resource,
                            acquired = DateTime.UtcNow
                        }, trx);
                        trx.Commit();
                    }
                    if (rowsAffected > 0)
                    {
                        return;
                    }
                }
                catch
                {
                }

                if (lockAcquiringTime.ElapsedMilliseconds > timeout.TotalMilliseconds)
                {
                    tryAcquireLock = false;
                }
                else
                {
                    int sleepDuration = (int)(timeout.TotalMilliseconds - lockAcquiringTime.ElapsedMilliseconds);
                    if (sleepDuration > 1000)
                    {
                        sleepDuration = 1000;
                    }
                    if (sleepDuration > 0)
                    {
                        Thread.Sleep(sleepDuration);
                    }
                    else
                    {
                        tryAcquireLock = false;
                    }
                }
            }

            throw new PostgreSqlDistributedLockException(
                      $"Could not place a lock on the resource \'{resource}\': Lock timeout.");
        }
 public PostgreSqlJobQueueProvider(PostgreSqlStorageOptions options)
 {
     if (options == null) throw new ArgumentNullException("options");
     _options = options;
 }
예제 #39
0
        private static void PostgreSqlDistributedLock_Init_UpdateCount(string resource, TimeSpan timeout, IDbConnection connection, PostgreSqlStorageOptions options)
        {
            var lockAcquiringTime = Stopwatch.StartNew();

            bool tryAcquireLock = true;

            while (tryAcquireLock)
            {
                try
                {
                    connection.Execute($@"
INSERT INTO ""{options.SchemaName}"".""lock""(""resource"", ""updatecount"", ""acquired"") 
SELECT @resource, 0, @acquired
WHERE NOT EXISTS (
    SELECT 1 FROM ""{options.SchemaName}"".""lock"" 
    WHERE ""resource"" = @resource
);
", new
                    {
                        resource = resource,
                        acquired = DateTime.UtcNow
                    });
                }
                catch (Exception)
                {
                }

                int rowsAffected = connection.Execute($@"UPDATE ""{options.SchemaName}"".""lock"" SET ""updatecount"" = 1 WHERE ""updatecount"" = 0");

                if (rowsAffected > 0)
                {
                    return;
                }

                if (lockAcquiringTime.ElapsedMilliseconds > timeout.TotalMilliseconds)
                {
                    tryAcquireLock = false;
                }
                else
                {
                    int sleepDuration = (int)(timeout.TotalMilliseconds - lockAcquiringTime.ElapsedMilliseconds);
                    if (sleepDuration > 1000)
                    {
                        sleepDuration = 1000;
                    }
                    if (sleepDuration > 0)
                    {
                        Thread.Sleep(sleepDuration);
                    }
                    else
                    {
                        tryAcquireLock = false;
                    }
                }
            }

            throw new PostgreSqlDistributedLockException(
                      $"Could not place a lock on the resource '{resource}': Lock timeout.");
        }
예제 #40
0
        private static void TryRemoveDeadlock(string resource, IDbConnection connection, PostgreSqlStorageOptions options)
        {
            try
            {
                using (var transaction = connection.BeginTransaction(IsolationLevel.RepeatableRead))
                {
                    int affected = -1;

                    affected = connection.Execute($@"DELETE FROM ""{options.SchemaName}"".""lock"" WHERE ""resource"" = @resource AND ""acquired"" < @timeout",
                                                  new
                    {
                        resource = resource,
                        timeout  = DateTime.UtcNow - options.DistributedLockTimeout
                    });

                    transaction.Commit();
                }
            }
            catch
            {
            }
        }
        public void PostgreSqlDistributedLock_Init_UpdateCount(string resource, TimeSpan timeout, IDbConnection connection, PostgreSqlStorageOptions options)
        {

            Stopwatch lockAcquiringTime = new Stopwatch();
            lockAcquiringTime.Start();

            bool tryAcquireLock = true;

            while (tryAcquireLock)
            {
                try
                {
                    _connection.Execute(@"
INSERT INTO """ + _options.SchemaName + @""".""lock""(""resource"", ""updatecount"") 
SELECT @resource, 0
WHERE NOT EXISTS (
    SELECT 1 FROM """ + _options.SchemaName + @""".""lock"" 
    WHERE ""resource"" = @resource
);
", new
 {
     resource = resource
 });
                }
                catch (Exception)
                {
                }

                int rowsAffected = _connection.Execute(@"UPDATE """ + _options.SchemaName + @""".""lock"" SET ""updatecount"" = 1 WHERE ""updatecount"" = 0");

                if (rowsAffected > 0) return;

                if (lockAcquiringTime.ElapsedMilliseconds > timeout.TotalMilliseconds)
                    tryAcquireLock = false;
                else
                {
                    int sleepDuration = (int)(timeout.TotalMilliseconds - lockAcquiringTime.ElapsedMilliseconds);
                    if (sleepDuration > 1000) sleepDuration = 1000;
                    if (sleepDuration > 0)
                        Thread.Sleep(sleepDuration);
                    else
                        tryAcquireLock = false;
                }
            }

            throw new PostgreSqlDistributedLockException(
                String.Format(
                "Could not place a lock on the resource '{0}': {1}.",
                _resource,
                "Lock timeout"));
        }
        private static void TryRemoveDeadlock(string resource, IDbConnection connection, PostgreSqlStorageOptions options)
        {
            try
            {
                using (var transaction = connection.BeginTransaction(IsolationLevel.RepeatableRead))
                {
                    int affected = -1;

                    affected = connection.Execute($@"DELETE FROM ""{options.SchemaName}"".""lock"" WHERE ""resource"" = @resource AND ""acquired"" < @timeout",
                        new
                        {
                            resource = resource,
                            timeout = DateTime.UtcNow - options.DistributedLockTimeout
                        });

                    transaction.Commit();
                }
            }
            catch
            {
            }
        }
예제 #43
0
 public ExpirationManager(PostgreSqlStorage storage, PostgreSqlStorageOptions options)
     : this(storage, options, TimeSpan.FromHours(1))
 {
 }
        private static void PostgreSqlDistributedLock_Init_UpdateCount(string resource, TimeSpan timeout, IDbConnection connection, PostgreSqlStorageOptions options)
        {
            var lockAcquiringTime = Stopwatch.StartNew();

            bool tryAcquireLock = true;

            while (tryAcquireLock)
            {
                try
                {
                    connection.Execute($@"
INSERT INTO ""{options.SchemaName}"".""lock""(""resource"", ""updatecount"", ""acquired"") 
SELECT @resource, 0, @acquired
WHERE NOT EXISTS (
    SELECT 1 FROM ""{options.SchemaName}"".""lock"" 
    WHERE ""resource"" = @resource
);
", new
                    {
                        resource = resource,
                        acquired = DateTime.UtcNow
                    });
                }
                catch (Exception)
                {
                }

                int rowsAffected = connection.Execute($@"UPDATE ""{options.SchemaName}"".""lock"" SET ""updatecount"" = 1 WHERE ""updatecount"" = 0");

                if (rowsAffected > 0) return;

                if (lockAcquiringTime.ElapsedMilliseconds > timeout.TotalMilliseconds)
                    tryAcquireLock = false;
                else
                {
                    int sleepDuration = (int)(timeout.TotalMilliseconds - lockAcquiringTime.ElapsedMilliseconds);
                    if (sleepDuration > 1000) sleepDuration = 1000;
                    if (sleepDuration > 0)
                        Thread.Sleep(sleepDuration);
                    else
                        tryAcquireLock = false;
                }
            }

            throw new PostgreSqlDistributedLockException(
                $"Could not place a lock on the resource '{resource}': Lock timeout.");
        }
 public ExpirationManager(PostgreSqlStorage storage, PostgreSqlStorageOptions options)
     : this(storage, options, TimeSpan.FromHours(1))
 {
 }
		/// <summary>
		/// Initializes a new instance of the <see cref="PostgreSqlStorage"/> class with
		/// explicit instance of the <see cref="NpgsqlConnection"/> class that will be used
		/// to query the data.
		/// </summary>
		/// <param name="existingConnection">Existing connection</param>
		/// <param name="options">PostgreSqlStorageOptions</param>
		public PostgreSqlStorage(NpgsqlConnection existingConnection, PostgreSqlStorageOptions options)
		{
			if (existingConnection == null) throw new ArgumentNullException(nameof(existingConnection));
			if (options == null) throw new ArgumentNullException(nameof(options));
			var connectionStringBuilder = new NpgsqlConnectionStringBuilder(existingConnection.ConnectionString);
			if (connectionStringBuilder.Enlist)
				throw new ArgumentException(
					"Npgsql is not fully compatible with TransactionScope yet, only connections without Enlist = true are accepted.");

			_existingConnection = existingConnection;
			_options = options;

			InitializeQueueProviders();
		}