class FormProcessingResult(object): def __init__(self, submitted_form, existing_duplicate=None): self.submitted_form = submitted_form self.existing_duplicate = existing_duplicate if submitted_form.is_duplicate: assert existing_duplicate is None if existing_duplicate: assert existing_duplicate.is_deprecated self.interface = FormProcessorInterface(self.submitted_form.domain) def _get_form_lock(self, form_id): return self.interface.acquire_lock_for_xform(form_id) def get_locked_forms(self): if self.existing_duplicate: # Lock docs with their original ID's (before they got switched during deprecation) new_id = self.existing_duplicate.form_id old_id = self.existing_duplicate.orig_id return MultiLockManager([ LockManager(self.submitted_form, self._get_form_lock(new_id)), LockManager(self.existing_duplicate, self._get_form_lock(old_id)), ]) else: return MultiLockManager([ LockManager(self.submitted_form, self._get_form_lock(self.submitted_form.form_id)) ])
class FormProcessingResult(object): def __init__(self, submitted_form, existing_duplicate=None): self.submitted_form = submitted_form self.existing_duplicate = existing_duplicate self.interface = FormProcessorInterface(self.submitted_form.domain) def _get_form_lock(self, form_id): return self.interface.acquire_lock_for_xform(form_id) def get_locked_forms(self): if self.existing_duplicate: # Lock docs with their original ID's (before they got switched during deprecation) old_id = self.existing_duplicate.form_id new_id = self.submitted_form.form_id assert old_id != new_id, 'Expecting form IDs to be different' return MultiLockManager([ LockManager(self.submitted_form, self._get_form_lock(new_id)), LockManager(self.existing_duplicate, self._get_form_lock(old_id)), ]) else: return MultiLockManager([ LockManager(self.submitted_form, self._get_form_lock(self.submitted_form.form_id)) ])
def test_xform_locked(self): from corehq.form_processor.interfaces.processor import FormProcessorInterface form_id = 'ad38211be256653bceac8e2156475664' proc = FormProcessorInterface(self.domain) lock = proc.acquire_lock_for_xform(form_id) try: _, response = self._submit('simple_form.xml') finally: lock.release() self.assertEqual(response.status_code, 423)
def test_xform_locked(self): from corehq.form_processor.interfaces.processor import FormProcessorInterface form_id = 'ad38211be256653bceac8e2156475664' proc = FormProcessorInterface(self.domain) lock = proc.acquire_lock_for_xform(form_id) try: _, response = self._submit('simple_form.xml') finally: lock.release() self.assertEqual(response.status_code, 423)
def reprocess_form(form, save=True, lock_form=True): interface = FormProcessorInterface(form.domain) lock = interface.acquire_lock_for_xform( form.form_id) if lock_form else None with LockManager(form, lock): logger.info('Reprocessing form: %s (%s)', form.form_id, form.domain) # reset form state prior to processing if should_use_sql_backend(form.domain): form.state = XFormInstanceSQL.NORMAL else: form.doc_type = 'XFormInstance' cache = interface.casedb_cache(domain=form.domain, lock=True, deleted_ok=True, xforms=[form]) with cache as casedb: try: case_stock_result = SubmissionPost.process_xforms_for_cases( [form], casedb) except (IllegalCaseId, UsesReferrals, MissingProductId, PhoneDateValueError, InvalidCaseIndex, CaseValueError) as e: error_message = '{}: {}'.format( type(e).__name__, six.text_type(e)) form = interface.xformerror_from_xform_instance( form, error_message) return ReprocessingResult(form, [], [], error_message) form.initial_processing_complete = True form.problem = None stock_result = case_stock_result.stock_result assert stock_result.populated cases = case_stock_result.case_models _log_changes(cases, stock_result.models_to_save, stock_result.models_to_delete) ledgers = [] if should_use_sql_backend(form.domain): cases_needing_rebuild = _get_case_ids_needing_rebuild( form, cases) ledgers = stock_result.models_to_save ledgers_updated = { ledger.ledger_reference for ledger in ledgers if ledger.is_saved() } if save: for case in cases: CaseAccessorSQL.save_case(case) LedgerAccessorSQL.save_ledger_values(ledgers) FormAccessorSQL.update_form_problem_and_state(form) FormProcessorSQL._publish_changes( ProcessedForms(form, None), cases, stock_result) # rebuild cases and ledgers that were affected for case in cases: if case.case_id in cases_needing_rebuild: logger.info('Rebuilding case: %s', case.case_id) if save: # only rebuild cases that were updated detail = FormReprocessRebuild(form_id=form.form_id) interface.hard_rebuild_case(case.case_id, detail, lock=False) for ledger in ledgers: if ledger.ledger_reference in ledgers_updated: logger.info('Rebuilding ledger: %s', ledger.ledger_reference) if save: # only rebuild updated ledgers interface.ledger_processor.rebuild_ledger_state( **ledger.ledger_reference._asdict()) else:
def reprocess_form(form, save=True, lock_form=True): if lock_form: # track load if locking; otherise it will be tracked elsewhere form_load_counter("reprocess_form", form.domain)() interface = FormProcessorInterface(form.domain) lock = interface.acquire_lock_for_xform(form.form_id) if lock_form else None with LockManager(form, lock): logger.info('Reprocessing form: %s (%s)', form.form_id, form.domain) # reset form state prior to processing if should_use_sql_backend(form.domain): form.state = XFormInstanceSQL.NORMAL else: form.doc_type = 'XFormInstance' cache = interface.casedb_cache( domain=form.domain, lock=True, deleted_ok=True, xforms=[form], load_src="reprocess_form", ) with cache as casedb: try: case_stock_result = SubmissionPost.process_xforms_for_cases([form], casedb) except (IllegalCaseId, UsesReferrals, MissingProductId, PhoneDateValueError, InvalidCaseIndex, CaseValueError) as e: error_message = '{}: {}'.format(type(e).__name__, six.text_type(e)) form = interface.xformerror_from_xform_instance(form, error_message) return ReprocessingResult(form, [], [], error_message) form.initial_processing_complete = True form.problem = None stock_result = case_stock_result.stock_result assert stock_result.populated cases = case_stock_result.case_models _log_changes(cases, stock_result.models_to_save, stock_result.models_to_delete) ledgers = [] if should_use_sql_backend(form.domain): cases_needing_rebuild = _get_case_ids_needing_rebuild(form, cases) ledgers = stock_result.models_to_save ledgers_updated = {ledger.ledger_reference for ledger in ledgers if ledger.is_saved()} if save: for case in cases: CaseAccessorSQL.save_case(case) LedgerAccessorSQL.save_ledger_values(ledgers) FormAccessorSQL.update_form_problem_and_state(form) FormProcessorSQL.publish_changes_to_kafka(ProcessedForms(form, None), cases, stock_result) # rebuild cases and ledgers that were affected for case in cases: if case.case_id in cases_needing_rebuild: logger.info('Rebuilding case: %s', case.case_id) if save: # only rebuild cases that were updated detail = FormReprocessRebuild(form_id=form.form_id) interface.hard_rebuild_case(case.case_id, detail, lock=False) for ledger in ledgers: if ledger.ledger_reference in ledgers_updated: logger.info('Rebuilding ledger: %s', ledger.ledger_reference) if save: # only rebuild updated ledgers interface.ledger_processor.rebuild_ledger_state(**ledger.ledger_reference._asdict()) else: if save: interface.processor.save_processed_models([form], cases, stock_result) from casexml.apps.stock.models import StockTransaction ledgers = [ model for model in stock_result.models_to_save if isinstance(model, StockTransaction) ] for ledger in ledgers: interface.ledger_processor.rebuild_ledger_state(**ledger.ledger_reference._asdict()) save and SubmissionPost.do_post_save_actions(casedb, [form], case_stock_result) return ReprocessingResult(form, cases, ledgers, None)