Пример #1
0
 def test_patch_missing_case_with_index(self):
     self.submit_form(make_test_form("form-1", case_id="case-1"))
     case = CaseAccessorCouch.get_case("case-1")
     case.indices = [
         CommCareCaseIndex.wrap({
             "doc_type": "CommCareCaseIndex",
             "identifier": "parent",
             "referenced_type": "household",
             "referenced_id": "a53346d5",
             "relationship": "child",
         })
     ]
     case.save()
     FormAccessors(self.domain_name).soft_delete_forms(['form-1'],
                                                       datetime.utcnow(),
                                                       'test-deletion')
     self.do_migration(diffs=IGNORE)
     self.compare_diffs(changes=[
         Diff('case-1',
              'missing', ['*'],
              old='*',
              new=MISSING,
              reason="deleted forms"),
     ])
     self.do_case_patch()
     self.compare_diffs()
     self.assert_patched_cases(["case-1"])
Пример #2
0
def _iter_missing_blob_present_forms(statedb, stopper):
    def get_blob_present_form_ids(diff):
        if diff.kind == "CommCareCase":
            case_id = diff.doc_id
            data = json.loads(diff.old_value)["forms"]
            form_ids = [
                form_id for form_id, status in data.items()
                if status == "missing, blob present"
            ]
            assert form_ids, diff.old_value
        elif diff.kind == "stock state":
            case_id = diff.doc_id.split("/", 1)[0]
            data = json.loads(diff.old_value)
            assert data["form_state"] == "missing, blob present", data
            form_ids = [data["ledger"]["last_modified_form_id"]]
        return form_ids, case_id

    def iter_blob_metas(form_ids):
        metas = metadb.get_for_parents(form_ids)
        parents = set()
        for meta in metas:
            if meta.type_code == CODES.form_xml:
                yield meta, [m for m in metas if m.parent_id == meta.parent_id]
                assert meta.parent_id not in parents, metas
                parents.add(meta.parent_id)
        assert parents == set(form_ids), (form_ids, parents)

    def xml_to_form(domain, xml_meta, case_id, all_metas):
        form_id = xml_meta.parent_id
        with xml_meta.open() as fh:
            xml = fh.read()
        form_data = convert_xform_to_json(xml)
        form = FormProcessorCouch.new_xform(form_data)
        form.domain = domain
        form.received_on = get_received_on(case_id, form_id)
        for meta in all_metas:
            form.external_blobs[meta.name] = BlobMetaRef(
                key=meta.key,
                blobmeta_id=meta.id,
                content_type=meta.content_type,
                content_length=meta.content_length,
            )
        return form

    def get_received_on(case_id, form_id):
        case = CaseAccessorCouch.get_case(case_id)
        for action in case.actions:
            if action.xform_id == form_id:
                return action.server_date
        raise ValueError(f"case {case_id} has no actions for form {form_id}")
Пример #3
0
    def get_case(self, case_id):
        try:
            return CaseAccessorSQL.get_case(case_id)
        except CaseNotFound:
            pass

        try:
            return CaseAccessorCouch.get_case(case_id)
        except ResourceNotFound:
            pass

        return None
Пример #4
0
    def get_case(self, case_id):
        try:
            return CaseAccessorSQL.get_case(case_id)
        except CaseNotFound:
            pass

        try:
            return CaseAccessorCouch.get_case(case_id)
        except ResourceNotFound:
            pass

        return None
Пример #5
0
 def test_patch_case_closed_in_couch_missing_sql(self):
     self.submit_form(make_test_form("form-1", case_id="case-1"))
     case = CaseAccessorCouch.get_case("case-1")
     case.closed = True
     case.closed_by = "3fae4ea4af440efaa53441b5"
     case.closed_on = datetime(2010, 9, 8, 7, 6, 5)
     case.user_id = "3fae4ea4af440efaa53441b5"
     case.save()
     FormAccessors(self.domain_name).soft_delete_forms(["form-1"],
                                                       datetime.utcnow(),
                                                       'test-deletion')
     self.do_migration(diffs=IGNORE)
     self.compare_diffs(changes=[
         Diff('case-1',
              'missing', ['*'],
              old='*',
              new=MISSING,
              reason="deleted forms"),
     ])
     self.do_case_patch()
     self.compare_diffs()
     self.assert_patched_cases(["case-1"])
Пример #6
0
    def test_patch_case_with_deleted_form_and_unexpected_diff(self):
        self.submit_form(make_test_form("form-1", case_id="case-1"))
        case = CaseAccessorCouch.get_case("case-1")
        case.user_id = "unexpected"
        case.save()
        FormAccessors(self.domain_name).soft_delete_forms(["form-1"],
                                                          datetime.utcnow(),
                                                          'test-deletion')
        self.do_migration(diffs=IGNORE)
        self.compare_diffs(changes=[
            Diff('case-1',
                 'missing', ['*'],
                 old='*',
                 new=MISSING,
                 reason="deleted forms"),
        ])

        # first patch results in unexpected diff
        self.do_case_patch()
        self.compare_diffs(diffs=[
            Diff('case-1',
                 'diff', ['opened_by'],
                 old='3fae4ea4af440efaa53441b5',
                 new='unexpected'),
            Diff('case-1',
                 'set_mismatch',
                 path=['xform_ids', '[*]'],
                 old='form-1',
                 new=ANY),
        ])
        self.assert_patched_cases(["case-1"])

        # second patch resolves unexpected diff
        self.do_case_patch()
        self.compare_diffs()
        self.assert_backend("sql")
        self.assertFalse(self._get_case("case-1").deleted)
Пример #7
0
def get_couch_case(case_id):
    return CaseAccessorCouch.get_case(case_id)
Пример #8
0
            kw.setdefault("diffs", IGNORE)
        return super().do_migration(*args, **kw)

    def do_case_diffs(self, cases=None, stop=False):
        self.migration_success = True  # clear migration failure on diff cases
        migrator = mod.get_migrator(self.domain_name, self.state_dir)
        return mod.do_case_diffs(migrator, cases, stop=stop, batch_size=100)

    def do_case_patch(self, cases=None, stop=False):
        self.migration_success = True  # clear migration failure on diff cases
        migrator = mod.get_migrator(self.domain_name, self.state_dir)
        return mod.do_case_patch(migrator, cases, stop=stop, batch_size=100)

    @contextmanager
    def augmented_couch_case(self, case_id):
        case = CaseAccessorCouch.get_case(case_id)
        with self.diff_without_rebuild():
            yield case

    def assert_patched_cases(self, case_ids=None):
        statedb = open_state_db(self.domain_name, self.state_dir)
        self.assertEqual(list(statedb.iter_patched_case_ids()), case_ids or [])
        self.assertFalse(list(statedb.iter_undiffed_case_ids()))


THING_FORM = """
<?xml version="1.0" ?>
<data
    name="Thing"
    uiVersion="1"
    version="11"