summaryrefslogtreecommitdiff
path: root/kazoo/recipe/election.py
blob: 93bb72580ebfacc3fac3454f7cd8a7e712b42315 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""ZooKeeper Leader Elections

:Maintainer: None
:Status: Unknown

"""
from kazoo.exceptions import CancelledError


class Election(object):
    """Kazoo Basic Leader Election

    Example usage with a :class:`~kazoo.client.KazooClient` instance::

        zk = KazooClient()
        zk.start()
        election = zk.Election("/electionpath", "my-identifier")

        # blocks until the election is won, then calls
        # my_leader_function()
        election.run(my_leader_function)

    """

    def __init__(self, client, path, identifier=None):
        """Create a Kazoo Leader Election

        :param client: A :class:`~kazoo.client.KazooClient` instance.
        :param path: The election path to use.
        :param identifier: Name to use for this lock contender. This
                           can be useful for querying to see who the
                           current lock contenders are.

        """
        self.lock = client.Lock(path, identifier)

    def run(self, func, *args, **kwargs):
        """Contend for the leadership

        This call will block until either this contender is cancelled
        or this contender wins the election and the provided leadership
        function subsequently returns or fails.

        :param func: A function to be called if/when the election is
                     won.
        :param args: Arguments to leadership function.
        :param kwargs: Keyword arguments to leadership function.

        """
        if not callable(func):
            raise ValueError("leader function is not callable")

        try:
            with self.lock:
                func(*args, **kwargs)

        except CancelledError:
            pass

    def cancel(self):
        """Cancel participation in the election

        .. note::

            If this contender has already been elected leader, this
            method will not interrupt the leadership function.

        """
        self.lock.cancel()

    def contenders(self):
        """Return an ordered list of the current contenders in the
        election

        .. note::

            If the contenders did not set an identifier, it will appear
            as a blank string.

        """
        return self.lock.contenders()