示例#1
0
    def test_multi_connection(self):
        lock_a = Lock("a")
        lock_b = Lock("b", using='other')

        with lock_a, lock_b:
            # Different connections = can hold > 1!
            assert lock_a.is_held()
            assert lock_b.is_held()
示例#2
0
    def test_held_with_prefix(self):
        if not self.supports_lock_info:
            self.skipTest(
                "Only MariaDB 10.0.7+ has the metadata_lock_info plugin on "
                "which held_with_prefix relies",
            )

        assert Lock.held_with_prefix('') == {}
        assert Lock.held_with_prefix('mylock') == {}

        with Lock('mylock-alpha') as lock:
            assert (
                Lock.held_with_prefix('')
                == {'mylock-alpha': lock.holding_connection_id()}
            )
            assert (
                Lock.held_with_prefix('mylock')
                == {'mylock-alpha': lock.holding_connection_id()}
            )
            assert (
                Lock.held_with_prefix('mylock-beta')
                == {}
            )

        assert Lock.held_with_prefix('') == {}
        assert Lock.held_with_prefix('mylock') == {}
示例#3
0
    def test_holding_more_than_one(self):
        is_mariadb = connection_is_mariadb(connection)
        supports_multiple_locks = (
            is_mariadb and connection.mysql_version >= (10, 0, 2)
        ) or (not is_mariadb and connection.mysql_version >= (5, 7))
        if not supports_multiple_locks:
            self.skipTest(
                "Only MySQL 5.7+ and MariaDB 10.0.2+ have the ability to hold "
                "more than one named lock"
            )

        lock_a = Lock("a")
        lock_b = Lock("b")
        with lock_a, lock_b:
            assert lock_a.is_held()
示例#4
0
    def test_simple(self):
        mylock = Lock("mylock")
        assert not mylock.is_held()

        with mylock:
            assert mylock.is_held()
            assert Lock("mylock").is_held()

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]
            assert mylock.holding_connection_id() == own_connection_id

        assert not mylock.is_held()
        assert not Lock("mylock").is_held()
示例#5
0
    def test_holding_more_than_one(self):
        conn = connection
        supports_multiple_locks = (
            (conn.is_mariadb and conn.mysql_version >= (10, 0, 2)) or
            (not conn.is_mariadb and conn.mysql_version >= (5, 7))
        )
        if not supports_multiple_locks:
            self.skipTest(
                "Only MySQL 5.7+ and MariaDB 10.0.2+ have the ability to hold "
                "more than one named lock"
            )

        lock_a = Lock("a")
        lock_b = Lock("b")
        with lock_a, lock_b:
            assert lock_a.is_held()
示例#6
0
    def test_held_with_prefix(self):
        if not self.supports_lock_info:
            self.skipTest(
                "Only MariaDB 10.0.7+ has the metadata_lock_info plugin on "
                "which held_with_prefix relies"
            )

        assert Lock.held_with_prefix('') == {}
        assert Lock.held_with_prefix('mylock') == {}

        with Lock('mylock-alpha') as lock:
            assert (
                Lock.held_with_prefix('') ==
                {'mylock-alpha': lock.holding_connection_id()}
            )
            assert (
                Lock.held_with_prefix('mylock') ==
                {'mylock-alpha': lock.holding_connection_id()}
            )
            assert (
                Lock.held_with_prefix('mylock-beta') ==
                {}
            )

        assert Lock.held_with_prefix('') == {}
        assert Lock.held_with_prefix('mylock') == {}
示例#7
0
    def test_threads_concurrent_access(self):
        """
        Test that the same lock object can be used in multiple threads, allows
        the definition of a lock upfront in a module.
        """
        if TYPE_CHECKING:  # pragma: no branch
            to_me: queue.Queue[str]
            to_you: queue.Queue[str]

        to_me = queue.Queue()
        to_you = queue.Queue()
        the_lock = Lock("THElock", 0.05)

        def check_it_lock_it():
            assert not the_lock.is_held()
            with the_lock:
                to_me.put("Locked")
                to_you.get(True)

        other_thread = Thread(target=check_it_lock_it)
        other_thread.start()
        try:
            item = to_me.get(True)
            assert item == "Locked"

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID()")
            own_connection_id = cursor.fetchone()[0]

            assert the_lock.is_held()
            assert the_lock.holding_connection_id() != own_connection_id

            with pytest.raises(TimeoutError):
                with the_lock:
                    pass

            to_you.put("Stop")
        finally:
            other_thread.join()

        with the_lock:
            pass
