{ "info": { "author": "Trey Morris", "author_email": "trey@treymorris.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: Apache Software License" ], "description": "==========\nTwiceRedis\n==========\nread and write sentinel connection pool backed redis client\nwith disconnecting sentinel clients and redis clients\n\nwhen using a redis connection backed by a ``SentinelConnectionPool``,\nthe pool is initialized to connect to either the master or slaves.\nthis is annoying if you want to read from slaves and occasionally\nwrite to the master.\n``TwiceRedis`` solves this by having two clients,\none for master and one for slaves:\n\n* ``tr.master`` also aliased as ``tr.write``\n* ``tr.slave`` also aliased as ``tr.read``\n\nthe clients are each backed by a separate ``SentinelConnectionPool``\ninitialized to connect to the master or slaves respectively\n\n``TwiceRedis`` also uses a ``DisconnectingSentinel`` class to drastically\nreduce the number of active connections to the redis sentinel service(s).\nthis class drops connection to the chosen sentinel once the master or\nslave has been chosen\n\nthe ``DisconnectionSentinel`` class also filters slaves a little more\nintelligently than the base ``Sentinel`` class does. In addition to\ninsuring slaves are not ``sdown`` or ``odown`` it makes sure the slaves\n``master-link-status`` is 'ok'\n\n``TwiceRedis`` randomizes the sentinel list so each ``TwiceRedis``\nobject will be connecting to a random sentinel in the list instead of\nthem all connecting to the first one (for as long as it works).\nthis shuffling is probably a bit superfluous used in conjunction with\n``DisconnectingSentinel``, but at worst will reduce the load on the\nfirst sentinel in the ``sentinels`` list\n\n``TwiceRedis`` also utilizes a subclass of ``StrictRedis`` called\n``DisconnectRedis`` that adds a ``disconnect()`` function to all the clients\nmaking it easier to manage individual connections to the redis services\n\n\n~~~~~\nusage\n~~~~~\n.. code:: python\n\n from twiceredis import TwiceRedis\n sentinels = [('10.10.10.10', 26379),\n ('10.10.10.11', 26379),\n ('10.10.10.12', 26379)]\n tr = TwiceRedis('master01', sentinels, 't\u00f6tes_passowrd')\n x = tr.slave.get('superkey')\n tr.master.set('je mange', 'huehue')\n x = tr.read.get('nous mangeons')\n tr.write.del('superkey')\n\npipelines work great too, you just have decide whether you need to write\nduring one or not, if write is needed, use ``tr.master``, else use ``tr.slave``\n\n.. code:: python\n\n with tr.master.pipeline() as wpipe:\n wpipe.set('turle', 'power')\n wpipe.set('tr3buchet', 't\u00f6tes')\n wpipe.execute()\n\nto connect, get a key, and then disconnect to reduce active connections\n\n.. code:: python\n\n x = tr.slave.get('some key')\n tr.slave.disconnect()\n\nand afterward reconnection will happen seamlessly as needed \\o/\nand chances are you'll hit a different slave\n\n.. code:: python\n\n x = tr.slave.get('some other key')\n\nor if you want to disconnect both ``tr.master`` and ``tr.slave``,\n``tr.disconnect()`` can be used. it calls ``disconnect()`` on both\nthe slave and master clients:\n\n.. code:: python\n\n x = tr.slave.get('some key')\n tr.master.publish('topic', x)\n tr.disconnect()\n\n # ... and later on reconnect seamlessly\n tr.master.set('some key', 'le totes!')\n x = tr.slave.get('some_key')\n\nas far as tuning goes, check out docstring in the definition of ``TwiceRedis`` in `the source `_. the default arguments to ``pool_kwargs`` and ``sentinel_kwargs`` are defined to make it easy to alter the specific parameters to your needs. it's mostly timeouts and tcp keepalive stuff, but every environment is different, so the defaults which work in mine may not work in yours. here's an example of tweaking:\n\n.. code:: python\n\n from twiceredis import TwiceRedis\n sentinels = [('10.10.10.10', 26379),\n ('10.10.10.11', 26379),\n ('10.10.10.12', 26379)]\n pool_kwargs = TwiceRedis.DEFAULT_POOL_KWARGS\n pool_kwargs['tcp_keepalive'] = False\n sentinel_kwargs = TwiceRedis.DEFAULT_SENTINEL_KWARGS\n sentinel_kwargs['min_other_sentinels'] = 2\n tr = TwiceRedis('master01', sentinels, 't\u00f6tes_passowrd',\n pool_kwargs=pool_kwargs, sentinel_kwargs=sentinel_kwargs)\n\n========\nListener\n========\nTwiceRedis based crazy durable message listener with persistent messages and in flight messages stored\n\ncreated because I was trying to use redis pubsub but was being disconnected by firewalls and losing messages. trying to handle whether messages are subscribed to from the publishing side was really painful and full of fail. ``Listener`` allows you to reliably listen for messages lpushed to any list. when a message is received, and in one transaction only, the message will be moved to a processing list. only after the message is handled will it be removed from the processing list. ``Listener`` can listen indefinitely and handle any and all connection failures or master failovers that might happen, passive firewall drops be damned.\n\n\n~~~~~\nusage\n~~~~~\n.. code:: python\n\n # on the listener side of things\n from twiceredis import TwiceRedis\n from twiceredis import Listener\n sentinels = [('10.10.10.10', 26379),\n ('10.10.10.11', 26379),\n ('10.10.10.12', 26379)]\n tr = TwiceRedis('master01', sentinels, 't\u00f6tes_passowrd')\n l = Listener(tr, 'message_list')\n l.listen() # <--- blocks and logs all messages that comes through\n\n # on the publisher side of things\n redis_client.lpush('message_list', 'incredibly important message')\n\nand that's it. it's easy to use. if you need a little more customization try using your own handler. I recommend always returning ``message`` from the handler to it works well with ``get_message()`` which returns the result of the handler whether it is your custom handler or the built in default handler which logs the ``message`` and then returns it.\n\n.. code:: python\n\n # again on the listener side of things\n def f(msg):\n do_thing(msg)\n print msg\n return msg\n\n l = Listener(tr, 'message_list', handler=f)\n l.listen() # <--- blocks and calls f(msg) for each msg that comes through\n\nif blocking isn't your thing, that's cool too, check out ``get_message()``. this example using the default handler will log the ``message`` and then return it for you to use however you wish. like the previous example, you may define your own handler and ignore or do whatever with the result of ``get_message()``\n\n.. code:: python\n\n # always with the listener side of things\n l = Listener(tr, 'message_list')\n while some_loop_construct_is_true:\n msg = l.get_message() # <--- does not block, returns None immediately if there is no message\n # do whatever with msg\n\nyou can manually handle messages with ``get_message()`` as well. the default handler is still called but it only logs and returns the message so you can handle it however you wish.\n\n.. code:: python\n\n # always with the listener side of things\n l = Listener(tr, 'message_list')\n while some_loop_construct_is_true:\n some_handler(l.get_message())\n # do other things in your loop\n\n``read_time`` is how long the ``listen()`` function will block per iteration when it hasn't received a message. it really doesn't matter what this value is as long as it is lower than the ``socket_timeout`` configured for the ``TwiceRedis`` object you pass to ``Listener`` on instantiation. if it is greater than ``socket_timeout`` there will be an exception raised each iteration, which is handled, but it's inefficient. I decided to implement a ``read_time`` pseudo timeout so the standard loop doesn't need to raise exceptions and it prevents getting stuck in a never ending listen if the socket hangs for whatever reason. NOTE!! ``read_time`` has nothing to do with the rate messages are handled. the loop will iterate as quickly as possible while it is receiving messages.\n\n``processing_suffix`` is added to the event list name to build the list key that is used to store the in flight messages until handling is finished and can be changed to any string you like.\n\nas far as exceptions or redis connection handling goes, if you start a ``listen()`` you can kill redis or do whatever, it can be down for a week, but as soon as it comes back up, ``Listener`` will pick up right where it left off as if nothing happened. each iteration will reuse or attempt to create a connection which relies on the sentinel backed nature of ``TwiceRedis`` to reconnect to the proper master (even if it changes due to failover or maintenance etc). it's built to be crazy durable.\n\n\n=======\ninstall\n=======\n``pip install twiceredis`` or clone the repo and ``python setup.py install``", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/tr3buchet/twiceredis", "keywords": "redis", "license": "Apache Software License", "maintainer": null, "maintainer_email": null, "name": "twiceredis", "package_url": "https://pypi.org/project/twiceredis/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/twiceredis/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/tr3buchet/twiceredis" }, "release_url": "https://pypi.org/project/twiceredis/2.0.0/", "requires_dist": null, "requires_python": null, "summary": "sentinel pool backed read and write redis client", "version": "2.0.0" }, "last_serial": 2021200, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "421450e05ad1a3ac8d2f357735de2029", "sha256": "b343cf6994e657ec77544f870871e28c692795b6f95c912455916258db08ef73" }, "downloads": -1, "filename": "twiceredis-1.0.0.tar.gz", "has_sig": false, "md5_digest": "421450e05ad1a3ac8d2f357735de2029", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6832, "upload_time": "2015-04-21T23:08:01", "url": "https://files.pythonhosted.org/packages/97/a8/b04858ba4e3e25c3ae534d8e233367d5e92ed9c16635ce044c5ce09dfc96/twiceredis-1.0.0.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "9c09e4097dfaddd14357d719acbadf51", "sha256": "87a9b355851513a76ee73a34562052165d615ccee443fa9ae5f0a0f87989a9b4" }, "downloads": -1, "filename": "twiceredis-1.0.2.tar.gz", "has_sig": false, "md5_digest": "9c09e4097dfaddd14357d719acbadf51", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7154, "upload_time": "2015-07-24T19:31:13", "url": "https://files.pythonhosted.org/packages/09/ab/0cf0359c93ed1f0f30bbcec1582df576c54387d14bf91b6549c7a8c89b70/twiceredis-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "f078f928b0260467b685d86e15c927cd", "sha256": "1ea3345f784b780411a797bdac8a5648280c0a436957260b78ff16233a7ca17f" }, "downloads": -1, "filename": "twiceredis-1.0.3.tar.gz", "has_sig": false, "md5_digest": "f078f928b0260467b685d86e15c927cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7166, "upload_time": "2015-07-24T20:17:56", "url": "https://files.pythonhosted.org/packages/36/75/b9f895c9f8207d68b3c9d176c0bdc301a4c1f38430f9ddf70b472970c638/twiceredis-1.0.3.tar.gz" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "f7056ab7607d5d5b6e68542754edfc36", "sha256": "8c7eda5f25756cd7311e650053ba8e46ca4feb03a71a8cf5ce70e74b75489381" }, "downloads": -1, "filename": "twiceredis-1.0.4.tar.gz", "has_sig": false, "md5_digest": "f7056ab7607d5d5b6e68542754edfc36", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7181, "upload_time": "2015-07-27T22:28:38", "url": "https://files.pythonhosted.org/packages/4b/28/8182e4b348c1dc13c6625bca4620a481221e509e6c14cb877384d43904e5/twiceredis-1.0.4.tar.gz" } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "1e70bc5c3f47d8f3a5d535cbaba4789f", "sha256": "8c4aa44d3b83dc9bcae516b32319754d51957e7edafe3a1f114b267b15ac396f" }, "downloads": -1, "filename": "twiceredis-1.0.5.tar.gz", "has_sig": false, "md5_digest": "1e70bc5c3f47d8f3a5d535cbaba4789f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7505, "upload_time": "2015-07-29T23:33:38", "url": "https://files.pythonhosted.org/packages/ab/ae/1db26f04acddc912705f82692ce18e144eb880eee85a2d92c3ebc4244f0b/twiceredis-1.0.5.tar.gz" } ], "1.0.6": [ { "comment_text": "", "digests": { "md5": "31eebb395f52f65c7155448dc232d93e", "sha256": "0241bd2f40ff831d2a854ba3fe6481ebbd15bade6c0d1f38900d3e07e5d42886" }, "downloads": -1, "filename": "twiceredis-1.0.6.tar.gz", "has_sig": false, "md5_digest": "31eebb395f52f65c7155448dc232d93e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7507, "upload_time": "2015-07-31T04:11:36", "url": "https://files.pythonhosted.org/packages/d6/71/9e54d5bce040c297969f6b612d8e4279c0a330550e49f91bb1c380e59309/twiceredis-1.0.6.tar.gz" } ], "1.0.7": [ { "comment_text": "", "digests": { "md5": "7b3b9770da1bca61f9e424a84c6d27d3", "sha256": "8608258c944ecc696de120a1f71cbdf74ca0db9640e2b2a80659655bce3fe7cd" }, "downloads": -1, "filename": "twiceredis-1.0.7.tar.gz", "has_sig": false, "md5_digest": "7b3b9770da1bca61f9e424a84c6d27d3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7695, "upload_time": "2016-02-06T00:07:30", "url": "https://files.pythonhosted.org/packages/8b/36/c74e7fa76e8a34c986207f14030c397bb028fc7218217433dfbe8cd3def6/twiceredis-1.0.7.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "ca2666a8b0e895963eb51e523cbe1f83", "sha256": "62d6c5274d9639fce75aa1abe06922450b8bfc5405532c5fd69285ee746ac951" }, "downloads": -1, "filename": "twiceredis-2.0.0.tar.gz", "has_sig": false, "md5_digest": "ca2666a8b0e895963eb51e523cbe1f83", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11751, "upload_time": "2016-03-22T19:09:10", "url": "https://files.pythonhosted.org/packages/ed/71/cdaafedec74d812f8023246365b3e8023c10e703f85c5672bad89c747aa0/twiceredis-2.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ca2666a8b0e895963eb51e523cbe1f83", "sha256": "62d6c5274d9639fce75aa1abe06922450b8bfc5405532c5fd69285ee746ac951" }, "downloads": -1, "filename": "twiceredis-2.0.0.tar.gz", "has_sig": false, "md5_digest": "ca2666a8b0e895963eb51e523cbe1f83", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11751, "upload_time": "2016-03-22T19:09:10", "url": "https://files.pythonhosted.org/packages/ed/71/cdaafedec74d812f8023246365b3e8023c10e703f85c5672bad89c747aa0/twiceredis-2.0.0.tar.gz" } ] }