Esempio n. 1
0
 def get(self):
     """获取任务列表"""
     args = request.args
     job_status = args.get('job_status')
     queue_name = args.get('queue_name')
     if job_status not in Config.RQ_JOB_STATUS:
         return {
             'code': StatesCode.JOB_STATUS_NO_EXIST,
             'message': '任务状态不存在!'
         }
     if queue_name not in Config.RQ_QUEUES_ALL:
         return {'code': StatesCode.QUEUE_NOT_EXIST, 'message': '任务队列不存在!'}
     job_list = []
     if job_status == 'queued':
         if queue_name == 'all':
             for queue_name in Config.RQ_QUEUES:
                 job_list += queue_dict[queue_name].get_job_ids()
         else:
             job_list = queue_dict[queue_name].get_job_ids()
     elif job_status == 'started':
         if queue_name == 'all':
             for queue_name in Config.RQ_QUEUES:
                 started_job_registry = StartedJobRegistry(
                     queue=queue_dict[queue_name])
                 job_list += started_job_registry.get_job_ids()
         else:
             started_job_registry = StartedJobRegistry(
                 queue=queue_dict[queue_name])
             job_list = started_job_registry.get_job_ids()
     elif job_status == 'finished':
         if queue_name == 'all':
             for queue_name in Config.RQ_QUEUES:
                 finished_job_registry = FinishedJobRegistry(
                     queue=queue_dict[queue_name])
                 job_list += finished_job_registry.get_job_ids()
         else:
             finished_job_registry = FinishedJobRegistry(
                 queue=queue_dict[queue_name])
             job_list = finished_job_registry.get_job_ids()
     elif job_status == 'failed':
         if queue_name == 'all':
             for queue_name in Config.RQ_QUEUES:
                 failed_job_registry = FailedJobRegistry(
                     queue=queue_dict[queue_name])
                 job_list += failed_job_registry.get_job_ids()
         else:
             failed_job_registry = FailedJobRegistry(
                 queue=queue_dict[queue_name])
             job_list = failed_job_registry.get_job_ids()
     elif job_status == 'deferred':
         if queue_name == 'all':
             for queue_name in Config.RQ_QUEUES:
                 deferred_job_registry = DeferredJobRegistry(
                     queue=queue_dict[queue_name])
                 job_list += deferred_job_registry.get_job_ids()
         else:
             deferred_job_registry = DeferredJobRegistry(
                 queue=queue_dict[queue_name])
             job_list = deferred_job_registry.get_job_ids()
     return {'code': StatesCode.SUCCESS, 'data': job_list}
Esempio n. 2
0
class TestFinishedJobRegistry(RQTestCase):

    def setUp(self):
        super(TestFinishedJobRegistry, self).setUp()
        self.registry = FinishedJobRegistry(connection=self.testconn)

    def test_cleanup(self):
        """Finished job registry removes expired jobs."""
        timestamp = current_timestamp()
        self.testconn.zadd(self.registry.key, 1, 'foo')
        self.testconn.zadd(self.registry.key, timestamp + 10, 'bar')
        self.testconn.zadd(self.registry.key, timestamp + 30, 'baz')

        self.registry.cleanup()
        self.assertEqual(self.registry.get_job_ids(), ['bar', 'baz'])

        self.registry.cleanup(timestamp + 20)
        self.assertEqual(self.registry.get_job_ids(), ['baz'])

    def test_jobs_are_put_in_registry(self):
        """Completed jobs are added to FinishedJobRegistry."""
        self.assertEqual(self.registry.get_job_ids(), [])
        queue = Queue(connection=self.testconn)
        worker = Worker([queue])

        # Completed jobs are put in FinishedJobRegistry
        job = queue.enqueue(say_hello)
        worker.perform_job(job, queue)
        self.assertEqual(self.registry.get_job_ids(), [job.id])

        # Failed jobs are not put in FinishedJobRegistry
        failed_job = queue.enqueue(div_by_zero)
        worker.perform_job(failed_job, queue)
        self.assertEqual(self.registry.get_job_ids(), [job.id])
