saga-api


Namesaga-api JSON
Version 0.0.1 PyPI version JSON
download
home_pagehttps://github.com/RupamSolanki/api-saga
Summary
upload_time2023-01-02 17:34:00
maintainer
docs_urlNone
authorRupam Solanki
requires_python>=3.6
licenseMIT
keywords saga rest_api api django flask roll_back transition
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![PyPI version](https://badge.fury.io/py/django-ninja-extra.svg)](https://badge.fury.io/py/django-ninja-extra)
[![PyPI version](https://img.shields.io/pypi/v/django-ninja-extra.svg)](https://pypi.python.org/pypi/django-ninja-extra)
[![PyPI version](https://img.shields.io/pypi/pyversions/django-ninja-extra.svg)](https://pypi.python.org/pypi/django-ninja-extra)

# API SAGA

**API SAGA** is a complete class-based fashion of building saga pattern for microservices. It offers both narrative
patterns `Orchestration-Based Saga` and `Choreography-Based Saga`. To execute saga operations use the following method.

- orchestrator_execute
- choreography_execute

**orchestrator_execute** Every transition is carried out one by one. If exception arises, all prior operations
will be compensated in the reversed order. All the operation responses are contained in the result list and the results
are arranged in the same sequence as the Saga operations.

**choreography_execute** Every transition is carried out concurrently, and no operation is dependent on any other
process. Hence, multithreading is used an if an error occurs in any of the operation process all the succeeded
operations will be compensated.

While executing compensations possible Exceptions are recorded and raised wrapped in a SagaException once all
compensations have been executed.

**Key features:**

- **Easy**: Designed to be easy to use and intuitive.
- **Fast to code**: Type hints and automatic docs lets you focus only on business logic.
- **Framework friendly**: Since it developed with standard Python, so it can simply implement with python based
  frameworks like Django and Flask.
- **Retry operation attempts**: Retry an operation action again if it fails.

---

### Requirements

- Python >= 3.6

## Installation

```
pip install api-saga
```

After installation, import `SagaAssembler` from `api-saga`


### Declartion
The saga operation contains only two function operation action and compensation. The action and compensation are 
 by two ways.
- when operation has arguments then pass the function along with in a tuple.
- When function is without argument then simply pass the function name.

**Example**
```python

...
# Operation with argument functions 
SagaAssembler.saga().operation((function_name, arg_1, arg_2),(compensation_function_name, arg_1)).orchestrator_execute()
...

# Operation without argument functions
SagaAssembler.saga().operation(function_name, compensation_function_name).orchestrator_execute()

```

## Usage

Simple example

```Python
import json

import requests


def update_product_state(state):
    #function to update the state in product service.
    url = "https://host/productService/product/123/"
    # updat e product state from 'in_stock' to 'sold_out' 
    response = requests.post(url=url,data=json.dumps({"state":state}))
    if response != 200:
        raise Exception(response.error)
    return response
    
def update_shipping_state(shipping_state):
    #function to update the state in shipping service.
    url = "https://host/shippingService/product/123/shipping/"
    # update shipping state to 'ready_to_dispatch'
    response = requests.post(url=url, data=json.dumps({"state": shipping_state}))
    if response != 200:
        raise Exception(response.error)
    return response
   

```

Now build saga as given below:

```Python
...
from api-saga import SagaAssembler

...
try:
    result = SagaAssembler.saga().operation((update_product_state, 'sold_out'),(update_product_state, 'in_stock')).operation((update_shipping_state, 'ready_to_dispatch')).choreography_execute()
except SagaAssembler.SagaException as exception:
  return str(exception.operation_error)
...
```

### Advanced saga usage

The prior operation result can be accessed inside the operation function when using `orchestrator_execute`.

**Example**
```python

def function_name(args):
    # access previous functions outcomes.
    prior_results = function_name.saga_results
    ...
```

### Advanced saga Exception handling

When an error occurs in saga execution it can be handled using `SagaException`. The SagaException provides error as well
as information to track error function and compensation results.

**Exmaple**
```python
...
except SagaAssembler.SagaException as exception:
    # Error
    exception.operation_error
    # Function name responsible for the error.
    exception.operation_name    
    # Compensation success result list.
    exception.compensation_success_result
    # Error list that occurs when compensation is executed.
    exception.compensation_errors                                
```




            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/RupamSolanki/api-saga",
    "name": "saga-api",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "saga,rest_api,api,django,flask,roll_back,transition",
    "author": "Rupam Solanki",
    "author_email": "rupam.solanki1412@gmail.com",
    "download_url": "",
    "platform": null,
    "description": "[![PyPI version](https://badge.fury.io/py/django-ninja-extra.svg)](https://badge.fury.io/py/django-ninja-extra)\n[![PyPI version](https://img.shields.io/pypi/v/django-ninja-extra.svg)](https://pypi.python.org/pypi/django-ninja-extra)\n[![PyPI version](https://img.shields.io/pypi/pyversions/django-ninja-extra.svg)](https://pypi.python.org/pypi/django-ninja-extra)\n\n# API SAGA\n\n**API SAGA** is a complete class-based fashion of building saga pattern for microservices. It offers both narrative\npatterns `Orchestration-Based Saga` and `Choreography-Based Saga`. To execute saga operations use the following method.\n\n- orchestrator_execute\n- choreography_execute\n\n**orchestrator_execute** Every transition is carried out one by one. If exception arises, all prior operations\nwill be compensated in the reversed order. All the operation responses are contained in the result list and the results\nare arranged in the same sequence as the Saga operations.\n\n**choreography_execute** Every transition is carried out concurrently, and no operation is dependent on any other\nprocess. Hence, multithreading is used an if an error occurs in any of the operation process all the succeeded\noperations will be compensated.\n\nWhile executing compensations possible Exceptions are recorded and raised wrapped in a SagaException once all\ncompensations have been executed.\n\n**Key features:**\n\n- **Easy**: Designed to be easy to use and intuitive.\n- **Fast to code**: Type hints and automatic docs lets you focus only on business logic.\n- **Framework friendly**: Since it developed with standard Python, so it can simply implement with python based\n  frameworks like Django and Flask.\n- **Retry operation attempts**: Retry an operation action again if it fails.\n\n---\n\n### Requirements\n\n- Python >= 3.6\n\n## Installation\n\n```\npip install api-saga\n```\n\nAfter installation, import `SagaAssembler` from `api-saga`\n\n\n### Declartion\nThe saga operation contains only two function operation action and compensation. The action and compensation are \n by two ways.\n- when operation has arguments then pass the function along with in a tuple.\n- When function is without argument then simply pass the function name.\n\n**Example**\n```python\n\n...\n# Operation with argument functions \nSagaAssembler.saga().operation((function_name, arg_1, arg_2),(compensation_function_name, arg_1)).orchestrator_execute()\n...\n\n# Operation without argument functions\nSagaAssembler.saga().operation(function_name, compensation_function_name).orchestrator_execute()\n\n```\n\n## Usage\n\nSimple example\n\n```Python\nimport json\n\nimport requests\n\n\ndef update_product_state(state):\n    #function to update the state in product service.\n    url = \"https://host/productService/product/123/\"\n    # updat e product state from 'in_stock' to 'sold_out' \n    response = requests.post(url=url,data=json.dumps({\"state\":state}))\n    if response != 200:\n        raise Exception(response.error)\n    return response\n    \ndef update_shipping_state(shipping_state):\n    #function to update the state in shipping service.\n    url = \"https://host/shippingService/product/123/shipping/\"\n    # update shipping state to 'ready_to_dispatch'\n    response = requests.post(url=url, data=json.dumps({\"state\": shipping_state}))\n    if response != 200:\n        raise Exception(response.error)\n    return response\n   \n\n```\n\nNow build saga as given below:\n\n```Python\n...\nfrom api-saga import SagaAssembler\n\n...\ntry:\n    result = SagaAssembler.saga().operation((update_product_state, 'sold_out'),(update_product_state, 'in_stock')).operation((update_shipping_state, 'ready_to_dispatch')).choreography_execute()\nexcept SagaAssembler.SagaException as exception:\n  return str(exception.operation_error)\n...\n```\n\n### Advanced saga usage\n\nThe prior operation result can be accessed inside the operation function when using `orchestrator_execute`.\n\n**Example**\n```python\n\ndef function_name(args):\n    # access previous functions outcomes.\n    prior_results = function_name.saga_results\n    ...\n```\n\n### Advanced saga Exception handling\n\nWhen an error occurs in saga execution it can be handled using `SagaException`. The SagaException provides error as well\nas information to track error function and compensation results.\n\n**Exmaple**\n```python\n...\nexcept SagaAssembler.SagaException as exception:\n    # Error\n    exception.operation_error\n    # Function name responsible for the error.\n    exception.operation_name    \n    # Compensation success result list.\n    exception.compensation_success_result\n    # Error list that occurs when compensation is executed.\n    exception.compensation_errors                                \n```\n\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "",
    "version": "0.0.1",
    "split_keywords": [
        "saga",
        "rest_api",
        "api",
        "django",
        "flask",
        "roll_back",
        "transition"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "689b5fd0ea30db86cf963c16c3767191bb293a71944121c9eb580bfcdee85455",
                "md5": "4fe6b69f8b7814fd53b9936dcb062dd2",
                "sha256": "08b1c9d7e6b657af1ee933079a37f68effb2d7b957930344b55bb12cd6aa9fa7"
            },
            "downloads": -1,
            "filename": "saga_api-0.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4fe6b69f8b7814fd53b9936dcb062dd2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 5901,
            "upload_time": "2023-01-02T17:34:00",
            "upload_time_iso_8601": "2023-01-02T17:34:00.027766Z",
            "url": "https://files.pythonhosted.org/packages/68/9b/5fd0ea30db86cf963c16c3767191bb293a71944121c9eb580bfcdee85455/saga_api-0.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-01-02 17:34:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "RupamSolanki",
    "github_project": "api-saga",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "saga-api"
}
        
Elapsed time: 0.02616s