예제 #1
0
        public override string CreateExpiredJob(
            Job job,
            IDictionary <string, string> parameters,
            DateTime createdAt,
            TimeSpan expireIn)
        {
            job.ThrowIfNull("job");
            parameters.ThrowIfNull("parameters");

            using (var repository = _storage.Repository.OpenSession()) {
                var invocationData = InvocationData.Serialize(job);

                var guid = Guid.NewGuid().ToString();

                var ravenJob = new RavenJob {
                    Id             = _storage.Repository.GetId(typeof(RavenJob), guid),
                    InvocationData = invocationData,
                    CreatedAt      = createdAt,
                    Parameters     = parameters
                };

                repository.Store(ravenJob);
                repository.Advanced.AddExpire(ravenJob, createdAt + expireIn);

                repository.SaveChanges();

                return(guid);
            }
        }
        private static JobQueue CreateJobQueue(RavenStorage storage, string queue, bool isFetched)
        {
            var jobId = Guid.NewGuid().ToString();

            var job = new RavenJob
            {
                Id        = storage.Repository.GetId(typeof(RavenJob), jobId),
                CreatedAt = DateTime.UtcNow,
                StateData = new StateData()
            };

            var jobQueue = new JobQueue
            {
                Id    = storage.Repository.GetId(typeof(JobQueue), queue, jobId),
                Queue = queue,
                JobId = jobId
            };

            if (isFetched)
            {
                jobQueue.FetchedAt = DateTime.UtcNow.AddDays(-1);
            }

            using (var session = storage.Repository.OpenSession())
            {
                session.Store(job);
                session.Store(jobQueue);
                session.SaveChanges();
            }

            return(jobQueue);
        }
예제 #3
0
        public override StateData GetStateData(string jobId)
        {
            jobId.ThrowIfNull("jobId");

            using (var repository = new Repository()) {
                RavenJob job = repository.Session.Load <RavenJob>(jobId);
                if (job == null)
                {
                    return(null);
                }

                State state = repository.Session.Query <State>().FirstOrDefault(t => t.Id == job.StateId);
                if (state == null)
                {
                    return(null);
                }

                return(new StateData
                {
                    Name = state.Name,
                    Reason = state.Reason,
                    Data = JobHelper.FromJson <Dictionary <string, string> >(state.Data)
                });
            }
        }
예제 #4
0
        public void Dequeue_ShouldFetchJobs_OnlyFromSpecifiedQueues()
        {
            UseStorage(storage =>
            {
                var queue = CreateJobQueue(storage);

                using (var session = storage.Repository.OpenSession())
                {
                    var job1Id = Guid.NewGuid().ToString();
                    var job1   = new RavenJob
                    {
                        Id             = storage.Repository.GetId(typeof(RavenJob), job1Id),
                        InvocationData = null,
                        CreatedAt      = DateTime.UtcNow
                    };
                    session.Store(job1);

                    session.Store(new JobQueue
                    {
                        Id    = storage.Repository.GetId(typeof(JobQueue), "critical", job1Id),
                        JobId = job1Id,
                        Queue = "critical"
                    });
                    session.SaveChanges();
                }

                Assert.Throws <OperationCanceledException>(() => queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken()));
            });
        }
예제 #5
0
        public void Dequeue_ShouldFetchJobs_FromMultipleQueuesBasedOnQueuePriority()
        {
            UseStorage(storage =>
            {
                var queue = CreateJobQueue(storage);

                using (var session = storage.Repository.OpenSession())
                {
                    var criticalJobId = Guid.NewGuid().ToString();
                    var criticalJob   = new RavenJob
                    {
                        Id             = storage.Repository.GetId(typeof(RavenJob), criticalJobId),
                        InvocationData = null,
                        CreatedAt      = DateTime.UtcNow
                    };
                    session.Store(criticalJob);

                    var defaultJobId = Guid.NewGuid().ToString();
                    var defaultJob   = new RavenJob
                    {
                        Id             = storage.Repository.GetId(typeof(RavenJob), defaultJobId),
                        InvocationData = null,
                        CreatedAt      = DateTime.UtcNow
                    };
                    session.Store(defaultJob);

                    session.Store(new JobQueue
                    {
                        Id    = storage.Repository.GetId(typeof(JobQueue), "default", defaultJobId),
                        JobId = defaultJobId,
                        Queue = "default"
                    });

                    session.Store(new JobQueue
                    {
                        Id    = storage.Repository.GetId(typeof(JobQueue), "critical", criticalJobId),
                        JobId = criticalJobId,
                        Queue = "critical"
                    });
                    session.SaveChanges();
                }

                var critical = (RavenFetchedJob)queue.Dequeue(
                    new[] { "critical", "default" },
                    CreateTimingOutCancellationToken());

                Assert.NotNull(critical.JobId);
                Assert.Equal("critical", critical.Queue);

                var @default = (RavenFetchedJob)queue.Dequeue(
                    new[] { "critical", "default" },
                    CreateTimingOutCancellationToken());

                Assert.NotNull(@default.JobId);
                Assert.Equal("default", @default.Queue);
            });
        }