Esempio n. 3
0
def test_reenqueue_object_success(reenqueue_object, session, redis,
                                  museum_object, museum_package):
    # Create fake DB entries
    museum_package.downloaded = True
    museum_package.packaged = True
    museum_package.uploaded = True
    museum_package.rejected = True
    session.commit()

    # Create a job that was completed prior to re-enqueuing
    queue = get_queue(QueueType.CONFIRM_SIP)

    queue.enqueue(successful_job, job_id="confirm_sip_123456")
    SimpleWorker([queue], connection=queue.connection).work(burst=True)

    finished_registry = FinishedJobRegistry(queue=queue)
    assert finished_registry.get_job_ids() == ["confirm_sip_123456"]

    result = reenqueue_object(["123456"])

    assert "Object 123456 re-enqueued" in result.stdout

    # New RQ task was enqueued
    queue = get_queue(QueueType.DOWNLOAD_OBJECT)
    assert "download_object_123456" in queue.job_ids

    # Database was updated
    db_museum_object = session.query(MuseumObject).filter_by(id=123456).one()

    assert len(db_museum_object.packages) == 1
    assert not db_museum_object.latest_package

    # Prior finished job was removed
    assert finished_registry.get_job_ids() == []
Esempio n. 4
0
class TestFinishedJobRegistry(RQTestCase):

    def setUp(self):
        super(TestFinishedJobRegistry, self).setUp()
        self.registry = FinishedJobRegistry(connection=self.testconn)

    def test_cleanup(self):
        """Finished job registry removes expired jobs."""
        timestamp = current_timestamp()
        self.testconn.zadd(self.registry.key, 1, 'foo')
        self.testconn.zadd(self.registry.key, timestamp + 10, 'bar')
        self.testconn.zadd(self.registry.key, timestamp + 30, 'baz')

        self.registry.cleanup()
        self.assertEqual(self.registry.get_job_ids(), ['bar', 'baz'])

        self.registry.cleanup(timestamp + 20)
        self.assertEqual(self.registry.get_job_ids(), ['baz'])

    def test_jobs_are_put_in_registry(self):
        """Completed jobs are added to FinishedJobRegistry."""
        self.assertEqual(self.registry.get_job_ids(), [])
        queue = Queue(connection=self.testconn)
        worker = Worker([queue])

        # Completed jobs are put in FinishedJobRegistry
        job = queue.enqueue(say_hello)
        worker.perform_job(job)
        self.assertEqual(self.registry.get_job_ids(), [job.id])

        # Failed jobs are not put in FinishedJobRegistry
        failed_job = queue.enqueue(div_by_zero)
        worker.perform_job(failed_job)
        self.assertEqual(self.registry.get_job_ids(), [job.id])
Esempio n. 5
0
def get_all_finished_tasks_from(queue_name, app_info):
    with Connection(redis.from_url(app_info['REDIS_URL'])):
        f_registry = FinishedJobRegistry(queue_name)
        job_ids = f_registry.get_job_ids()

        # Generate the task info
        return generate_task_info(queue_name, job_ids, "finished")
Esempio n. 6
0
 def getfinishedjobs(self, q):
     try:
         registry = FinishedJobRegistry(q, connection=self.base_connection)
         response_object = registry.get_job_ids()
         return response_object
     except Exception as e:
         return e
Esempio n. 7
0
def get_finished_tasks(request):

    current_queue = request.GET.get('queue')
    queue = django_rq.get_queue(current_queue)
    registry = FinishedJobRegistry(queue.name, queue.connection)

    items_per_page = 10
    num_jobs = len(registry)
    jobs = []

    if num_jobs > 0:
        offset = 0
        job_ids = registry.get_job_ids(offset, items_per_page)

        for job_id in job_ids:
            try:
                jobs.append(Job.fetch(job_id, connection=queue.connection))
            except NoSuchJobError:
                pass

    jobdata = list()
    for job in jobs:

        job_dict = {
            'job_id': job.id,
            'func_name': job.func_name,
            'ended_at': job.ended_at.strftime("%a, %d %b %Y %H:%M:%S +0000"),
            'enqueued_at': job.enqueued_at.strftime("%a, %d %b %Y %H:%M:%S +0000"),
            'args': job.args}

        jobdata.append(job_dict)

    data = json.dumps(jobdata)
    return HttpResponse(data, content_type='application/json')
Esempio n. 8
0
def finished_jobs(request, queue_index):
    queue_index = int(queue_index)
    queue = get_queue_by_index(queue_index)

    registry = FinishedJobRegistry(queue.name, queue.connection)

    items_per_page = 100
    num_jobs = len(registry)
    page = int(request.GET.get('page', 1))
    jobs = []

    if num_jobs > 0:
        last_page = int(ceil(num_jobs / items_per_page))
        page_range = range(1, last_page + 1)
        offset = items_per_page * (page - 1)
        job_ids = registry.get_job_ids(offset, offset + items_per_page - 1)
        jobs = get_jobs(queue, job_ids, registry)

    else:
        page_range = []

    context_data = {
        'queue': queue,
        'queue_index': queue_index,
        'jobs': jobs,
        'num_jobs': num_jobs,
        'page': page,
        'page_range': page_range,
        'job_status': 'Finished',
    }
    return render(request, 'django_rq/jobs.html', context_data)
