def test_restore_in_progress_form_submitted_kills_old_jobs(self): """If the user submits a form somehow while a job is running, the job should be terminated """ task_cache_id = restore_cache_key(ASYNC_RESTORE_CACHE_KEY_PREFIX, self.user.user_id) initial_sync_cache_id = restore_cache_key(RESTORE_CACHE_KEY_PREFIX, self.user.user_id, version='2.0') fake_cached_thing = 'fake-cached-thing' restore_config = self._restore_config(async=True) # pretend we have a task running restore_config.cache.set(task_cache_id, fake_cached_thing) restore_config.cache.set(initial_sync_cache_id, fake_cached_thing) form = """ <data xmlns="http://openrosa.org/formdesigner/blah"> <meta> <userID>{user_id}</userID> </meta> </data> """ with mock.patch('corehq.form_processor.submission_post.revoke_celery_task') as revoke: # with a different user in the same domain, task doesn't get killed submit_form_locally(form.format(user_id="other_user"), self.domain) self.assertFalse(revoke.called) self.assertEqual(restore_config.cache.get(task_cache_id), fake_cached_thing) self.assertEqual(restore_config.cache.get(initial_sync_cache_id), fake_cached_thing) # task gets killed when the user submits a form submit_form_locally(form.format(user_id=self.user.user_id), self.domain) revoke.assert_called_with(fake_cached_thing) self.assertIsNone(restore_config.cache.get(task_cache_id)) self.assertIsNone(restore_config.cache.get(initial_sync_cache_id))
def test_restore_in_progress_form_submitted_kills_old_jobs(self): """If the user submits a form somehow while a job is running, the job should be terminated """ task_cache_id = restore_cache_key(ASYNC_RESTORE_CACHE_KEY_PREFIX, self.user.user_id) initial_sync_cache_id = restore_cache_key(RESTORE_CACHE_KEY_PREFIX, self.user.user_id, version='2.0') fake_cached_thing = 'fake-cached-thing' restore_config = self._restore_config(async=True) # pretend we have a task running restore_config.cache.set(task_cache_id, fake_cached_thing) restore_config.cache.set(initial_sync_cache_id, fake_cached_thing) form = """ <data xmlns="http://openrosa.org/formdesigner/blah"> <meta> <userID>{user_id}</userID> </meta> </data> """ with mock.patch('corehq.form_processor.submission_post.revoke_celery_task') as revoke: # with a different user in the same domain, task doesn't get killed submit_form_locally(form.format(user_id="other_user"), self.domain) self.assertFalse(revoke.called) self.assertEqual(restore_config.cache.get(task_cache_id), fake_cached_thing) self.assertEqual(restore_config.cache.get(initial_sync_cache_id), fake_cached_thing) # task gets killed when the user submits a form submit_form_locally(form.format(user_id=self.user.user_id), self.domain) revoke.assert_called_with(fake_cached_thing) self.assertIsNone(restore_config.cache.get(task_cache_id)) self.assertIsNone(restore_config.cache.get(initial_sync_cache_id))
def test_switch_restore_response(self): ''' Ensures that when switching from using a FileRestoreResponse to a BlobRestoreResponse that we don't use the old FileRestoreResponse cache ''' key1 = restore_cache_key('domain', 'prefix', 'user_id') with flag_enabled('BLOBDB_RESTORE'): key2 = restore_cache_key('domain', 'prefix', 'user_id') self.assertNotEqual(key1, key2)
def test_subsequent_syncs_when_job_complete(self): # First sync, return a timout. Ensure that the async_task_id gets set cache_id = restore_cache_key(ASYNC_RESTORE_CACHE_KEY_PREFIX, self.user.user_id) with mock.patch('casexml.apps.phone.restore.get_async_restore_payload' ) as task: delay = mock.MagicMock() delay.id = 'random_task_id' delay.get = mock.MagicMock( side_effect=TimeoutError()) # task not finished task.delay.return_value = delay restore_config = self._restore_config(async=True) initial_payload = restore_config.get_payload() self.assertIsNotNone(restore_config.cache.get(cache_id)) self.assertIsInstance(initial_payload, AsyncRestoreResponse) # new synclog should not have been created self.assertIsNone(restore_config.restore_state.current_sync_log) # Second sync, don't timeout (can't use AsyncResult in tests, so mock # the return value). file_restore_response = mock.MagicMock( return_value=FileRestoreResponse()) with mock.patch.object(AsyncResult, 'get', file_restore_response) as get_result: with mock.patch.object(AsyncResult, 'status', ASYNC_RESTORE_SENT): subsequent_restore = self._restore_config(async=True) self.assertIsNotNone(restore_config.cache.get(cache_id)) subsequent_restore.get_payload() # if the task actually ran, the cache should now not have the task id, # however, the task is not run in this test. See `test_completed_task_deletes_cache` # self.assertIsNone(restore_config.cache.get(cache_id)) get_result.assert_called_with(timeout=1)
def test_subsequent_syncs_when_job_complete(self): # First sync, return a timout. Ensure that the async_task_id gets set cache_id = restore_cache_key(ASYNC_RESTORE_CACHE_KEY_PREFIX, self.user.user_id) with mock.patch('casexml.apps.phone.restore.get_async_restore_payload') as task: delay = mock.MagicMock() delay.id = 'random_task_id' delay.get = mock.MagicMock(side_effect=TimeoutError()) # task not finished task.delay.return_value = delay restore_config = self._restore_config(async=True) initial_payload = restore_config.get_payload() self.assertIsNotNone(restore_config.cache.get(cache_id)) self.assertIsInstance(initial_payload, AsyncRestoreResponse) # new synclog should not have been created self.assertIsNone(restore_config.restore_state.current_sync_log) # Second sync, don't timeout (can't use AsyncResult in tests, so mock # the return value). file_restore_response = mock.MagicMock(return_value=FileRestoreResponse()) with mock.patch.object(AsyncResult, 'get', file_restore_response) as get_result: with mock.patch.object(AsyncResult, 'status', ASYNC_RESTORE_SENT): subsequent_restore = self._restore_config(async=True) self.assertIsNotNone(restore_config.cache.get(cache_id)) subsequent_restore.get_payload() # if the task actually ran, the cache should now not have the task id, # however, the task is not run in this test. See `test_completed_task_deletes_cache` # self.assertIsNone(restore_config.cache.get(cache_id)) get_result.assert_called_with(timeout=1)
def test_completed_task_deletes_cache(self): cache_id = restore_cache_key(ASYNC_RESTORE_CACHE_KEY_PREFIX, self.user.user_id) restore_config = self._restore_config(async=True) restore_config.cache.set(cache_id, 'im going to be deleted by the next command') get_async_restore_payload.delay(restore_config) self.assertIsNone(restore_config.cache.get(cache_id))
def has_cached_payload(sync_log, version, prefix=RESTORE_CACHE_KEY_PREFIX): return bool(get_redis_default_cache().get(restore_cache_key( sync_log.domain, prefix, sync_log.user_id, version=version, sync_log_id=sync_log._id, )))
def test_restore_caches_cleared(self): cache = get_redis_default_cache() cache_key = restore_cache_key(RESTORE_CACHE_KEY_PREFIX, 'user_id', version="2.0") cache.set(cache_key, 'test-thing') self.assertEqual(cache.get(cache_key), 'test-thing') form = """ <data xmlns="http://openrosa.org/formdesigner/blah"> <meta> <userID>{user_id}</userID> </meta> </data> """ submit_form_locally(form.format(user_id='user_id'), DOMAIN) self.assertIsNone(cache.get(cache_key))
def test_restore_caches_cleared(self): cache = get_redis_default_cache() cache_key = restore_cache_key(RESTORE_CACHE_KEY_PREFIX, 'user_id', version="2.0") cache.set(cache_key, 'test-thing') self.assertEqual(cache.get(cache_key), 'test-thing') form = """ <data xmlns="http://openrosa.org/formdesigner/blah"> <meta> <userID>{user_id}</userID> </meta> </data> """ submit_form_locally(form.format(user_id='user_id'), DOMAIN) self.assertIsNone(cache.get(cache_key))
def test_completed_task_deletes_cache(self): cache_id = restore_cache_key(ASYNC_RESTORE_CACHE_KEY_PREFIX, self.user.user_id) restore_config = self._restore_config(async=True) restore_config.cache.set(cache_id, 'im going to be deleted by the next command') get_async_restore_payload.delay(restore_config) self.assertIsNone(restore_config.cache.get(cache_id))