예제 #6
0
        public void Dequeue_ShouldSetFetchedAt_OnlyForTheFetchedJob()
        {
            UseStorage(storage =>
            {
                // Arrange
                var queue = CreateJobQueue(storage);

                using (var session = storage.Repository.OpenSession())
                {
                    var job1Id = Guid.NewGuid().ToString();
                    var job1   = new RavenJob
                    {
                        Id             = storage.Repository.GetId(typeof(RavenJob), job1Id),
                        InvocationData = null,
                        CreatedAt      = DateTime.UtcNow
                    };
                    session.Store(job1);

                    var job2Id = Guid.NewGuid().ToString();
                    var job2   = new RavenJob
                    {
                        Id             = storage.Repository.GetId(typeof(RavenJob), job2Id),
                        InvocationData = null,
                        CreatedAt      = DateTime.UtcNow
                    };
                    session.Store(job2);

                    session.Store(new JobQueue
                    {
                        Id    = storage.Repository.GetId(typeof(JobQueue), "default", job1Id),
                        JobId = job1Id,
                        Queue = "default"
                    });

                    session.Store(new JobQueue
                    {
                        Id    = storage.Repository.GetId(typeof(JobQueue), "default", job2Id),
                        JobId = job2Id,
                        Queue = "default"
                    });
                    session.SaveChanges();
                }

                // Act
                var payload = queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken());

                // Assert
                using (var session = storage.Repository.OpenSession())
                {
                    var otherJobFetchedAt = session.Query <JobQueue>().Where(_ => _.JobId != payload.JobId).FirstOrDefault().FetchedAt;

                    Assert.Null(otherJobFetchedAt);
                }
            });
        }