Esempio n. 9
0
def get_previous_job_from_registry(index=-1):
    q = Queue('high', connection=conn)
    registry = FinishedJobRegistry(queue=q)

    job_id = registry.get_job_ids()[index]
    job = q.fetch_job(job_id)

    return job
Esempio n. 10
0
 def _remove_jobs(self, project):
     started_registry = StartedJobRegistry(self._redis_queue.name, self._redis_queue.connection)
     finished_registry = FinishedJobRegistry(self._redis_queue.name, self._redis_queue.connection)
     for job_id in started_registry.get_job_ids() + finished_registry.get_job_ids():
         job = Job.fetch(job_id, connection=self._redis)
         if job.meta.get('project') != project:
             continue
         logger.info(f'Deleting job_id {job_id}')
         job.delete()
Esempio n. 11
0
 def getfinishedjobs(self, q):
     """returns list of finished redis jobs"""
     log.info(f"getting finished jobs: {q}")
     try:
         registry = FinishedJobRegistry(q, connection=self.base_connection)
         response_object = registry.get_job_ids()
         return response_object
     except Exception as e:
         return e
Esempio n. 12
0
def show_results():
    registry = FinishedJobRegistry(queue=q)
    ids = registry.get_job_ids()
    print("Got finished jobs:", len(ids))
    res = []
    for j in ids:
        job = q.fetch_job(j)
        if job.result and job.result is not None and isinstance(job.result, ResultField):
            print("Result:", job.result.name, job.result.power, job.result.duration)
            res.append(job.result)
    return render_template('overview.html', rows=res)
Esempio n. 13
0
def queue_count():
    queue_out = {}
    csv_out = str(int(time.time()))
    csv_out += ','
    with Connection(redis.from_url(current_app.config['REDIS_URL'])):
        q = Queue('default')
        f_registry = FinishedJobRegistry('default')
        csv_out += str(len(q))
        csv_out += ','
        csv_out += str(len(f_registry.get_job_ids()))
    csv_out += '\n'
    return csv_out
Esempio n. 14
0
 def test_job_from_non_default_queue_completed(self):
     """
     Ensure that job from non default queue successfully completed
     when run from rqworker.
     """
     queue_name = 'django_rq_test'
     queue = get_queue(queue_name)
     job = queue.enqueue(divide, 42, 1)
     finished_job_registry = FinishedJobRegistry(queue.name,
                                                 queue.connection)
     call_command('rqworker', queue_name, burst=True)
     self.assertTrue(job.is_finished)
     self.assertIn(job.id, finished_job_registry.get_job_ids())
Esempio n. 15
0
 def _remove_jobs(cls, project):
     started_registry = StartedJobRegistry(
         cls._redis_queue.name, cls._redis_queue.connection
     )
     finished_registry = FinishedJobRegistry(
         cls._redis_queue.name, cls._redis_queue.connection
     )
     for job_id in started_registry.get_job_ids() + finished_registry.get_job_ids():
         job = Job.fetch(job_id, connection=cls._redis)
         if job.meta.get("project") != project:
             continue
         logger.info("Deleting job_id " + job_id)
         job.delete()
Esempio n. 16
0
    def test_04_schedule(self):
        """
        Should create a task a put in Redis queue.
        """

        redis_conn = db_utils.get_redis_conn()
        job_id = upload.schedule("test", "test")
        time.sleep(1)
        finished = FinishedJobRegistry(RQ_NLP_QUEUE_LOW, connection=redis_conn)
        finished_job_ids = finished.get_job_ids()
        queue = Queue(RQ_NLP_QUEUE_LOW, connection=redis_conn)
        active_job_ids = queue.get_job_ids()
        self.assertTrue(job_id in [*finished_job_ids, *active_job_ids])
Esempio n. 17
0
def flush_redis():
    with Connection(redis.from_url(current_app.config['REDIS_URL'])):
        queues = ['default', 'aggregator']

        for queue in queues:
            q = Queue(queue)
            f_registry = FinishedJobRegistry(queue)
            finished_job_ids = f_registry.get_job_ids()

            for f_job_id in finished_job_ids:
                j = q.fetch_job(f_job_id)
                j.cleanup(0)

    return "Flushed"
