def test_RunnableQueue_process_PauseQueueJob(mocker): api_client = mocker.MagicMock() session_maker = mocker.MagicMock(return_value=mocker.MagicMock()) queue = RunnableQueue(api_client, session_maker) queue.JOB_PRIORITIES = {PauseQueueJob: 11} queue.add_job(PauseQueueJob()) queue.process() assert queue.queue.empty()
def test_ApiJobQueue_on_file_download_queue_paused(mocker): job_queue = ApiJobQueue(mocker.MagicMock(), mocker.MagicMock()) mocker.patch.object(job_queue, 'paused') pause_job = PauseQueueJob() mocker.patch('securedrop_client.queue.PauseQueueJob', return_value=pause_job) job_queue.on_file_download_queue_paused() job_queue.paused.emit.assert_called_once_with()
def test_ApiJobQueue_on_main_queue_paused(mocker): job_queue = ApiJobQueue(mocker.MagicMock(), mocker.MagicMock()) mocker.patch.object(job_queue, "paused") pause_job = PauseQueueJob() mocker.patch("securedrop_client.queue.PauseQueueJob", return_value=pause_job) job_queue.on_main_queue_paused() job_queue.paused.emit.assert_called_once_with()
def test_ApiJobQueue_pause_queues(mocker): job_queue = ApiJobQueue(mocker.MagicMock(), mocker.MagicMock()) mocker.patch.object(job_queue, 'paused') pause_job = PauseQueueJob() mocker.patch('securedrop_client.queue.PauseQueueJob', return_value=pause_job) job_queue.on_queue_paused() job_queue.paused.emit()
def process(self) -> None: """ Process the next job in the queue. If the job is a PauseQueueJob, emit the paused signal and return from the processing loop so that no more jobs are processed until the queue resumes. If the job raises RequestTimeoutError or ServerConnectionError, then: (1) Add a PauseQueuejob to the queue (2) Add the job back to the queue so that it can be reprocessed once the queue is resumed. If the job raises ApiInaccessibleError, then: (1) Set the token to None so that the queue manager will stop enqueuing jobs since we are no longer able to make api requests. (2) Return from the processing loop since a valid token will be needed in order to process jobs. Note: Generic exceptions are handled in _do_call_api. """ while True: with self.condition_add_or_remove_job: self.condition_add_or_remove_job.wait_for(lambda: not self.queue.empty()) priority, self.current_job = self.queue.get(block=False) if isinstance(self.current_job, PauseQueueJob): self.paused.emit() with self.condition_add_or_remove_job: self.current_job = None return try: session = self.session_maker() self.current_job._do_call_api(self.api_client, session) except ApiInaccessibleError as e: logger.debug("{}: {}".format(type(e).__name__, e)) self.api_client = None with self.condition_add_or_remove_job: self.current_job = None return except (RequestTimeoutError, ServerConnectionError) as e: logger.debug("{}: {}".format(type(e).__name__, e)) self.add_job(PauseQueueJob()) with self.condition_add_or_remove_job: job, self.current_job = self.current_job, None self._re_add_job(job) except Exception as e: logger.error("{}: {}".format(type(e).__name__, e)) logger.debug("Skipping job") finally: with self.condition_add_or_remove_job: self.current_job = None session.close()
def test_RunnableQueue_happy_path(mocker): ''' Add one job to the queue, run it. ''' mock_api_client = mocker.MagicMock() mock_session = mocker.MagicMock() mock_session_maker = mocker.MagicMock(return_value=mock_session) return_value = 'foo' dummy_job_cls = factory.dummy_job_factory(mocker, return_value) queue = RunnableQueue(mock_api_client, mock_session_maker) queue.JOB_PRIORITIES = {dummy_job_cls: 1, PauseQueueJob: 2} queue.add_job(dummy_job_cls()) queue.add_job( PauseQueueJob()) # Pause queue so our test exits the processing loop queue.process() assert queue.queue.empty()
def test_RunnableQueue_job_generic_exception(mocker): ''' Add two jobs to the queue, the first of which will cause a generic exception, which is handled in _do_call_api. Ensure that the queue continues processing jobs after dropping a job that runs into a generic exception. ''' job1_cls = factory.dummy_job_factory(mocker, Exception()) # processing skips job job2_cls = factory.dummy_job_factory(mocker, 'mock') job1 = job1_cls() job2 = job2_cls() queue = RunnableQueue(mocker.MagicMock(), mocker.MagicMock()) queue.JOB_PRIORITIES = {PauseQueueJob: 3, job1_cls: 2, job2_cls: 2} queue.add_job(job1) queue.add_job(job2) queue.add_job( PauseQueueJob()) # Pause queue so our test exits the processing loop queue.process() # check that all jobs are gone assert queue.queue.empty()
def fake_pause() -> None: queue.add_job(PauseQueueJob())