{ "info": { "author": "Jacob Svensson", "author_email": "jacob@nephics.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Topic :: System :: Distributed Computing", "Topic :: System :: Networking", "Topic :: Utilities" ], "description": "# Linger\n\n*-- Message queue and pub-sub service with HTTP API*\n\n## About\n\nThe [linger](https://github.com/nephics/linger) package provides the Linger server, which is a message queue and pub-sub service with a REST HTTP API.\n\nThe message queue distributes messages in channels from publishers to consumers. The message queue can be used in situations where a work queue is needed, e.g., for running time-consuming tasks asynchronously.\n\nThe pub-sub (publish-subscribe) service distribute messages from publishers to subscribers (both fan-in and fan-out). It can be used in situations where message notification is needed, e.g., for delivering status updates, or change notifications.\n\nThe HTTP API server is implemented in Python 3 using a non-blocking, single-threaded [Tornado web server](http://www.tornadoweb.org/).\n\n## Message queue\n\nLinger provides a message queue where messages are added by producers, and made available to consumers.\n\nProducers may add messages to any named channel, which are created on-demand. \n\nConsumers may subscribe and consume messages from any named channel, but is limited to retrieving a message from one channel per request.\n\nMessages are delivered to consumers at least once, and they may be re-delivered, if the consumer doesn't delete the delivered message.\n\nMessages can be in one of two states: ready or hidden. Where 'ready' messages are those available for delivery to consumers, and hidden messages are not made available to consumers. A message is hidden during a visibility timeout, after being delivered to a consumer.\n\n### The life of a message in the queue\n\n1. A producer adds a new message to a named channel (the queue).\n2. A consumer requests a message from the channel, the message is delivered to the consumer.\n3. Once the message has been delivered, it will be hidden and not delivered again until the visibility timeout has passed. (This keeps multiple consumers from requesting the same message.)\n4. When the consumer has successfully processed the message, they delete the message from the channel.\n\nA message can be assigned a priority which is different from the default, so messages are delivered in a non-sequential order (an order not based on the time messages are added to the queue).\n\nA retention (linger) period may be set on a message, to limit the lifetime of the message in the channel. This can be useful when the channel (for some reason) has no consumers, and you want to limit the age of messages in the channel.\n\n## Pub-sub service\n\nLinger provides pub-sub functionality where messages are posted by publishers, and made available to subscribers.\n\nA message is published on a named topic, and is distributed by Linger to one or more subscribed channels. Each channel may have one or more subscribers that consume the messages of that channel.\n\n### The life of a published message\n\n1. A publisher post a new message to a named topic.\n2. The message is distributed to channels subscribed to the topic.\n3. A subscriber requests a message from a channel, the message is returned.\n4. Once the message has been delivered, it will not be delivered again until the visibility timeout has passed.\n5. When the publisher has successfully received a message, they delete the message from the channel.\n\nNotice that step 3 to 5 here is the same as step 2 to 4 in \"the life of a message in the queue\". In a standard pub-sub model there is only one subscriber per channel, but Linger allows for multiple subscribers, which consume the messages delivered to the channel. Hence, multiple subscribers to same channel will not see the same messages.\n\nWhen subscribing a channel to a topic, you can set the message priority, retention (linger) period, etc., which will be applied to messages on that topic delivered to the channel.\n\n## Getting started\n\n### Install\n\nInstall the `linger` script in `/usr/local/bin` (on Linux and OS X) with the following pip command:\n\n pip install https://github.com/nephics/linger/archive/master.zip\n\nThis will also ensure that the dependency package `tornado` is installed.\n\n### Run\n\nStart a Linger server by running the script:\n\n linger\n\nfrom the command line, or use *systemd* or a process-daemon tool like [Supervisor](http://supervisord.org).\n\nThe default port is 8989. This and other options can be set from the command line, or using a config file (with path specified as a command line option). Command line options can be listed using argument `--help`.\n\nBy default the database is kept in memory, but the server can store the database on disk, both to reduce memory footprint and to allow for full restore in the event of a server/process restart. Use the `--dbfile` command line option to store the database on disk.\n\nIt is also possible to define a global a high-level mark limiting the number of messages in any channel. The default is no high-level mark, this setting may be changed using the `--hlm` command line option. \n\n## Security\n\nThe HTTP API is unauthenticated, all clients have unrestricted access to the full API, but you may use a reverse proxy like [nginx](http://nginx.org) to require authentication for network access, see [HTTP Basic Auth](http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html).\n\n## Limits and performance\n\nLong-polling duration is limited to about 2 mins.\n\nMessages are by default limited to 256 KB in size, and may contain any sequences of bytes.\n\nLinger is not currently optimised with regard to memory usage, and it has not been tested for high-performance usage scenarios, such as delivering billions of messages a day. But, for most real world situations, Linger will serve you reliably.\n\n## HTTP API overview\n\nThe Linger HTTP API consists of these methods:\n\n* GET `/channels` *- list channels*\n* GET `/channels/` *- get message from channel*\n* POST `/channels/` *- add message to channel*\n* DELETE `/channels/` *- drain the channel*\n* GET `/channels//stats` *- get channel stats*\n* GET `/channels//topics` *- list topics a channel is subscribed to*\n* PUT `/channels//topics/` *- subscribe channel to a topic*\n* DELETE `/channels//topics/` *- unsubscribe channel from topic*\n* GET `/topics` *- list topics*\n* POST `/topics/` *- publish message on topic*\n* GET `/topics//channels` *- list channels subscribed to topic*\n* DELETE `/messages/` *- delete message*\n* GET `/stats` *- get server stats*\n\nWhere `` is the channel name, where messages can be added and removed. Channel names may contain characters from `a-z` `A-Z` `0-9` `_` `%` `-`. Remember to URL-encode the name when using it in requests, particularly important if the name includes space or slash.\n\nChannels are created on-demand, and are automatically destroyed when they are empty and not in use.\n\nThe `` is an integer that identifies a message (uniquely across all channels).\n\nThe API methods are described in more detailed in the following sections, with examples using [cURL](http://curl.haxx.se).\n\n## List channels\n\nThe list of current channels can be retrieved using a HTTP GET request to `/channels`. Example request:\n\n curl -X GET http://127.0.0.1:8989/channels\n\nThe server responds with HTTP status code 200, and the channel list is included in the response body, which is text encoded as JSON.\nExample response:\n\n {\"channels\": ['test']}\n\n## Add message to a channel\n\nAdd a message to a named channel using a HTTP POST request to `/channels/`. Example request:\n\n curl --data-urlencode msg='Do this and that!' \\\n http://127.0.0.1:8989/channels/test\n\nIf you set any other content-type than \"application/x-www-form-urlencoded\" and \"multipart/form-data\", the request body is the message. Example request with JSON encoded message:\n\n curl -d '{\"txt\": \"Do this and that!\"}' \\\n -H \"Content-Type: application/json\" \\\n http://127.0.0.1:8989/channels/test\n\nThe server responds with HTTP status code 202, and the message id (an integer) encoded as JSON in the response body. Example response:\n\n {\"id\": 1}\n\nYou can set the message priority, visibility timeout, max delivery attempts, and message retention limit using query parameters:\n\n priority=10 message priority, a lower number means a\n higher priority in the channel,\n default is zero\n (any integer is accepted)\n\n timeout=60 wait for 60 seconds before delivering the\n message to another client, default is\n 30 seconds\n (accepts an integer greater than zero)\n\n deliver=5 deliver the message at most 5 times before\n discarding it, default is zero, which means\n never discard the message\n (any positive integer is accepted)\n\n linger=60 keep the message for 60 seconds, before\n discarding it, default is zero, which means\n never discard the message\n (any positive integer is accepted)\n\nThe parameters can be combined in a request. Example request with JSON encoded message:\n\n curl -d '{\"txt\": \"Do this and that!\"}' \\\n -H \"Content-Type: application/json\" \\\n \"http://127.0.0.1:8989/channels/test?priority=10&timeout=60&deliver=5&linger=60\"\n\nExample request with a text message:\n\n curl --data-urlencode msg='Do this and that!' \\\n -d priority=10 -d timeout=60 -d deliver=5 \\\n -d linger=60 http://127.0.0.1:8989/channels/test\n\nIf the channel is at the high-level-mark, the message cannot be added, and the server responds with the HTTP status code 507 Insufficient Storage.\n\n## Get message from a channel\n\nGet a message from a named channel using a HTTP GET request to `/channels/`. Example request:\n\n curl -i http://127.0.0.1:8989/channels/test\n\nThe server will either reply with HTTP status code 200, and the message in the response body, or the server will hold on to the request (long-polling) until a message becomes available in the channel.\n\nThe server will automatically end a long-polling request after a couple of minutes. If there is no message available, the server replies with HTTP status code 204, and an empty response body.\n\nThe response headers with prefix `x-linger-` contains the Linger message meta data. Example:\n\n x-linger-msg-id: 1 # message ID\n x-linger-channel: test # channel name\n x-linger-priority: 10 # priority\n x-linger-timeout: 60 # visibility timeout\n x-linger-deliver: 5 # max delivery attempts\n x-linger-delivered: 1 # count of delivery attempts (including this one)\n x-linger-received: 11 # seconds since the message was received by the channel\n x-linger-linger: 0 # message linger time in the channel (before being discarded)\n x-linger-topic: some-topic # topic (if message was published to a topic)\n\nThe response content-type will be the same as specified when adding the message to the channel (default is text/plain).\n\nBy adding the `nowait` query parameter, you may prevent long-polling, and have the server send a response immediately. This implies that the server will return an empty reply, if there is no message waiting in the channel. Example request:\n\n curl http://127.0.0.1:8989/channels/test?nowait\n\n## Drain the channel\n\nDrain (discard) all messages from channel using a HTTP DELETE request to `/channels/`. Example request:\n\n curl -X DELETE http://127.0.0.1:8989/channels/test\n\nThe server responds with HTTP status code 204.\n\n\n## Get channel stats\n\nRetrieve statistics about the messages in a channel using a HTTP GET request to `/channels//stats`. Example request:\n\n curl -X GET http://127.0.0.1:8989/channels/test/stats\n\nThe server responds with HTTP status code 200, and the response body contains a JSON encoded mapping of stats about messages in the channel.\n\nExample response:\n\n {\"ready\": 2, \"hidden\": 0}\n\n\n## List topics a channel is subscribed to\n\nThe list of topics a channel is subscribed to can be retrieved using a HTTP GET request to `/channels//topics`. Example request:\n\n curl http://127.0.0.1:8989/channels/test/topics\n\nExample response:\n\n {\"topics\": [\"some-topic\"]}\n\n## Subscribe channel to a topic\n\nSubscribe a channel to a named topic using a HTTP PUT request to `/channels//topics/`. Example request:\n\n curl -X PUT http://127.0.0.1:8989/channels/test/topics/some-topic\n\nThe server responds with HTTP status code 204.\n\nIf you add query parameters, the subscription applies these parameters to all messages published to the channel on the specific topic. The possible query parameters are the same as available for when adding a message to a channel (see above). This includes message priority, visibility timeout, max delivery attempts, and message retention limit.\n\nExample request limiting the message retention to 60 seconds for all messages published to the channel on the specific topic:\n\n curl -X PUT -d linger=60 http://127.0.0.1:8989/channels/test/topics/some-topic\n\n## Unsubscribe channel from a topic\n\nUnsubscribe a channel from a named topic using a HTTP DELETE request to `/channels//topics/`. Example request:\n\n curl -X DELETE http://127.0.0.1:8989/channels/test/topics/some-topic\n\nThe server responds with HTTP status code 204.\n\n## List topics\n\nThe list of topics with subscriptions can be retrieved using a HTTP GET request to `/topics`. Example request:\n\n curl http://127.0.0.1:8989/topics\n\nThe server responds with HTTP status code 200, and the response body contains a JSON encoded list of topics. Example response:\n\n {\"topics\": [\"some-topic\"]}\n\n\n## Publish message on topic\n\nPublish a message on a name topic using a POST request to `/topics/`. Example request:\n\n curl --data-urlencode msg='Have you heard!' \\\n http://127.0.0.1:8989/topics/some-topic\n\nThe message is distributed to subscribed channels (if any). The message priority, etc., is determined by the channel subscriptions to the topic (see above).\n\nThe server responds with HTTP status code 202, and the response body contains a JSON encoded mapping of channels and message ids. Example response:\n\n {\"test\": 1}\n\n## List channels subscribed to topic\n\nThe list of channels subscribed to a named topic can be retrieved using a HTTP GET request to `/topics//channels`. Example request:\n\n curl http://127.0.0.1:8989/topics/some-topic/channels\n\nThe server responds with HTTP status code 200, and the response body contains a JSON encoded list of channels. Example response:\n\n {\"channels\": [\"test\"]}\n\n## Delete message\n\nDelete the specified message using a HTTP DELETE request to `/messages/`. Example request:\n\n curl -X DELETE http://127.0.0.1:8989/messages/1\n\nIf successful, the server responds with HTTP status code 204. If the message is not found, HTTP status code 404 is returned.\n\n## Get server stats\n\nRetrieve server statistics and runtime information using a HTTP GET request to `/stats`. Example request:\n\n curl -X GET http://127.0.0.1:8989/stats\n\nThe server responds with HTTP status code 200, and the response body contains a JSON encoded mapping of the available stats.\n\n# Support\n\nSupport for the software can be provided on a commercial basis, please see [www.nephics.com](http://www.nephics.com) for contact information.\n\n# License\n\nThe code and documentation is licensed under the Apache License v2.0, see more in the LICENSE file.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/nephics/linger", "keywords": "", "license": "http://www.apache.org/licenses/LICENSE-2.0", "maintainer": "", "maintainer_email": "", "name": "linger", "package_url": "https://pypi.org/project/linger/", "platform": "", "project_url": "https://pypi.org/project/linger/", "project_urls": { "Homepage": "https://github.com/nephics/linger" }, "release_url": "https://pypi.org/project/linger/1.0.1/", "requires_dist": [ "tornado (>=4.5.2)" ], "requires_python": "", "summary": "Message queue and pubsub service with HTTP API", "version": "1.0.1" }, "last_serial": 4529145, "releases": { "1.0.1": [ { "comment_text": "", "digests": { "md5": "2381046607355d5f0f07fa9d56fe9b93", "sha256": "465e9dffcd0ed6cacf0d477446da2fc3b8f190515427a005f6031e21d6952101" }, "downloads": -1, "filename": "linger-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "2381046607355d5f0f07fa9d56fe9b93", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14935, "upload_time": "2018-11-26T10:42:12", "url": "https://files.pythonhosted.org/packages/f9/44/764f1a9dc2c282e1139c81cbd065927b44e48bd72b66c155d0be6fc16951/linger-1.0.1-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2381046607355d5f0f07fa9d56fe9b93", "sha256": "465e9dffcd0ed6cacf0d477446da2fc3b8f190515427a005f6031e21d6952101" }, "downloads": -1, "filename": "linger-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "2381046607355d5f0f07fa9d56fe9b93", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14935, "upload_time": "2018-11-26T10:42:12", "url": "https://files.pythonhosted.org/packages/f9/44/764f1a9dc2c282e1139c81cbd065927b44e48bd72b66c155d0be6fc16951/linger-1.0.1-py3-none-any.whl" } ] }