Esempio n. 18
0
def monitor():
    '''
    DOESN'T WORK
    Meant to run until all jobs are finished. Monitors queues and adds completed graphs to Blazegraph.
    '''
    sregistry = StartedJobRegistry(connection=redis_conn)
    fregistry = FinishedJobRegistry(connection=redis_conn)
    print high.get_job_ids()
    print sregistry.get_job_ids()
    while sregistry.get_job_ids():
        print 'in sregistry...'
        print fregistry.get_job_ids()
        for job_id in fregistry.get_job_ids():
            job = Job.fetch(job_id, connection=redis_conn)
            # sanity check
            if type(job.result) is Graph:
                print ('inserting', job_id, job)
                logging.info('inserting', job_id, job)
                insert(job.result)
        print 'sleeping 5'
        time.sleep(5)

    print 'all jobs complete'
    logging.info('monitor() exiting...all jobs complete')
Esempio n. 19
0
def get_all_finished_tasks_from(queue_name):
    with Connection(redis.from_url(current_app.config['REDIS_URL'])):
        # q = Queue(queue_name)
        f_registry = FinishedJobRegistry(queue_name)
        data = {}

        finished_job_ids = f_registry.get_job_ids()
        data['status'] = 'success'
        data['queue_name'] = queue_name
        data['finished'] = {}

        data['finished']['count'] = len(finished_job_ids)
        data['finished']['finished_tasks_ids'] = []
        for finished_job_id in finished_job_ids:
            data['finished']['finished_tasks_ids'].append(finished_job_id)

        return jsonify(data)
Esempio n. 20
0
def delete_finished(c, queue=None):
    """Delete finished jobs from given queue
    """
    if queue is None:
        raise ValueError("Please specify queue")

    q = Queue(
        queue,
        connection=Redis(host=REDIS_HOST,
                         port=REDIS_PORT,
                         password=REDIS_PASSWORD,
                         db=REDIS_DB),
    )
    registry = FinishedJobRegistry(queue=q)
    for job_id in registry.get_job_ids():
        job = q.fetch_job(job_id)
        if job is not None and job.is_started:
            job.delete()
def _get_job_list(redis_conn):
    queue_list = _get_queue_list()
    job_list = []

    for q in queue_list:
        queue = Queue(q, connection=redis_conn)
        jobs = queue.get_jobs()

        for j in jobs:
            job_list.append({'id': j.get_id(), 'status': j.get_status()})

        registry = FinishedJobRegistry(name=q, connection=redis_conn)
        job_ids = registry.get_job_ids()

        for jid in job_ids:
            job = Job.fetch(jid, connection=redis_conn)
            job_list.append({'id': jid, 'status': job.get_status()})

    return job_list
Esempio n. 22
0
def get_average():

    # TODO: Code for case where there are no registries yet
    avg_time = {}
    redis = Redis()
    qs = ['high', 'default', 'low']
    for q in qs:
        registry = FinishedJobRegistry(name=q, connection=redis)
        averages = []
        for job_id in registry.get_job_ids():
            job = Job.fetch(job_id, connection=redis)
            averages.append((job.ended_at - job.enqueued_at).total_seconds())
        ave = sum(averages) / len(averages)
        avg_time[q] = time.strftime('%H:%M:%S', time.gmtime(ave))

    response = api.response_class(response=json.dumps(avg_time),
                                  status=200,
                                  mimetype='application/json')
    return response
Esempio n. 23
0
def get_all_task_ids(app_info):
    with Connection(redis.from_url(app_info['REDIS_URL'])):
        q = Queue('default')
        registry = StartedJobRegistry('default')
        f_registry = FinishedJobRegistry('default')

    if q:
        data = {}
        running_job_ids = registry.get_job_ids()
        expired_job_ids = registry.get_expired_job_ids()
        finished_job_ids = f_registry.get_job_ids()
        queued_job_ids = q.job_ids
        data['status'] = 'success'
        data['queue_name'] = 'default'  #Make dynamic or parameterized?
        data['running'] = {}
        data['queued'] = {}
        data['expired'] = {}
        data['finished'] = {}

        data['running']['count'] = len(running_job_ids)
        data['running']['running_tasks_ids'] = []
        for running_job_id in running_job_ids:
            data['running']['running_tasks_ids'].append(running_job_id)

        data['queued']['count'] = len(queued_job_ids)
        data['queued']['queued_tasks_ids'] = []
        for queued_job_id in queued_job_ids:
            data['queued']['queued_tasks_ids'].append(queued_job_id)

        data['expired']['count'] = len(expired_job_ids)
        data['expired']['expired_tasks_ids'] = []
        for expired_job_id in expired_job_ids:
            data['expired']['expired_tasks_ids'].append(expired_job_id)

        data['finished']['count'] = len(finished_job_ids)
        data['finished']['finished_tasks_ids'] = []
        for finished_job_id in finished_job_ids:
            data['finished']['finished_tasks_ids'].append(finished_job_id)

        return data

    return {'status': 'error'}