예제 #7
0
        public void SetJobState_AppendsAStateAndSetItToTheJob()
        {
            UseConnection(repository =>
            {
                var jobId    = Guid.NewGuid().ToString();
                RavenJob job = new RavenJob
                {
                    Id             = repository.GetId(typeof(RavenJob), jobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                var anotherJobId    = Guid.NewGuid().ToString();
                RavenJob anotherJob = new RavenJob
                {
                    Id             = repository.GetId(typeof(RavenJob), anotherJobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                using (var session = repository.OpenSession())
                {
                    session.Store(job);
                    session.Store(anotherJob);
                    session.SaveChanges();
                }

                var serializedData = new Dictionary <string, string> {
                    { "Name", "Value" }
                };

                var state = new Mock <IState>();
                state.Setup(x => x.Name).Returns("State");
                state.Setup(x => x.Reason).Returns("Reason");
                state.Setup(x => x.SerializeData()).Returns(serializedData);

                Commit(repository, x => x.SetJobState(jobId, state.Object));

                using (var session = repository.OpenSession())
                {
                    var testJob = GetTestJob(session, job.Id);
                    Assert.NotNull(testJob.StateData);

                    var anotherTestJob = GetTestJob(session, anotherJob.Id);
                    Assert.Null(anotherTestJob.StateData);

                    var jobState = testJob.StateData;
                    Assert.Equal("State", jobState.Name);
                    Assert.Equal("Reason", jobState.Reason);
                    Assert.Equal(serializedData, jobState.Data);
                }
            });
        }
예제 #8
0
        public void Dequeue_ShouldLeaveJobInTheQueue_ButSetItsFetchedAtValue()
        {
            // Arrange
            UseStorage(storage =>
            {
                var queue = CreateJobQueue(storage);

                var jobId = Guid.NewGuid().ToString();

                var job = new RavenJob
                {
                    Id             = storage.Repository.GetId(typeof(RavenJob), jobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                var jobQueue = new JobQueue
                {
                    Id    = storage.Repository.GetId(typeof(JobQueue), "default", jobId),
                    JobId = jobId,
                    Queue = "default"
                };

                using (var session = storage.Repository.OpenSession())
                {
                    session.Store(job);
                    session.Store(jobQueue);
                    session.SaveChanges();
                }

                // Act
                var payload = queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken());

                // Assert
                Assert.NotNull(payload);

                using (var session = storage.Repository.OpenSession())
                {
                    var fetchedAt = session.Query <JobQueue>().Where(_ => _.JobId == payload.JobId).FirstOrDefault().FetchedAt;

                    Assert.NotNull(fetchedAt);
                    Assert.True(fetchedAt > DateTime.UtcNow.AddMinutes(-1));
                }
            });
        }
        private RavenJob CreateJobInState(IRepository repository, string jobId, string stateName)
        {
            var job = Job.FromExpression(() => SampleMethod("Arguments"));

            var ravenJob = new RavenJob
            {
                Id             = repository.GetId(typeof(RavenJob), jobId),
                InvocationData = InvocationData.Serialize(job),
                CreatedAt      = DateTime.UtcNow,
                StateData      = new StateData
                {
                    Name = stateName,
                    Data =
                        stateName == EnqueuedState.StateName
                            ? new Dictionary <string, string> {
                        ["EnqueuedAt"] = $"{DateTime.UtcNow:o}"
                    }
                            : new Dictionary <string, string>(),
                }
            };

            var jobQueue = new JobQueue
            {
                FetchedAt = null,
                Id        = repository.GetId(typeof(JobQueue), DefaultQueue, jobId),
                JobId     = jobId,
                Queue     = DefaultQueue
            };

            if (stateName == FetchedStateName)
            {
                jobQueue.FetchedAt = DateTime.UtcNow;
            }

            using (var session = repository.OpenSession())
            {
                session.Store(ravenJob);
                session.Store(jobQueue);
                session.SaveChanges();
            }

            return(ravenJob);
        }
예제 #10
0
        public void PersistJob_ClearsTheJobExpirationData()
        {
            UseConnection(repository =>
            {
                var jobId    = Guid.NewGuid().ToString();
                RavenJob job = new RavenJob
                {
                    Id             = repository.GetId(typeof(RavenJob), jobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                var anotherJobId    = Guid.NewGuid().ToString();
                RavenJob anotherJob = new RavenJob
                {
                    Id             = repository.GetId(typeof(RavenJob), anotherJobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                using (var session = repository.OpenSession())
                {
                    session.Store(job);
                    session.Advanced.AddExpire(job, DateTime.UtcNow);
                    session.Store(anotherJob);
                    session.Advanced.AddExpire(anotherJob, DateTime.UtcNow);
                    session.SaveChanges();
                }

                Commit(repository, x => x.PersistJob(jobId.ToString()));

                using (var session = repository.OpenSession())
                {
                    var testJob  = GetTestJob(session, job.Id);
                    var expireAt = session.Advanced.GetExpire(testJob);
                    Assert.Null(expireAt);

                    var anotherTestJob = GetTestJob(session, anotherJob.Id);
                    expireAt           = session.Advanced.GetExpire(anotherTestJob);
                    Assert.NotNull(expireAt);
                }
            });
        }
예제 #11
0
        public void ExpireJob_SetsJobExpirationData()
        {
            UseConnection(repository =>
            {
                var jobId    = Guid.NewGuid().ToString();
                RavenJob job = new RavenJob
                {
                    Id             = repository.GetId(typeof(RavenJob), jobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                var anotherJobId    = Guid.NewGuid().ToString();
                RavenJob anotherJob = new RavenJob
                {
                    Id             = repository.GetId(typeof(RavenJob), anotherJobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                using (var session = repository.OpenSession())
                {
                    session.Store(job);
                    session.Store(anotherJob);
                    session.SaveChanges();
                }

                Commit(repository, x => x.ExpireJob(jobId, TimeSpan.FromDays(1)));

                using (var session = repository.OpenSession())
                {
                    var testJob  = GetTestJob(session, job.Id);
                    var expireAt = session.Advanced.GetExpire(testJob);
                    Assert.True(DateTime.UtcNow.AddMinutes(-1) < expireAt && expireAt <= DateTime.UtcNow.AddDays(1));

                    var anotherTestJob = GetTestJob(session, anotherJob.Id);
                    expireAt           = session.Advanced.GetExpire(anotherTestJob);
                    Assert.Null(expireAt);
                }
            });
        }
예제 #12
0
        public override string CreateExpiredJob(
            Job job,
            IDictionary <string, string> parameters,
            DateTime createdAt,
            TimeSpan expireIn)
        {
            job.ThrowIfNull("job");
            parameters.ThrowIfNull("parameters");

            var invocationData = InvocationData.Serialize(job);

            var ravenJob = new RavenJob
            {
                Id             = Guid.NewGuid().ToString(),
                InvocationData = JobHelper.ToJson(invocationData),
                Arguments      = invocationData.Arguments,
                CreatedAt      = createdAt,
                ExpireAt       = createdAt.Add(expireIn)
            };

            using (var repository = new Repository()) {
                repository.Save(ravenJob);

                if (parameters.Count > 0)
                {
                    foreach (var parameter in parameters)
                    {
                        repository.Save(new JobParameter
                        {
                            JobId = ravenJob.Id,
                            Name  = parameter.Key,
                            Value = parameter.Value
                        });
                    }
                }

                return(ravenJob.Id.ToString());
            }
        }
예제 #13
0
        public void Dequeue_ShouldFetchATimedOutJobs_FromTheSpecifiedQueue()
        {
            // Arrange
            UseStorage(storage =>
            {
                var queue = CreateJobQueue(storage);

                var jobId = Guid.NewGuid().ToString();

                var job = new RavenJob
                {
                    Id             = storage.Repository.GetId(typeof(RavenJob), jobId),
                    InvocationData = null,
                    CreatedAt      = DateTime.UtcNow
                };

                var jobQueue = new JobQueue
                {
                    Id        = storage.Repository.GetId(typeof(JobQueue), "default", jobId),
                    JobId     = jobId,
                    Queue     = "default",
                    FetchedAt = DateTime.UtcNow.AddDays(-1)
                };

                using (var session = storage.Repository.OpenSession())
                {
                    session.Store(job);
                    session.Store(jobQueue);
                    session.SaveChanges();
                }

                // Act
                var payload = queue.Dequeue(DefaultQueues, CreateTimingOutCancellationToken());

                // Assert
                Assert.NotEmpty(payload.JobId);
            });
        }