Metadata-Version: 1.1
Name: saga_py
Version: 0.0.1.dev9
Summary: create a series of dependent actions and roll everything back when one of them fails
Home-page: https://github.com/flowpl/dbit
Author: Florian Plattner
Author-email: me@florianplattner.de
License: MIT
Description-Content-Type: UNKNOWN
Description: [![Build Status](https://travis-ci.org/flowpl/saga_py.svg?branch=master)](https://travis-ci.org/flowpl/saga_py)
        [![Coverage Status](https://coveralls.io/repos/github/flowpl/saga_py/badge.svg?branch=master)](https://coveralls.io/github/flowpl/saga_py?branch=master)
        
        saga_py
        =======
        
        Create a series of dependent actions and roll everything back when one of them fails.
        
        
        Install
        -------
        
        .. code-block:: bash
        
            $ pip install saga_py
        
        
        Usage
        -----
        
        
        Simple example
        ^^^^^^^^^^^^^^
        
        .. code-block:: python
        
            from saga import SagaBuilder
        
            counter1 = 0
            counter2 = 0
        
            def incr_counter1(amount):
                global counter1
                counter1 += amount
        
            def incr_counter2(amount):
                global counter2
                counter2 += amount
        
            def decr_counter1(amount):
                global counter1
                counter1 -= amount
        
            def decr_counter2(amount):
                global counter2
                counter2 -= amount
        
            SagaBuilder \
                .create() \
                .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \
                .action(lambda: incr_counter2(1), lambda: decr_counter2(1)) \
                .action() \
                .build() \
                .execute()
        
            # if every action succeeds, the effects of all actions are applied
            print(counter1)  # 15
            print(counter2)  # 1
        
        
        An action fails example
        ^^^^^^^^^^^^^^^^^^^^^^^
        
        If one action fails, the compensations for all already executed actions are run and a SagaError is raised that wraps
        all Exceptions encountered during the run.
        
        .. code-block:: python
        
            from saga import SagaBuilder, SagaError
        
            counter1 = 0
            counter2 = 0
        
            def incr_counter1(amount):
                global counter1
                counter1 += amount
        
            def incr_counter2(amount):
                global counter2
                counter2 += amount
                raise BaseException('some error happened')
        
            def decr_counter1(amount):
                global counter1
                counter1 -= amount
        
            def decr_counter2(amount):
                global counter2
                counter2 -= amount
        
            try:
                SagaBuilder \
                    .create() \
                    .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \
                    .action(lambda: incr_counter2(1), lambda: decr_counter2(1)) \
                    .action() \
                    .build() \
                    .execute()
            except SagaError as e:
                print(e)  # wraps the BaseException('some error happened')
        
            print(counter1)  # 0
            print(counter2)  # 0
        
        
        An action and a compensation fail example
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        
        Since the compensation for action2 fails, the compensation effect is undefined from the framework's perspective,
        all other compensations are run regardless.
        
        .. code-block:: python
        
            from saga import SagaBuilder, SagaError
        
            counter1 = 0
            counter2 = 0
        
            def incr_counter1(amount):
                global counter1
                counter1 += amount
        
            def incr_counter2(amount):
                global counter2
                counter2 += amount
                raise BaseException('some error happened')
        
            def decr_counter1(amount):
                global counter1
                counter1 -= amount
        
            def decr_counter2(amount):
                global counter2
                raise BaseException('compensation also fails')
        
            try:
                SagaBuilder \
                    .create() \
                    .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \
                    .action(lambda: incr_counter2(1), lambda: decr_counter2(1)) \
                    .action() \
                    .build() \
                    .execute()
            except SagaError as e:
                print(e)  #
        
            print(counter1)  # 0
            print(counter2)  # 1
        
        
        Passing values from one action to the next
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        
        An action can return a dict of return values.
        The dict is then passed as keyword arguments to the next action and it's corresponding compensation.
        No values can be passed between compensations.
        
        .. code-block:: python
        
            from saga import SagaBuilder, SagaError
        
            counter1 = 0
            counter2 = 0
        
            def incr_counter1(amount):
                global counter1
                counter1 += amount
                return {'counter1_value': counter1}
        
            def incr_counter2(counter1_value):
                global counter2
                counter2 += amount
        
            def decr_counter1(amount):
                global counter1
                counter1 -= amount
        
            def decr_counter2(counter1_value):
                global counter2
                counter2 -= amount
        
            SagaBuilder \
                .create() \
                .action(lambda: incr_counter1(15), lambda: decr_counter1(15)) \
                .action(incr_counter2, decr_counter2) \
                .action() \
                .build() \
                .execute()
        
            print(counter1)  # 15
            print(counter2)  # 15
        
        
Keywords: saga
dependent actions
rollback
compensate
distributed transaction
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Other Environment
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Software Development :: Libraries :: Python Modules