Esempio n. 24
0
def finished_jobs(request, queue_index):
    queue_index = int(queue_index)
    queue = get_queue_by_index(queue_index)

    registry = FinishedJobRegistry(queue.name, queue.connection)

    items_per_page = 100
    num_jobs = len(registry)
    page = int(request.GET.get('page', 1))
    jobs = []

    if num_jobs > 0:
        last_page = int(ceil(num_jobs / items_per_page))
        page_range = range(1, last_page + 1)
        offset = items_per_page * (page - 1)
        job_ids = registry.get_job_ids(offset, items_per_page)

        for job_id in job_ids:
            try:
                jobs.append(Job.fetch(job_id, connection=queue.connection))
            except NoSuchJobError:
                pass

    else:
        page_range = []

    ###
    # Custom logic here
    for job in jobs:
        use_actual_name(job)
    ##

    context_data = {
        'queue': queue,
        'queue_index': queue_index,
        'jobs': jobs,
        'num_jobs': num_jobs,
        'page': page,
        'page_range': page_range,
        'job_status': 'Finished',
    }
    return render(request, 'django_rq/jobs.html', context_data)
Esempio n. 25
0
 def handle(self, *args, **options):
     import django_rq
     from rq.registry import FinishedJobRegistry
     from rq.exceptions import NoSuchJobError
     from rq.job import Job
     from datetime import datetime, timedelta
     day_before_yesterday = datetime.now() - timedelta(days=2)
     for index, config in enumerate(django_rq.settings.QUEUES_LIST):
         queue = django_rq.queues.get_queue_by_index(index)
         registry = FinishedJobRegistry(queue.name, queue.connection)
         for job_id in registry.get_job_ids():
             try:
                 job = Job.fetch(job_id, connection=queue.connection)
                 # delete jobs older 2 days
                 if job.ended_at > day_before_yesterday:
                     continue
             except NoSuchJobError:
                 # for some reason job already deleted but job key exists
                 pass
             registry.connection.zrem(registry.key, job_id)
Esempio n. 26
0
def finished_jobs(request, queue_index):
    queue_index = int(queue_index)
    queue = get_queue_by_index(queue_index)

    registry = FinishedJobRegistry(queue.name, queue.connection)

    items_per_page = 100
    num_jobs = len(registry)
    page = int(request.GET.get('page', 1))
    jobs = []

    if num_jobs > 0:
        last_page = int(ceil(num_jobs / items_per_page))
        page_range = range(1, last_page + 1)
        offset = items_per_page * (page - 1)
        job_ids = registry.get_job_ids(offset, items_per_page)

        for job_id in job_ids:
            try:
                jobs.append(Job.fetch(job_id, connection=queue.connection))
            except NoSuchJobError:
                pass

    else:
        page_range = []

    context_data = admin.site.each_context(request)
    context_data.update({
        'title': _("Finished Jobs"),
        'queue': queue,
        'queue_index': queue_index,
        'jobs': jobs,
        'num_jobs': num_jobs,
        'page': page,
        'page_range': page_range,
        'job_status': _('Finished'),
    })
    return render(request, 'django_rq/jobs.html', context_data)
