File: extending.rst

package info (click to toggle)
python-sherlock 0.4.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 344 kB
  • sloc: python: 2,008; makefile: 162
file content (128 lines) | stat: -rw-r--r-- 3,976 bytes parent folder | download
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
.. :mod:`sherlock` documentation master file, created by
   sphinx-quickstart on Wed Jan 22 11:28:21 2014.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

.. _extending:

Extending
=========

:mod:`sherlock` can be easily extended to work with any backend. You just have
to register your lock's implementation with :mod:`sherlock` and you will be
able to use your lock with the backend of your choice in your project.

Registration
++++++++++++

Custom locks can be registered using the following API:

.. automethod:: sherlock.backends.register

Example
+++++++

Here is an example of implementing a custom lock that uses `Elasticsearch`_ as
backend.

.. _Elasticsearch: http://elasticsearch.org

.. note:: You may distributed your custom lock implementation as package if you
          please. Just make sure that you add :mod:`sherlock` as a dependency.

The following code goes in a module called ``sherlock_es.py``.

.. code:: python

    import elasticsearch
    import sherlock
    import uuid

    from elasticsearch import Elasticsearch
    from sherlock import LockException


    class ESLock(sherlock.lock.BaseLock):
        def __init__(self, lock_name, **kwargs):
            super(ESLock, self).__init__(lock_name, **kwargs)

            if self.client is None:
                self.client = Elasticsearch(hosts=['localhost:9200'])

            self._owner = None

        def _acquire(self):
            owner = uuid.uuid4().hex

            try:
                self.client.get(index='sherlock', doc_type='locks',
                                id=self.lock_name)
            except elasticsearch.NotFoundError, err:
                self.client.index(index='sherlock', doc_type='locks',
                                  id=self.lock_name, body=dict(owner=owner))
                self._owner = owner
                return True
            else:
                return False

        def _release(self):
            if self._owner is None:
                raise LockException('Lock was not set by this process.')

            try:
                resp = self.client.get(index='sherlock', doc_type='locks',
                                       id=self.lock_name)
                if resp['_source']['owner'] == self._owner:
                    self.client.delete(index='sherlock', doc_type='locks',
                                       id=self.lock_name)

                else:
                    raise LockException('Lock could not be released because it '
                                        'was not acquired by this process.')
            except elasticsearch.NotFoundError, err:
                raise LockException('Lock could not be released as it has not '
                                    'been acquired.')

        @property
        def _locked(self):
            try:
                self.client.get(index='sherlock', doc_type='locks',
                                id=self.lock_name)
                return True
            except elasticsearch.NotFoundError, err:
                return False


    # Register the custom lock with sherlock
    sherlock.backends.register(name='ES',
                               lock_class=ESLock,
                               library='elasticsearch',
                               client_class=Elasticsearch,
                               default_args=(),
                               default_kwargs={
                                   'hosts': ['localhost:9200'],
                               })

Our module can be used like so:

.. code:: python

    import sherlock
    import sherlock_es

    # Notice that ES is available as backend now
    sherlock.configure(backend=sherlock.backends.ES)

    lock1 = sherlock.Lock('test1')
    lock1.acquire() # True

    lock2 = sherlock_es.ESLock('test2')
    lock2.acquire() # True

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`