diff --git a/rq/job.py b/rq/job.py index fa85b9d..9f0b07e 100644 --- a/rq/job.py +++ b/rq/job.py @@ -306,6 +306,7 @@ class Job(object): self.description = None self.origin = None self.enqueued_at = None + self.started_at = None self.ended_at = None self._result = None self.exc_info = None @@ -410,6 +411,7 @@ class Job(object): self.origin = as_text(obj.get('origin')) self.description = as_text(obj.get('description')) self.enqueued_at = to_date(as_text(obj.get('enqueued_at'))) + self.started_at = to_date(as_text(obj.get('started_at'))) self.ended_at = to_date(as_text(obj.get('ended_at'))) self._result = unpickle(obj.get('result')) if obj.get('result') else None # noqa self.exc_info = obj.get('exc_info') @@ -432,6 +434,8 @@ class Job(object): obj['description'] = self.description if self.enqueued_at is not None: obj['enqueued_at'] = utcformat(self.enqueued_at) + if self.started_at is not None: + obj['started_at'] = utcformat(self.started_at) if self.ended_at is not None: obj['ended_at'] = utcformat(self.ended_at) if self._result is not None: diff --git a/rq/worker.py b/rq/worker.py index 64efdba..9ecb149 100644 --- a/rq/worker.py +++ b/rq/worker.py @@ -564,6 +564,7 @@ class Worker(object): started_job_registry = StartedJobRegistry(job.origin, self.connection) try: + job.started_at = utcnow() with self.death_penalty_class(job.timeout or self.queue_class.DEFAULT_TIMEOUT): rv = job.perform() diff --git a/tests/test_job.py b/tests/test_job.py index 4a57e6e..f31e316 100644 --- a/tests/test_job.py +++ b/tests/test_job.py @@ -54,6 +54,7 @@ class TestJob(RQTestCase): # ...and nothing else self.assertIsNone(job.origin) self.assertIsNone(job.enqueued_at) + self.assertIsNone(job.started_at) self.assertIsNone(job.ended_at) self.assertIsNone(job.result) self.assertIsNone(job.exc_info) diff --git a/tests/test_worker.py b/tests/test_worker.py index 40b84b4..8aafd83 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -83,6 +83,29 @@ class TestWorker(RQTestCase): 'Expected at least some work done.') self.assertEquals(job.result, 'Hi there, Frank!') + def assert_dt_between(self, dt, before, after): + if not before <= dt <= after: # pragma: no cover + raise AssertionError('Not %s <= %s <= %s' % (before, dt, after)) + + def test_job_times(self): + """job times are set correctly.""" + q = Queue('foo') + w = Worker([q]) + before = utcnow() + before = before.replace(microsecond=0) + job = q.enqueue(say_hello) + self.assertIsNotNone(job.enqueued_at) + self.assertIsNone(job.started_at) + self.assertIsNone(job.ended_at) + self.assertEquals(w.work(burst=True), True, + 'Expected at least some work done.') + self.assertEquals(job.result, 'Hi there, Stranger!') + after = utcnow() + job.refresh() + self.assert_dt_between(job.enqueued_at, before, after) + self.assert_dt_between(job.started_at, before, after) + self.assert_dt_between(job.ended_at, before, after) + def test_work_is_unreadable(self): """Unreadable jobs are put on the failed queue.""" q = Queue()