Esempio n. 27
0
class TestFinishedJobRegistry(RQTestCase):
    def setUp(self):
        super(TestFinishedJobRegistry, self).setUp()
        self.registry = FinishedJobRegistry(connection=self.testconn)

    def test_key(self):
        self.assertEqual(self.registry.key, 'rq:finished:default')

    def test_cleanup(self):
        """Finished job registry removes expired jobs."""
        timestamp = current_timestamp()
        self.testconn.zadd(self.registry.key, {'foo': 1})
        self.testconn.zadd(self.registry.key, {'bar': timestamp + 10})
        self.testconn.zadd(self.registry.key, {'baz': timestamp + 30})

        self.registry.cleanup()
        self.assertEqual(self.registry.get_job_ids(), ['bar', 'baz'])

        self.registry.cleanup(timestamp + 20)
        self.assertEqual(self.registry.get_job_ids(), ['baz'])

        # CanceledJobRegistry now implements noop cleanup, should not raise exception
        registry = CanceledJobRegistry(connection=self.testconn)
        registry.cleanup()

    def test_jobs_are_put_in_registry(self):
        """Completed jobs are added to FinishedJobRegistry."""
        self.assertEqual(self.registry.get_job_ids(), [])
        queue = Queue(connection=self.testconn)
        worker = Worker([queue])

        # Completed jobs are put in FinishedJobRegistry
        job = queue.enqueue(say_hello)
        worker.perform_job(job, queue)
        self.assertEqual(self.registry.get_job_ids(), [job.id])

        # When job is deleted, it should be removed from FinishedJobRegistry
        self.assertEqual(job.get_status(), JobStatus.FINISHED)
        job.delete()
        self.assertEqual(self.registry.get_job_ids(), [])

        # Failed jobs are not put in FinishedJobRegistry
        failed_job = queue.enqueue(div_by_zero)
        worker.perform_job(failed_job, queue)
        self.assertEqual(self.registry.get_job_ids(), [])
Esempio n. 28
0
def finished_jobs(request, queue_index):
    queue_index = int(queue_index)
    queue = get_queue_by_index(queue_index)

    registry = FinishedJobRegistry(queue.name, queue.connection)

    items_per_page = 100
    num_jobs = len(registry)
    page = int(request.GET.get('page', 1))
    jobs = []

    if num_jobs > 0:
        last_page = int(ceil(num_jobs / items_per_page))
        page_range = range(1, last_page + 1)
        offset = items_per_page * (page - 1)
        job_ids = registry.get_job_ids(offset, offset + items_per_page - 1)

        for job_id in job_ids:
            try:
                jobs.append(Job.fetch(job_id, connection=queue.connection))
            except NoSuchJobError:
                pass

    else:
        page_range = []

    context_data = {
        'queue': queue,
        'queue_index': queue_index,
        'jobs': jobs,
        'num_jobs': num_jobs,
        'page': page,
        'page_range': page_range,
        'job_status': 'Finished',
    }
    return render(request, 'django_rq/jobs.html', context_data)
Esempio n. 29
0
class TestFinishedJobRegistry(RQTestCase):

    def setUp(self):
        super(TestFinishedJobRegistry, self).setUp()
        self.registry = FinishedJobRegistry(connection=self.testconn)

    def test_key(self):
        self.assertEqual(self.registry.key, 'rq:finished:default')

    def test_cleanup(self):
        """Finished job registry removes expired jobs."""
        timestamp = current_timestamp()
        self.testconn.zadd(self.registry.key, {'foo': 1})
        self.testconn.zadd(self.registry.key, {'bar': timestamp + 10})
        self.testconn.zadd(self.registry.key, {'baz': timestamp + 30})

        self.registry.cleanup()
        self.assertEqual(self.registry.get_job_ids(), ['bar', 'baz'])

        self.registry.cleanup(timestamp + 20)
        self.assertEqual(self.registry.get_job_ids(), ['baz'])

    def test_jobs_are_put_in_registry(self):
        """Completed jobs are added to FinishedJobRegistry."""
        self.assertEqual(self.registry.get_job_ids(), [])
        queue = Queue(connection=self.testconn)
        worker = Worker([queue])

        # Completed jobs are put in FinishedJobRegistry
        job = queue.enqueue(say_hello)
        worker.perform_job(job, queue)
        self.assertEqual(self.registry.get_job_ids(), [job.id])

        # When job is deleted, it should be removed from FinishedJobRegistry
        self.assertEqual(job.get_status(), JobStatus.FINISHED)
        job.delete()
        self.assertEqual(self.registry.get_job_ids(), [])

        # Failed jobs are not put in FinishedJobRegistry
        failed_job = queue.enqueue(div_by_zero)
        worker.perform_job(failed_job, queue)
        self.assertEqual(self.registry.get_job_ids(), [])
