{ "info": { "author": "Florian Plattner", "author_email": "me@florianplattner.de", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Other Environment", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "saga_py\n=======\n\nCreate a series of dependent actions and roll everything back when one of them fails.\n\n\nInstall\n-------\n\n.. code-block:: bash\n\n $ pip install saga_py\n\n\nUsage\n-----\n\n\nSimple example\n^^^^^^^^^^^^^^\n\n.. code-block:: python\n\n from saga import SagaBuilder\n\n counter1 = 0\n counter2 = 0\n\n def incr_counter1(amount):\n global counter1\n counter1 += amount\n\n def incr_counter2(amount):\n global counter2\n counter2 += amount\n\n def decr_counter1(amount):\n global counter1\n counter1 -= amount\n\n def decr_counter2(amount):\n global counter2\n counter2 -= amount\n\n SagaBuilder \\\n .create() \\\n .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \\\n .action(lambda: incr_counter2(1), lambda: decr_counter2(1)) \\\n .action() \\\n .build() \\\n .execute()\n\n # if every action succeeds, the effects of all actions are applied\n print(counter1) # 15\n print(counter2) # 1\n\n\nAn action fails example\n^^^^^^^^^^^^^^^^^^^^^^^\n\nIf one action fails, the compensations for all already executed actions are run and a SagaError is raised that wraps\nall Exceptions encountered during the run.\n\n.. code-block:: python\n\n from saga import SagaBuilder, SagaError\n\n counter1 = 0\n counter2 = 0\n\n def incr_counter1(amount):\n global counter1\n counter1 += amount\n\n def incr_counter2(amount):\n global counter2\n counter2 += amount\n raise BaseException('some error happened')\n\n def decr_counter1(amount):\n global counter1\n counter1 -= amount\n\n def decr_counter2(amount):\n global counter2\n counter2 -= amount\n\n try:\n SagaBuilder \\\n .create() \\\n .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \\\n .action(lambda: incr_counter2(1), lambda: decr_counter2(1)) \\\n .action() \\\n .build() \\\n .execute()\n except SagaError as e:\n print(e) # wraps the BaseException('some error happened')\n\n print(counter1) # 0\n print(counter2) # 0\n\n\nAn action and a compensation fail example\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nSince the compensation for action2 fails, the compensation effect is undefined from the framework's perspective,\nall other compensations are run regardless.\n\n.. code-block:: python\n\n from saga import SagaBuilder, SagaError\n\n counter1 = 0\n counter2 = 0\n\n def incr_counter1(amount):\n global counter1\n counter1 += amount\n\n def incr_counter2(amount):\n global counter2\n counter2 += amount\n raise BaseException('some error happened')\n\n def decr_counter1(amount):\n global counter1\n counter1 -= amount\n\n def decr_counter2(amount):\n global counter2\n raise BaseException('compensation also fails')\n\n try:\n SagaBuilder \\\n .create() \\\n .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \\\n .action(lambda: incr_counter2(1), lambda: decr_counter2(1)) \\\n .action() \\\n .build() \\\n .execute()\n except SagaError as e:\n print(e) #\n\n print(counter1) # 0\n print(counter2) # 1\n\n\nPassing values from one action to the next\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nAn action can return a dict of return values.\nThe dict is then passed as keyword arguments to the next action and it's corresponding compensation.\nNo values can be passed between compensations.\n\n.. code-block:: python\n\n from saga import SagaBuilder, SagaError\n\n counter1 = 0\n counter2 = 0\n\n def incr_counter1(amount):\n global counter1\n counter1 += amount\n return {'counter1_value': counter1}\n\n def incr_counter2(counter1_value):\n global counter2\n counter2 += amount\n\n def decr_counter1(amount):\n global counter1\n counter1 -= amount\n\n def decr_counter2(counter1_value):\n global counter2\n counter2 -= amount\n\n SagaBuilder \\\n .create() \\\n .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \\\n .action(incr_counter2, decr_counter2) \\\n .action() \\\n .build() \\\n .execute()\n\n print(counter1) # 15\n print(counter2) # 15\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/flowpl/dbit", "keywords": "saga\ndependent actions\nrollback\ncompensate\ndistributed transaction", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "saga_py", "package_url": "https://pypi.org/project/saga_py/", "platform": "", "project_url": "https://pypi.org/project/saga_py/", "project_urls": { "Homepage": "https://github.com/flowpl/dbit" }, "release_url": "https://pypi.org/project/saga_py/1.1.0/", "requires_dist": null, "requires_python": "", "summary": "create a series of dependent actions and roll everything back when one of them fails", "version": "1.1.0" }, "last_serial": 3307003, "releases": { "0.0.1.dev9": [ { "comment_text": "", "digests": { "md5": "0d36068fcb28ca103270c263a8c215c2", "sha256": "6c6434fd10ce79078d92516cce09423cbdf85842fa53c80e107a600184355434" }, "downloads": -1, "filename": "saga_py-0.0.1.dev9.tar.gz", "has_sig": false, "md5_digest": "0d36068fcb28ca103270c263a8c215c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5830, "upload_time": "2017-11-05T12:08:54", "url": "https://files.pythonhosted.org/packages/1b/cf/436326a00a7c5d46393325de420d4793d9fa7320cac1f8cf54b554edbf0e/saga_py-0.0.1.dev9.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "28e0699800ad0bd7775653e59c781552", "sha256": "6dd0e5fd622fcce96646ad272aafa9006cd47d1d0d4ab12b63a5bf2f900f455b" }, "downloads": -1, "filename": "saga_py-1.0.0.tar.gz", "has_sig": false, "md5_digest": "28e0699800ad0bd7775653e59c781552", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5838, "upload_time": "2017-11-05T12:09:34", "url": "https://files.pythonhosted.org/packages/fa/4b/4c2c90280bbc9eb2be595fc64593e6769fd8e6eb08c97d9cf1fc7c87c6d9/saga_py-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "dfaef4d93fce81576c5ac40d245c652f", "sha256": "b3c679310c95bd1288cec9b2d07c0c4f28ac2b748d4c2dc7da38f437f5a0850e" }, "downloads": -1, "filename": "saga_py-1.1.0.tar.gz", "has_sig": false, "md5_digest": "dfaef4d93fce81576c5ac40d245c652f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5770, "upload_time": "2017-11-05T13:01:01", "url": "https://files.pythonhosted.org/packages/32/cf/e9e4003be1bb7386882e1427b7c79c599ffc80ca84ecfbfd76d8efc1e067/saga_py-1.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "dfaef4d93fce81576c5ac40d245c652f", "sha256": "b3c679310c95bd1288cec9b2d07c0c4f28ac2b748d4c2dc7da38f437f5a0850e" }, "downloads": -1, "filename": "saga_py-1.1.0.tar.gz", "has_sig": false, "md5_digest": "dfaef4d93fce81576c5ac40d245c652f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5770, "upload_time": "2017-11-05T13:01:01", "url": "https://files.pythonhosted.org/packages/32/cf/e9e4003be1bb7386882e1427b7c79c599ffc80ca84ecfbfd76d8efc1e067/saga_py-1.1.0.tar.gz" } ] }