示例#8
0
    def test_simple(self):
        mylock = Lock("mylock")
        assert not mylock.is_held()

        with mylock:
            assert mylock.is_held()
            assert Lock("mylock").is_held()

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]
            assert mylock.holding_connection_id() == own_connection_id

        assert not mylock.is_held()
        assert not Lock("mylock").is_held()
示例#9
0
    def test_multi_connection(self):
        lock_a = Lock("a")
        lock_b = Lock("b", using="other")

        with lock_a, lock_b:
            # Different connections = can hold > 1!
            assert lock_a.is_held()
            assert lock_b.is_held()
示例#10
0
    def test_threads_concurrent_access(self):
        """
        Test that the same lock object can be used in multiple threads, allows
        the definition of a lock upfront in a module.
        """
        to_me = queue.Queue()
        to_you = queue.Queue()
        the_lock = Lock('THElock', 0.05)

        def check_it_lock_it():
            assert not the_lock.is_held()
            with the_lock:
                to_me.put("Locked")
                to_you.get(True)

        other_thread = Thread(target=check_it_lock_it)
        other_thread.start()
        try:
            item = to_me.get(True)
            assert item == "Locked"

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID()")
            own_connection_id = cursor.fetchone()[0]

            assert the_lock.is_held()
            assert the_lock.holding_connection_id() != own_connection_id

            with pytest.raises(TimeoutError):
                with the_lock:
                    pass

            to_you.put("Stop")
        finally:
            other_thread.join()

        with the_lock:
            pass
示例#11
0
    def test_timeout_with_threads(self):
        to_me = queue.Queue()
        to_you = queue.Queue()

        def lock_until_told():
            with Lock('threading_test'):
                to_me.put("Locked")
                to_you.get(True)

        threading_test = Lock('threading_test', 0.05)
        assert not threading_test.is_held()

        other_thread = Thread(target=lock_until_told)
        other_thread.start()
        try:
            item = to_me.get(True)
            assert item == "Locked"

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]

            assert threading_test.is_held()
            assert threading_test.holding_connection_id() != own_connection_id

            with pytest.raises(TimeoutError):
                with threading_test:
                        pass

            to_you.put("Stop")
        finally:
            other_thread.join()

        assert not threading_test.is_held()
        with threading_test:
            pass
示例#12
0
    def test_timeout_with_threads(self):
        if TYPE_CHECKING:  # pragma: no cover
            to_me: queue.Queue[str]
            to_you: queue.Queue[str]

        to_me = queue.Queue()
        to_you = queue.Queue()

        def lock_until_told():
            with Lock("threading_test"):
                to_me.put("Locked")
                to_you.get(True)

        threading_test = Lock("threading_test", 0.05)
        assert not threading_test.is_held()

        other_thread = Thread(target=lock_until_told)
        other_thread.start()
        try:
            item = to_me.get(True)
            assert item == "Locked"

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]

            assert threading_test.is_held()
            assert threading_test.holding_connection_id() != own_connection_id

            with pytest.raises(TimeoutError):
                with threading_test:
                    pass

            to_you.put("Stop")
        finally:
            other_thread.join()

        assert not threading_test.is_held()
        with threading_test:
            pass
示例#13
0
 def test_acquire_release(self):
     my_lock = Lock('not_a_context_manager')
     my_lock.acquire()
     my_lock.release()
