{ "info": { "author": "Aurelien Campeas", "author_email": "aurelien.campeas@pythonian.fr", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Database", "Topic :: Software Development :: Object Brokering", "Topic :: System :: Distributed Computing" ], "description": "REWORK\n========\n\nThis is a python task scheduling and execution tool, which needs only\npython and Postgres to work (using sqlalchemy).\n\n\n# Principles\n\nRework might interest people who:\n\n* want Postgres (and *only Postgres*) as a Task Queue Manager,\n Input/Output store and task log store\n\n* have Python long-running tasks to run, with the ability to\n preemptively kill tasks\n\n* want a tiny, self-contained tool with great functional test\n abilities.\n\nThe most common python library for such things is Celery. If you don't\nmind depending on RabbitMQ and the Celery API and feature set, Celery\nis for you. It is mature, probably well-tested, and largely used.\n\n\n# Basic usage\n\n## Setting up a database\n\nYou need a postgresql database. Rework will install its tables into\nits own namespace schema, so you can use either a dedicated database\nor an exising one, with little risk of conflict.\n\nIf you don't already have a database, create a fresh one with:\n\n```shell\ncreatedb jobstore\n```\n\nTo install rework inside:\n\n```shell\nrework init-db postgres://babar:password@localhost:5432/jobstore\n```\n\n\n## Declaring and scheduling a task\n\nAll the features are covered in the [test suite][1], which can\nhenceforth be regarded as a reasonnable source of\ndocumentation. However here's a simple example:\n\n```python\nfrom time import sleep\nfrom rework import api\nfrom sqlalchemy import create_engine\n\n\n@api.task\ndef my_first_task(task):\n with task.capturelogs(std=True):\n print('I am running')\n somevalue = task.input * 2\n task.save_output(somevalue)\n print('I am done')\n\n\ndef main(dburi):\n engine = create_engine(dburi)\n\n # record the decorated tasks\n @api.freeze_operations(engine)\n\n # now, schedule tasks\n t1 = api.schedule(engine, 'my_first_task', 'hello')\n t2 = api.schedule(engine, 'my_first_task', 100)\n\n # wait til they are completed\n t1.join()\n t2.join()\n\n assert t1.output == 'hellohello'\n assert t2.output == 200\n\n\nif __name__ == '__main__':\n main('postgres://babar:password@localhost:5432/jobstore')\n```\n\nIf you put this into a `test_rework.py` module and type `python\ntest_rework.py` it should *hang* forever. Hold on, what's missing ?\n\nOn another terminal, one needs to *start* the workers that will\nexecute the tasks. Do as follows:\n\n```shell\nrework monitor postgres://babar:password@localhost:5432/jobstore\n```\n\nThen, the script will quickly terminate, as both tasks have been\nexecuted.\n\n\n# API\n\nThe `api` module exposes most if what is needed. The `task` module\nand task objects provide the rest.\n\n\n## `api` module\n\nThree functions are provided: the `task` decorator, the\n`freeze_operations` and `schedule` functions.\n\nDefining tasks is done using the `task` decorator:\n\n```python\nfrom rework.api import task\n\n@task\ndef my_task(task):\n pass\n```\n\nTo make the tasks available for use, they must be recorded within\nthe database referential. We use `freeze_operations` for this:\n\n```python\nfrom sqlalchemy import create_engine\nfrom rework.api import freeze_operations\n\nengine = create_engine('postgres://babar:password@localhost:5432/jobstore')\napi.freeze_operations(engine)\n```\n\nFinally, one can schedule tasks as such:\n\n```python\nfrom sqlalchemy import create_engine\nfrom rework.api import schedule\n\nengine = create_engine('postgres://babar:password@localhost:5432/jobstore')\n\ntask = api.schedule(engine, 'my_task', 42)\n```\n\nThe `schedule` function wants these mandatory parameters:\n\n* engine: sqlalchemy engine\n\n* task name: string\n\n* task input: any python picklable object\n\n\nIt also accepts two more options:\n\n* hostid: an host identifier (e.g. '192.168.1.1')\n\n* metadata: a json-serializable dictionary (e.g. {'user': 'Babar'})\n\n\n## Task objects\n\nTask objects can be obtained from the `schedule` api call (as seen in the\nprevious example) or through the `task` module.\n\n```python\nfrom task import Task\n\ntask = task.by_id(42)\n```\n\nThe task object provides:\n\n* `.state` attribute to describe the task state (amongst: `queued`,\n `running`, `aborting`, `aborted`, `failed`, `done`)\n\n* `.join()` method to wait synchronously for the task completion\n\n* `.capturelogs(sync=True, level=logging.NOTSET, std=False)` method to\n record matching logs into the db (`sync` controls whether the logs\n are written synchronously, `level` specifies the capture level,\n `std` permits to also record prints as logs)\n\n* `.input` attribute to get the task input (yields any object)\n\n* `.save_output()` method to store any object\n\n* `.abort()` method to preemptively stop the task\n\n* `.log(fromid=None)` method to retrieve the task logs (all or from a\n given log id)\n\n\n# Command line\n\n## Operations\n\nIf you read the previous chapter, you already know the `init-db` and\n`monitor` commands.\n\nThe `rework` command, if typed without subcommand, shows its usage:\n\n```shell\n$ rework\nUsage: rework [OPTIONS] COMMAND [ARGS]...\n\nOptions:\n --help Show this message and exit.\n\nCommands:\n abort-task\n monitor\n init-db\n kill-worker\n list-operations\n list-tasks\n list-workers\n log-task\n new-worker\n shutdown-worker\n vacuum\n```\n\nOf those commands, `new-worker` is for purely internal purposes, and\nunless you know what you're doing, should should never use it.\n\nOne can list the tasks:\n\n```shell\nrework list-tasks postgres://babar:password@localhost:5432/jobstore\n1 my_first_task done [2017-09-13 17:08:48.306970+02]\n2 my_first_task done [2017-09-13 17:08:48.416770+02]\n```\n\nIt is possible to monitor the output of a given task:\n\n```shell\n$ rework log-task postgres://babar:password@localhost:5432/jobstore 1\nstdout:INFO: 2017-09-13 17:08:49: I am running\nstdout:INFO: 2017-09-13 17:08:49: I am done\n```\n\nThe last argument `1` is the task identifier as was shown by the\n`list-tasks` command.\n\nNotice how we capture the standard output (print calls) using the\n`task.capturelogs` context manager. This is completely optional of\ncourse but quite handy. The line shown above actually capture\n*standard output*, *standard error* and *all logs*. It accepts a\n`level` parameter, like e.g. `capturelogs(level=logging.INFO)`.\n\nLastly, `list-workers` will show the currently running workers:\n\n```shell\n$ rework list-workers postgres://babar:password@localhost:5432/jobstore\n1 4889896@192.168.1.2 30 Mb [running]\n2 4889748@192.168.1.2 30 Mb [running]\n```\n\n[1]: https://bitbucket.org/pythonian/rework/src/default/test/test_monitor.py?fileviewer=file-view-default\n\n\n## Extensions\n\nIt is possible to augment the `rework` command with new subcommands (or\naugment, modify existing commands).\n\nAny program doing so must define a new command and declare a setup\ntools entry point named `rework:subcommand` as in e.g.:\n\n```python\n\n entry_points={'rework.subcommands': [\n 'view=rework_ui.cli:view'\n ]}\n```\n\nFor instance, the [rework_ui][reworkui] python package provides such a\n`view` subcommand to launch a monitoring webapp for a given rework job\nstore.\n\n[reworkui]: https://bitbucket.org/pythonian/rework_ui\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://bitbucket.org/pythonian/rework", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "rework", "package_url": "https://pypi.org/project/rework/", "platform": "", "project_url": "https://pypi.org/project/rework/", "project_urls": { "Homepage": "https://bitbucket.org/pythonian/rework" }, "release_url": "https://pypi.org/project/rework/0.9.2/", "requires_dist": [ "psutil", "colorama", "sqlalchemy", "sqlhelp", "psycopg2-binary", "pystuck", "click", "tzlocal (==1.5.1)", "inireader" ], "requires_python": "", "summary": "A database-oriented distributed task dispatcher", "version": "0.9.2" }, "last_serial": 5855829, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "d7ef3d37cf882d9cc6648169237096a3", "sha256": "bd59759e880eeba511cd16254dd19051330ee270b15e7d5bf4e7c2b764d53224" }, "downloads": -1, "filename": "rework-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d7ef3d37cf882d9cc6648169237096a3", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 12875, "upload_time": "2017-11-09T17:19:42", "url": "https://files.pythonhosted.org/packages/4b/1f/e4a9ec9cdacf06300c33649c607d8066293334120dce83f97e4676271213/rework-0.1.0-py2.py3-none-any.whl" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "ea718673ecd84c39c56bc15c58562d7a", "sha256": "439b19a2470be129a942799a217a28cbf5fa4f23d9414106dc618e0c604c7e8e" }, "downloads": -1, "filename": "rework-0.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ea718673ecd84c39c56bc15c58562d7a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13897, "upload_time": "2018-01-25T09:31:50", "url": "https://files.pythonhosted.org/packages/86/08/7920eb3eae7f2293f24d353b647c3721f172f28efd388fed40ae185f5959/rework-0.2.0-py2.py3-none-any.whl" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "d18506fa3f12aff091484e1a589c8f09", "sha256": "a789333e30983e8cb3b8a4a687f15d62be010540b6bbe37bac8f063a574d8275" }, "downloads": -1, "filename": "rework-0.3.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d18506fa3f12aff091484e1a589c8f09", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14261, "upload_time": "2018-04-23T09:20:18", "url": "https://files.pythonhosted.org/packages/d8/46/86e5af8cd9a2d725484a15971ec3db437585d178d2bca838c90e972e02ec/rework-0.3.0-py2.py3-none-any.whl" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "d03e01a72cb75772bb83e8753ab31414", "sha256": "b45a4d9c7899881defde4383a61ccd707e23d041e61e4a4e802b917b2ebeae08" }, "downloads": -1, "filename": "rework-0.4.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d03e01a72cb75772bb83e8753ab31414", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14252, "upload_time": "2018-06-18T13:55:11", "url": "https://files.pythonhosted.org/packages/a6/b5/c764008748ab106440a67425ab6f61753ac6b1d68101e85da97f9a5a8fd4/rework-0.4.0-py2.py3-none-any.whl" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "d852c23fa152824d02778cd869007899", "sha256": "9b881dd61198246127089898e53150e02ad934f8a1a9cf570560fb4e3a38df53" }, "downloads": -1, "filename": "rework-0.6.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d852c23fa152824d02778cd869007899", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15517, "upload_time": "2018-10-05T12:16:24", "url": "https://files.pythonhosted.org/packages/1f/fd/32167a51c7b1da67585087dbaa76cf9a00427e400951d5269d478f26b060/rework-0.6.0-py2.py3-none-any.whl" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "f7e6ed9caee36acbea67c06eaf1b37a5", "sha256": "0ea75a7c5e2f3e05842ea867ed8c29b014898eece1bce9b9def436dd6b4ae115" }, "downloads": -1, "filename": "rework-0.7.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f7e6ed9caee36acbea67c06eaf1b37a5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15838, "upload_time": "2018-11-09T10:56:18", "url": "https://files.pythonhosted.org/packages/b0/ef/2f98b418909b1b6b89d025628ba09583979dbcd3b3a109ce8a67115c9765/rework-0.7.0-py2.py3-none-any.whl" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "4f3f576a4332ad2bbd7027b769ca697f", "sha256": "7991f25ec46f36b8cce2d6f6546560313a206d781760713463019557e6900056" }, "downloads": -1, "filename": "rework-0.8.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4f3f576a4332ad2bbd7027b769ca697f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18818, "upload_time": "2018-12-21T14:56:01", "url": "https://files.pythonhosted.org/packages/78/29/16d88b6caa18310aa97d0ef9c4fca133a90e60c90f617fc102420c3d7f67/rework-0.8.0-py2.py3-none-any.whl" } ], "0.9.0": [ { "comment_text": "", "digests": { "md5": "e86a70187899a15d2725d8f6c9184b33", "sha256": "6e9c3c8b22b0c1387ccce91df0599e7210ccb3bfc43ae0a1dfcd00fc3ea8ab2b" }, "downloads": -1, "filename": "rework-0.9.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e86a70187899a15d2725d8f6c9184b33", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18596, "upload_time": "2019-07-16T15:01:23", "url": "https://files.pythonhosted.org/packages/36/90/cfcc3274aee22db74b477bf60e097ee1f687bb113d46f593ff236fe0feb4/rework-0.9.0-py2.py3-none-any.whl" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "0d1419e307b526a180664a116c05b7f3", "sha256": "b0ac5076ce9a02f99e0c15c91f436d65df782710ad43f0a31faa60734255b90c" }, "downloads": -1, "filename": "rework-0.9.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0d1419e307b526a180664a116c05b7f3", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22252, "upload_time": "2019-09-04T16:59:32", "url": "https://files.pythonhosted.org/packages/21/da/4c35010674ffb51507dbd3a036deb1d6a6016a19f61e2524ba6ca9506a4b/rework-0.9.1-py2.py3-none-any.whl" } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "ccff28ab2c9e98a7ce52a25ac8ed0e4a", "sha256": "bde454235c9ecae8da91df34e2fe301731926fcd6f62a3d9b216181d7cc437a8" }, "downloads": -1, "filename": "rework-0.9.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ccff28ab2c9e98a7ce52a25ac8ed0e4a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22249, "upload_time": "2019-09-19T12:09:01", "url": "https://files.pythonhosted.org/packages/eb/5f/3da6f6dd5a585e7367aca6210d59baa2b7386d72ad70110e461d39911c86/rework-0.9.2-py2.py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ccff28ab2c9e98a7ce52a25ac8ed0e4a", "sha256": "bde454235c9ecae8da91df34e2fe301731926fcd6f62a3d9b216181d7cc437a8" }, "downloads": -1, "filename": "rework-0.9.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ccff28ab2c9e98a7ce52a25ac8ed0e4a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22249, "upload_time": "2019-09-19T12:09:01", "url": "https://files.pythonhosted.org/packages/eb/5f/3da6f6dd5a585e7367aca6210d59baa2b7386d72ad70110e461d39911c86/rework-0.9.2-py2.py3-none-any.whl" } ] }