internal MySqlDistributedLock Acquire()
		{
			Logger.TraceFormat("Acquire resource={0}, timeout={1}", _resource, _timeout);

			int insertedObjectCount;
			do
			{
				_cancellationToken.ThrowIfCancellationRequested();

				var timeLeft = _start.Add(_timeout).Subtract(DateTime.UtcNow);
				using (ResourceLock.AcquireOne(
					_connection, _storageOptions.TablesPrefix, 
					timeLeft, _cancellationToken,
					LockableResource.Lock))
				{
					insertedObjectCount = AcquireLock();
				}

				if (ContinueCondition(insertedObjectCount))
				{
					_cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses);
					_cancellationToken.ThrowIfCancellationRequested();
				}
			}
			while (ContinueCondition(insertedObjectCount));

			if (insertedObjectCount == 0)
			{
				throw new MySqlDistributedLockException("cannot acquire lock");
			}

			return this;
		}
 private int AggregateCounter(MySqlConnection connection)
 {
     using (ResourceLock.AcquireOne(
                connection, _options.TablesPrefix, LockableResource.Counter))
     {
         return(connection.Execute(
                    GetAggregationQuery(),
                    new { now = DateTime.UtcNow, count = NumberOfRecordsInSinglePass }));
     }
 }
Example #3
0
        public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken)
        {
            if (queues is null || !queues.Any())
            {
                throw new ArgumentException("Queue array must be non-empty.", nameof(queues));
            }

            var token = Guid.NewGuid().ToString();
            // I'm not sure if this is used correctly...
            var expiration = _options.InvisibilityTimeout;
            // the connection variable is mutable, it job is claimed then this connection
            // is passed to job itself, and variable is set to null so it does not get
            // disposed here in such case
            var connection = _storage.CreateAndOpenConnection();

            try
            {
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    using (ResourceLock.AcquireOne(
                               connection, _options.TablesPrefix, LockableResource.Queue))
                    {
                        var updated = ClaimJob(connection, queues, expiration, token);

                        if (updated != 0)
                        {
                            var fetchedJob = FetchJobByToken(connection, token);
                            return(new MySqlFetchedJob(
                                       _storage, _options,
                                       Interlocked.Exchange(ref connection, null),
                                       fetchedJob));
                        }
                    }

                    cancellationToken.WaitHandle.WaitOne(_options.QueuePollInterval);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            }
            catch (MySqlException ex)
            {
                Logger.ErrorException(ex.Message, ex);
                throw;
            }
            finally
            {
                if (connection != null)
                {
                    _storage.ReleaseConnection(connection);
                }
            }
        }
Example #4
0
        public void Requeue()
        {
            Logger.TraceFormat("Requeue JobId={0}", JobId);

            using (ResourceLock.AcquireOne(
                       _connection, _options.TablesPrefix, LockableResource.Queue))
            {
                _connection.Execute(
                    $"update `{_options.TablesPrefix}JobQueue` set FetchedAt = null where Id = @id",
                    new { id = _id });
            }

            _requeued = true;
        }
Example #5
0
        public void RemoveFromQueue()
        {
            Logger.TraceFormat("RemoveFromQueue JobId={0}", JobId);

            using (ResourceLock.AcquireOne(
                       _connection, _options.TablesPrefix, LockableResource.Queue))
            {
                _connection.Execute(
                    $"delete from `{_options.TablesPrefix}JobQueue` where Id = @id",
                    new { id = _id });
            }

            _removed = true;
        }
		internal void Release()
		{
			Logger.TraceFormat("Release resource={0}", _resource);

			using (ResourceLock.AcquireOne(
				_connection, _storageOptions.TablesPrefix, 
				_timeout, CancellationToken.None,
				LockableResource.Lock))
			{
				_connection.Execute(
					$"DELETE FROM `{_storageOptions.TablesPrefix}DistributedLock`  " +
					"WHERE Resource = @resource",
					new { resource = _resource });
			}
		}
Example #7
0
        private void Enqueue(
            IDbConnection connection, IDbTransaction transaction, string queue, string jobId)
        {
            Logger.TraceFormat("Enqueue JobId={0} Queue={1}", jobId, queue);

            using (ResourceLock.AcquireOne(
                       connection, transaction, _options.TablesPrefix, LockableResource.Queue))
            {
                connection.Execute(
                    $@"/* MySqlJobQueue.Enqueue */
                    insert into `{_options.TablesPrefix}JobQueue` (JobId, Queue)
                    values (@jobId, @queue)",
                    new { jobId, queue },
                    transaction);
            }
        }
        public static void Upgrade(MySqlConnection connection, string tablesPrefix = null)
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }

            var prefix = tablesPrefix ?? string.Empty;

            using (ResourceLock.AcquireOne(
                       connection, prefix,
                       MigrationTimeout, CancellationToken.None,
                       LockableResource.Migration))
            {
                var resourceName = $"{typeof(MySqlObjectsInstaller).Namespace}.Migrations.xml";
                var document     = XElement.Parse(GetStringResource(resourceName));

                EnsureMigrationsTable(connection, prefix);

                var migrations = document
                                 .Elements("migration")
                                 .Select(e => new { id = e.Attribute("id")?.Value, script = e.Value })
                                 .ToArray();

                foreach (var migration in migrations)
                {
                    var alreadyApplied = IsMigrationApplied(connection, prefix, migration.id);
                    if (alreadyApplied)
                    {
                        continue;
                    }

                    ApplyMigration(connection, migration.script, prefix, migration.id);
                }
            }
        }