示例#14
0
class LockTests(TestCase):

    if django.VERSION >= (2, 2):
        databases = ["default", "other"]
    else:
        multi_db = True

    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        cls.supports_lock_info = connection_is_mariadb(
            connection
        ) and connection.mysql_version >= (10, 0, 7)
        if cls.supports_lock_info:
            with connection.cursor() as cursor:
                cursor.execute(
                    """SELECT COUNT(*) FROM INFORMATION_SCHEMA.PLUGINS
                       WHERE PLUGIN_NAME = 'metadata_lock_info'"""
                )
                cls.lock_info_preinstalled = cursor.fetchone()[0] > 0
                if not cls.lock_info_preinstalled:
                    cursor.execute("INSTALL SONAME 'metadata_lock_info'")

    @classmethod
    def tearDownClass(cls):
        if cls.supports_lock_info and not cls.lock_info_preinstalled:
            with connection.cursor() as cursor:
                cursor.execute("UNINSTALL SONAME 'metadata_lock_info'")
        super().tearDownClass()

    def test_simple(self):
        mylock = Lock("mylock")
        assert not mylock.is_held()

        with mylock:
            assert mylock.is_held()
            assert Lock("mylock").is_held()

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]
            assert mylock.holding_connection_id() == own_connection_id

        assert not mylock.is_held()
        assert not Lock("mylock").is_held()

    def test_error_on_unneeded_exit(self):
        mylock = Lock("mylock")
        assert not mylock.is_held()
        with pytest.raises(ValueError) as excinfo:
            mylock.__exit__(None, None, None)
        assert "unheld lock" in str(excinfo.value)

    import_time_lock = Lock("defined_at_import_time")

    def test_defined_at_import_time(self):
        import_time_lock = self.import_time_lock

        assert not import_time_lock.is_held()

        with import_time_lock:
            assert import_time_lock.is_held()

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]
            assert import_time_lock.holding_connection_id() == own_connection_id

        assert not import_time_lock.is_held()

    def test_timeout_with_threads(self):
        to_me = queue.Queue()
        to_you = queue.Queue()

        def lock_until_told():
            with Lock("threading_test"):
                to_me.put("Locked")
                to_you.get(True)

        threading_test = Lock("threading_test", 0.05)
        assert not threading_test.is_held()

        other_thread = Thread(target=lock_until_told)
        other_thread.start()
        try:
            item = to_me.get(True)
            assert item == "Locked"

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID();")
            own_connection_id = cursor.fetchone()[0]

            assert threading_test.is_held()
            assert threading_test.holding_connection_id() != own_connection_id

            with pytest.raises(TimeoutError):
                with threading_test:
                    pass

            to_you.put("Stop")
        finally:
            other_thread.join()

        assert not threading_test.is_held()
        with threading_test:
            pass

    def test_threads_concurrent_access(self):
        """
        Test that the same lock object can be used in multiple threads, allows
        the definition of a lock upfront in a module.
        """
        to_me = queue.Queue()
        to_you = queue.Queue()
        the_lock = Lock("THElock", 0.05)

        def check_it_lock_it():
            assert not the_lock.is_held()
            with the_lock:
                to_me.put("Locked")
                to_you.get(True)

        other_thread = Thread(target=check_it_lock_it)
        other_thread.start()
        try:
            item = to_me.get(True)
            assert item == "Locked"

            cursor = connection.cursor()
            cursor.execute("SELECT CONNECTION_ID()")
            own_connection_id = cursor.fetchone()[0]

            assert the_lock.is_held()
            assert the_lock.holding_connection_id() != own_connection_id

            with pytest.raises(TimeoutError):
                with the_lock:
                    pass

            to_you.put("Stop")
        finally:
            other_thread.join()

        with the_lock:
            pass

    def test_holding_more_than_one(self):
        is_mariadb = connection_is_mariadb(connection)
        supports_multiple_locks = (
            is_mariadb and connection.mysql_version >= (10, 0, 2)
        ) or (not is_mariadb and connection.mysql_version >= (5, 7))
        if not supports_multiple_locks:
            self.skipTest(
                "Only MySQL 5.7+ and MariaDB 10.0.2+ have the ability to hold "
                "more than one named lock"
            )

        lock_a = Lock("a")
        lock_b = Lock("b")
        with lock_a, lock_b:
            assert lock_a.is_held()

    def test_multi_connection(self):
        lock_a = Lock("a")
        lock_b = Lock("b", using="other")

        with lock_a, lock_b:
            # Different connections = can hold > 1!
            assert lock_a.is_held()
            assert lock_b.is_held()

    def test_held_with_prefix(self):
        if not self.supports_lock_info:
            self.skipTest(
                "Only MariaDB 10.0.7+ has the metadata_lock_info plugin on "
                "which held_with_prefix relies"
            )

        assert Lock.held_with_prefix("") == {}
        assert Lock.held_with_prefix("mylock") == {}

        with Lock("mylock-alpha") as lock:
            assert Lock.held_with_prefix("") == {
                "mylock-alpha": lock.holding_connection_id()
            }
            assert Lock.held_with_prefix("mylock") == {
                "mylock-alpha": lock.holding_connection_id()
            }
            assert Lock.held_with_prefix("mylock-beta") == {}

        assert Lock.held_with_prefix("") == {}
        assert Lock.held_with_prefix("mylock") == {}

    def test_acquire_release(self):
        my_lock = Lock("not_a_context_manager")
        my_lock.acquire()
        my_lock.release()