Esempio n. 30
0
class QueueManager:

    retries_before_fail = 10
    backoff = 30

    def __init__(self, name, connection):
        self._name = name
        self._logger = logger.bind(queue=name)

        self._queue = rq.Queue('vivarium', connection=connection)
        self._wip = StartedJobRegistry('vivarium',
                                       connection=connection,
                                       job_class=self._queue.job_class)
        self._finished = FinishedJobRegistry('vivarium',
                                             connection=connection,
                                             job_class=self._queue.job_class)

        self._status = {
            'total': 0,
            'pending': 0,
            'running': 0,
            'failed': 0,
            'finished': 0,
            'done': 0.,
            'workers': 0
        }
        self._failed = False
        self._completed = False

        self._retries = QueueManager.retries_before_fail
        self._backoff = QueueManager.backoff

    @property
    def name(self):
        return self._name

    @property
    def failed(self):
        return self._failed

    @property
    def completed(self):
        return self._completed

    @property
    def jobs_to_finish(self):
        return not (self.failed or self.completed)

    def enqueue(self, jobs):
        self._logger.info(f'Enqueuing jobs in queue {self.name}')
        for job in jobs:
            # TODO: might be nice to have tighter ttls but it's hard to predict how long our jobs
            # will take from model to model and the entire system is short lived anyway
            self._queue.enqueue(
                'vivarium_cluster_tools.psimulate.distributed_worker.worker',
                parameters=job,
                ttl=60 * 60 * 24 * 2,
                result_ttl=60 * 60,
                job_timeout='7d')

    def get_results(self):
        self._logger.info(f'Checking queue {self.name}')
        finished_jobs = self._get_finished_jobs()
        start = time.time()
        results = []
        for job_id in finished_jobs:
            result = self._get_result(job_id)
            if result is not None:
                results.append(result)
        self._logger.info(
            f'Retrieved {len(results)} results from queue {self.name} in {time.time() - start:.2f}s'
        )
        return results

    def update_and_report(self):
        self._update_status()
        template = (
            f"Queue {self.name} - Total jobs: {{total}}, % Done: {{done:.2f}}% "
            f"Pending: {{pending}}, Running: {{running}}, Failed: {{failed}}, Finished: {{finished}} "
            f"Workers: {{workers}}.")
        if not (self.completed or self.failed):
            self._logger.info(template.format(**self._status))
        return self._status

    def _update_status(self):
        if self.jobs_to_finish and self._retries > 0:
            self._logger.info(f'Updating status for queue {self.name}')
            # TODO: Sometimes there are duplicate job_ids, why?
            try:
                q_pending = len(set(self._queue.job_ids)) if self._queue else 0
                q_running = len(self._wip) if self._wip else 0
                q_to_write = len(self._finished) if self._finished else 0
                q_failed = len(self._queue.failed_job_registry
                               ) if self._queue else self._status['failed']
                q_finished = self._status['finished']
                q_total = q_pending + q_running + q_failed + q_to_write + q_finished
                q_workers = len(ResilientWorker.all(
                    queue=self._queue)) if self._queue else 0

                self._status['pending'] = q_pending
                self._status['running'] = q_running + q_to_write
                self._status['failed'] = q_failed
                self._status['finished'] = q_finished
                self._status['total'] = q_total
                self._status['workers'] = q_workers
                self._status['done'] = q_finished / q_total * 100

                if sum([q_pending, q_running, q_to_write]) == 0:
                    self._mark_complete()
                elif sum([q_pending, q_workers, q_to_write]) == 0:
                    self._logger.info(
                        f'Queue {self.name} ran out of workers with running jobs.  Marking finished.'
                    )
                    self._mark_complete()
            except redis.connection.ConnectionError:
                self._sleep_on_it()
                self._update_status()
        else:
            self._mark_failed()

    def _get_finished_jobs(self):
        if self._retries:
            try:
                return self._finished.get_job_ids()
            except redis.exceptions.ConnectionError:
                self._sleep_on_it()
                return self._get_finished_jobs()
        else:
            self._mark_failed()
            return []

    def _get_result(self, job_id):
        job = self._get_job(job_id)
        result = None
        if job is not None:
            start = time.time()
            result = pd.read_msgpack(job.result[0])
            end = time.time()
            self._logger.debug(
                f'Read {job_id} from msgpack from queue {self.name} in {end - start:.2f}s.'
            )
            self._status['finished'] += 1
            self._remove_finished_job(job)
        return result

    def _get_job(self, job_id):
        if self._retries:
            try:
                start = time.time()
                job = self._queue.fetch_job(job_id)
                end = time.time()
                self._logger.debug(
                    f'Fetched job {job_id} from queue {self.name} in {end - start:.2f}s'
                )
                return job
            except redis.exceptions.ConnectionError:
                self._sleep_on_it()
                return self._get_job(job_id)
        else:
            self._mark_failed()
            return None

    def _remove_finished_job(self, job):
        if self._retries:
            try:
                self._finished.remove(job)
            except redis.exceptions.ConnectionError:
                self._sleep_on_it()
                self._remove_finished_job(job)
        else:
            self._mark_failed()

    def _sleep_on_it(self):
        backoff = self._backoff * random.random()
        self._logger.warning(
            f'Failed to connect to redis for queue {self.name}.  Retrying in {backoff}s.'
        )
        self._retries -= 1
        time.sleep(backoff)

    def _mark_failed(self):
        # TODO: Probably should cleanup redis stuff, but not sure how yet.
        if not (self.failed or self.completed):
            self._logger.warning(
                f'Queue {self.name} has run out of retries.  Marking as failed.'
            )
            self._status[
                'failed'] += self._status['pending'] + self._status['running']
            self._status['pending'] = 0
            self._status['running'] = 0
            self._status['workers'] = 0
            self._failed = True

    def _mark_complete(self):
        if not (self.failed or self.completed):
            self._logger.info(f'All jobs on queue {self.name} complete.')
            self._status['finished'] += self._status['pending'] + self._status[
                'running']
            self._status['pending'] = 0
            self._status['running'] = 0
            self._status['workers'] = 0
            self._completed = True
