public async Task <IQueuedTask> PeekAsync()
        {
            IQueuedTask    peekedTask = null;
            DateTimeOffset refNow     = mTimestampProvider.GetNow();

            CheckNotDisposedOrThrow();

            //This simply returns the latest item on top of the queue,
            //  without acquiring any lock

            string peekSql = $@"SELECT q.*
				FROM {mOptions.Mapping.QueueTableName} as q
				WHERE q.task_locked_until_ts < @t_now 
				ORDER BY q.task_priority ASC,
					q.task_locked_until_ts ASC,
					q.task_lock_handle_id ASC
				LIMIT 1"                ;

            using (NpgsqlConnection conn = await OpenConnectionAsync())
                using (NpgsqlCommand peekCmd = new NpgsqlCommand(peekSql, conn))
                {
                    peekCmd.Parameters.AddWithValue("t_now",
                                                    NpgsqlDbType.TimestampTz,
                                                    refNow);

                    await peekCmd.PrepareAsync();

                    using (NpgsqlDataReader taskReader = await peekCmd.ExecuteReaderAsync())
                    {
                        if (await taskReader.ReadAsync())
                        {
                            peekedTask = await taskReader.ReadQueuedTaskAsync();
                        }

                        await taskReader.CloseAsync();
                    }

                    await conn.CloseAsync();
                }

            return(peekedTask);
        }
Ejemplo n.º 2
0
 private DateTimeOffset GenerateImmediatePastLockedTimestamp()
 {
     return(mTimestampProvider
            .GetNow()
            .AddSeconds(-ImmediatePastSecondsInterval));
 }
        public async Task <IQueuedTaskToken> DequeueAsync(params string[] selectTaskTypes)
        {
            NpgsqlConnection          conn               = null;
            QueuedTask                dequeuedTask       = null;
            QueuedTaskResult          dequeuedTaskResult = null;
            PostgreSqlQueuedTaskToken dequeuedTaskToken  = null;

            MonotonicTimestamp startDequeue;
            DateTimeOffset     refNow = mTimestampProvider.GetNow();

            CheckNotDisposedOrThrow();

            try
            {
                mLogger.DebugFormat("Begin dequeue task. Looking for types: {0}.",
                                    string.Join <string>(",", selectTaskTypes));

                startDequeue = MonotonicTimestamp
                               .Now();

                conn = await OpenQueueConnectionAsync();

                if (conn == null)
                {
                    return(null);
                }

                using (NpgsqlTransaction tx = conn.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    //1. Dequeue means that we acquire lock on a task in the queue
                    //	with the guarantee that nobody else did, and respecting
                    //	the priority and static locks (basically the task_locked_until which says
                    //	that it should not be pulled out of the queue until the
                    //	current abstract time reaches that tick value)
                    dequeuedTask = await TryDequeueTaskAsync(selectTaskTypes, refNow, conn, tx);

                    if (dequeuedTask != null)
                    {
                        //2. Mark the task as being "Processing" and pull result info
                        //	The result is stored separately and it's what allows us to remove
                        //	the task from the queue at step #2,
                        //	whils also tracking it's processing status and previous results
                        dequeuedTaskResult = await TryUpdateTaskResultAsync(dequeuedTask, conn, tx);

                        if (dequeuedTaskResult != null)
                        {
                            await tx.CommitAsync();

                            dequeuedTaskToken = new PostgreSqlQueuedTaskToken(dequeuedTask,
                                                                              dequeuedTaskResult,
                                                                              refNow);
                        }
                    }

                    if (dequeuedTaskToken != null)
                    {
                        IncrementDequeueCount(MonotonicTimestamp.Since(startDequeue));
                    }
                    else
                    {
                        await tx.RollbackAsync();
                    }
                }
            }
            finally
            {
                if (conn != null)
                {
                    await conn.CloseAsync();

                    conn.Dispose();
                }
            }

            return(dequeuedTaskToken);
        }