public void Dispose()
        {
            if (_disposed)
            {
                return;
            }

            if (!_removedFromQueue && !_requeued)
            {
                Requeue();
            }

            _storage.ReleaseConnection(_connection);

            _disposed = true;
        }
        public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken)
        {
            if (queues == null)
            {
                throw new ArgumentNullException(nameof(queues));
            }
            if (queues.Length == 0)
            {
                throw new ArgumentException("Queue array must be non-empty.", nameof(queues));
            }

            FetchedJob    fetchedJob = null;
            IDbConnection connection;

            do
            {
                cancellationToken.ThrowIfCancellationRequested();
                connection = _storage.CreateAndOpenConnection();

                try
                {
                    using (new OracleDistributedLock(_storage, "JobQueue", TimeSpan.FromSeconds(30)))
                    {
                        var token = Guid.NewGuid().ToString();

                        var nUpdated = connection.Execute(@"
UPDATE HF_JOB_QUEUE
   SET FETCHED_AT = SYS_EXTRACT_UTC (SYSTIMESTAMP), FETCH_TOKEN = :FETCH_TOKEN
 WHERE (FETCHED_AT IS NULL OR FETCHED_AT < SYS_EXTRACT_UTC (SYSTIMESTAMP) + numToDSInterval(:TIMEOUT, 'second' )) AND (QUEUE IN :QUEUES) AND ROWNUM = 1
",
                                                          new
                        {
                            QUEUES      = queues,
                            TIMEOUT     = _options.InvisibilityTimeout.Negate().TotalSeconds,
                            FETCH_TOKEN = token
                        });

                        if (nUpdated != 0)
                        {
                            fetchedJob =
                                connection
                                .QuerySingle <FetchedJob>(
                                    @"
 SELECT ID as Id, JOB_ID as JobId, QUEUE as Queue
   FROM HF_JOB_QUEUE
  WHERE FETCH_TOKEN = :FETCH_TOKEN
",
                                    new
                            {
                                FETCH_TOKEN = token
                            });
                        }
                    }
                }
                catch (DbException ex)
                {
                    Logger.ErrorException(ex.Message, ex);
                    _storage.ReleaseConnection(connection);
                    throw;
                }

                if (fetchedJob == null)
                {
                    _storage.ReleaseConnection(connection);

                    cancellationToken.WaitHandle.WaitOne(_options.QueuePollInterval);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            } while (fetchedJob == null);

            return(new OracleFetchedJob(_storage, connection, fetchedJob));
        }
        public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken)
        {
            if (queues == null)
            {
                throw new ArgumentNullException("queues");
            }
            if (queues.Length == 0)
            {
                throw new ArgumentException("Queue array must be non-empty.", "queues");
            }

            FetchedJob       fetchedJob = null;
            OracleConnection connection = null;

            do
            {
                cancellationToken.ThrowIfCancellationRequested();
                connection = _storage.CreateAndOpenConnection();

                try
                {
                    using (new OracleDistributedLock(_storage, "JobQueue", TimeSpan.FromSeconds(30)))
                    {
                        string token = Guid.NewGuid().ToString();

                        var timeout  = _options.InvisibilityTimeout.Negate().TotalSeconds;
                        int nUpdated = connection.Execute(
                            $@" update HANGFIRE_JOBQUEUE set FetchedAt = sysdate, FetchToken = :fetchToken
where(FetchedAt is null or FetchedAt < (sysdate + INTERVAL '{timeout}' SECOND))
and Queue in :queues
and rownum = 1",
                            new
                        {
                            queues     = queues,
                            fetchToken = token
                        });

                        if (nUpdated != 0)
                        {
                            fetchedJob =
                                connection
                                .Query <FetchedJob>(
                                    "select Id, JobId, Queue from HANGFIRE_JOBQUEUE where FetchToken = :fetchToken",
                                    new
                            {
                                fetchToken = token
                            })
                                .SingleOrDefault();
                        }
                    }
                }
                catch (OracleException ex)
                {
                    Logger.ErrorException(ex.Message, ex);
                    _storage.ReleaseConnection(connection);
                    throw;
                }

                if (fetchedJob == null)
                {
                    _storage.ReleaseConnection(connection);

                    cancellationToken.WaitHandle.WaitOne(_options.QueuePollInterval);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            } while (fetchedJob == null);

            return(new OracleFetchedJob(_storage, connection, fetchedJob));
        }