示例#1
0
    def _handle_quorum(self, quorum: int, quorum_timeout: int,
                       options: dict) -> Iterator[bool]:
        """
        Context manager that handles migration application quorum by only
        allowing a single caller to proceed with application and preventing
        exit attempts until the application is completes.

        This ensures only a single invocation is allowed to proceed once
        quorum is reached and that context can only be exited once the
        invocation application succeeds.
        """
        if quorum < 2:
            yield True
            return
        verbosity = options["verbosity"]
        plan = self._get_plan(**options)
        if not plan:
            yield True
            return
        database = options["database"]
        plan_hash = hash_plan(plan)
        pre_namespace = f"pre:{database}:{plan_hash}"
        post_namespace = f"post:{database}:{plan_hash}"
        if join_quorum(pre_namespace, quorum):
            if verbosity:
                self.stdout.write(
                    "Reached pre-migrate quorum, proceeding with planned migrations..."
                )
            yield True
            if verbosity:
                self.stdout.write("Waiting for post-migrate quorum...")
            duration = self._join_or_poll_until_quorum(post_namespace, quorum,
                                                       quorum_timeout)
            if verbosity:
                self.stdout.write(
                    f"Reached post-migrate quorum after {duration:.2f}s...")
            return
        yield False
        if verbosity:
            self.stdout.write("Waiting for pre-migrate quorum...")
        duration = self._poll_until_quorum(pre_namespace, quorum,
                                           quorum_timeout)
        if verbosity:
            self.stdout.write(
                f"Reached pre-migrate quorum after {duration:.2f}s...")
            self.stdout.write(
                "Waiting for migrations to be applied by remote party...")
        duration = self._join_or_poll_until_quorum(post_namespace, quorum,
                                                   quorum_timeout)
        if verbosity:
            self.stdout.write(
                f"Reached post-migrate quorum after {duration:.2f}s...")
            self.stdout.write("Migrations applied by remote party")
        return
示例#2
0
 def test_app_label(self):
     test_app = (Migration("0001_initial", "tests"), True)
     other_app = (Migration("0001_initial", "other"), True)
     self.assertNotEqual(hash_plan([test_app]), hash_plan([other_app]))
示例#3
0
 def test_backward(self):
     forward = (Migration("0001_initial", "tests"), True)
     backward = (Migration("0001_initial", "tests"), False)
     self.assertNotEqual(hash_plan([forward]), hash_plan([backward]))
示例#4
0
 def test_migration_name(self):
     first = (Migration("0001_initial", "tests"), True)
     second = (Migration("0002_second", "tests"), True)
     self.assertNotEqual(hash_plan([first]), hash_plan([second]))
示例#5
0
 def test_stable(self):
     plan = [(Migration("0001_initial", "tests"), True)]
     self.assertEqual(hash_plan(plan),
                      "a4a35230c7d1942265f1bc8f9ce53e05a50848be")