Esempio n. 31
0
def list_all_jobs():
    registry = FinishedJobRegistry(os.environ["RQ_QUEUE"], connection=redis)

    print(f"{len(registry.get_job_ids())} record(s) succesfully saved to './output/data.json'.")
    return Job.fetch_many(registry.get_job_ids(), connection=redis)
Esempio n. 32
0
def GetJobProgress(app):
    """Infinite thread that sends job updates to client."""
    with app.app_context():
        redis = Redis()
        queue = Queue(connection=redis)
        running_registry = StartedJobRegistry(queue=queue)
        finished_registry = FinishedJobRegistry(queue=queue)

        showing_running_job_bar = False
        toggle_on_running_job_bar = False
        toggle_off_running_job_bar = False

        while True:
            time.sleep(2)
            running_msg = "Running jobs:"
            finished_msg = ""
            running_job_id_list = running_registry.get_job_ids()
            finished_job_id_list = finished_registry.get_job_ids()

            if running_job_id_list:
                # Get all job progress and emit update
                for job_id in running_job_id_list:
                    running_msg += "<br>Job ID: {}".format(job_id)
                    running_job = Job.fetch(id=job_id, connection=redis)
                    if 'process' in running_job.meta:
                        running_msg += "<UL><LI>Process: {}".format(
                            running_job.meta['process'])
                    if 'progress' in running_job.meta:
                        running_msg += "<LI>Progress: {}</UL>".format(
                            running_job.meta['progress'])
                socketio.emit('update job progress', {'data': running_msg})
                toggle_on_running_job_bar = True
            else:
                toggle_off_running_job_bar = True

            if finished_job_id_list:
                # Display finished job notification and save to db
                for job_id in finished_job_id_list:
                    finished_msg += "<br>Job ID: {}".format(job_id)
                    finished_job = Job.fetch(job_id, connection=redis)
                    if 'process' in finished_job.meta:
                        finished_msg += "<UL><LI>Process: {}".format(
                            finished_job.meta['process'])
                    rq_job = RQJob()
                    rq_job.save_job(finished_job)
                    finished_registry.remove(finished_job)
                    finished_msg += "<LI>Result: {}".format(
                        rq_job.get_result())
                    finished_msg += "<LI>Time elapsed: {} seconds</UL>".format(
                        rq_job.get_elapsed_time())
                socketio.emit('update job finished', {'data': finished_msg})
                socketio.emit('show finished job bar')

            if showing_running_job_bar and toggle_off_running_job_bar:
                toggle_off_running_job_bar = False
                toggle_on_running_job_bar = False
                showing_running_job_bar = False
                print('---------Server: Hide running job bar')
                socketio.emit('hide running job bar')
            elif not showing_running_job_bar and toggle_on_running_job_bar:
                toggle_off_running_job_bar = False
                toggle_on_running_job_bar = False
                showing_running_job_bar = True
                print('---------Server: Show running job bar')
                socketio.emit('show running job bar')
    return
Esempio n. 33
0
def clear_registry():
    registry = FinishedJobRegistry(os.environ["RQ_QUEUE"], connection=redis)
    for job_id in registry.get_job_ids():
        registry.remove(job_id)