示例#15
0
 def test_acquire_release(self):
     my_lock = Lock("not_a_context_manager")
     my_lock.acquire()
     my_lock.release()
示例#16
0
 def test_holding_more_than_one(self):
     lock_a = Lock("a")
     lock_b = Lock("b")
     with lock_a, lock_b:
         assert lock_a.is_held()
示例#17
0
    def handle(self):
        if self.is_event('CLICK'):
            activity_id = int(self.input['EventKey'][len(self.view.event_keys['book_header']):])
            try:
                activity = Activity.objects.get(id=activity_id)
            except Activity.DoesNotExist:
                raise NotExistError
        else:
            try:
                activity_name = self.get_first_param_in_command()
            except:
                return self.reply_text((self.get_message('book_format_wrong')))
            activity = Activity.objects.get(name=activity_name)

        # user
        if self.user.student_id == "":
            # 未绑定学号
            return self.reply_text(self.get_message('student_id_not_bind'))

        # activity
        if not activity:
            # 活动不存在或活动名输入错误
            return self.reply_text(self.get_message('activity_not_exist'))
        if time.time() < activity.book_start.timestamp():
            # 还未到抢票开始时间
            return self.reply_text(self.get_message('book_not_start'))
        if time.time() > activity.book_end.timestamp():
            # 已经超过了抢票开始时间
            return self.reply_text(self.get_message('book_already_finish'))
        if activity.remain_tickets <= 0:
            # 票已抢光
            return self.reply_text(self.get_message('tickets_out'))

        # ticket
        if Ticket.objects.filter(Q(student_id=self.user.student_id) & Q(activity=activity)).exists():
            # 本学号已经抢过票
            ticket=Ticket.objects.get(Q(student_id=self.user.student_id) & Q(activity=activity))
            if ticket.status==Ticket.STATUS_VALID:
                return self.reply_text(self.get_message('already_book_tickets'))
            else:
                ticket.status=Ticket.STATUS_VALID
                activity.remain_tickets = activity.remain_tickets - 1
                ticket.save()
                activity.save()
                return self.reply_text(self.get_message('book_success'))



        try:
            with Lock('book_ticket_lock', acquire_timeout=2.0):
                activity.remain_tickets = activity.remain_tickets - 1
                activity.save()
        except TimeoutError:
            return self.reply_text('抢票冲突,请稍后再试。')

        uniqueid=uuid.uuid3(uuid.NAMESPACE_DNS, self.user.student_id).hex+uuid.uuid3(uuid.NAMESPACE_DNS, activity.name).hex

        try:
            Ticket.objects.create(student_id=self.user.student_id, unique_id=uniqueid,
                                  activity=activity, status=Ticket.STATUS_VALID)
        except:
            raise BookFailedError("Book ticket handler error: ticket creation failed")

        return self.reply_text(self.get_message('book_success'))
示例#18
0
 def test_error_on_unneeded_exit(self):
     mylock = Lock("mylock")
     assert not mylock.is_held()
     with pytest.raises(ValueError) as excinfo:
         mylock.__exit__(None, None, None)
     assert "unheld lock" in str(excinfo.value)
示例#19
0
 def test_error_on_unneeded_exit(self):
     mylock = Lock("mylock")
     assert not mylock.is_held()
     with pytest.raises(ValueError) as excinfo:
         mylock.__exit__(None, None, None)
     assert "unheld lock" in str(excinfo.value)
示例#20
0
 def lock_until_told():
     with Lock("threading_test"):
         to_me.put("Locked")
         to_you.get(True)
示例#21
0
 def serialized_func(*args, **kws):
     with Lock(str(id(func))):
         return func(*args, **kws)