{"id":19503636,"url":"https://github.com/im-cloud-spain-connectors/python-connect-devops-fulfillment-framework","last_synced_at":"2025-02-25T21:44:29.316Z","repository":{"id":78684763,"uuid":"596032995","full_name":"IM-Cloud-Spain-Connectors/python-connect-devops-fulfillment-framework","owner":"IM-Cloud-Spain-Connectors","description":"Framework to ease and speedup the development of a Connect DevOps Fulfillment Extension. ","archived":false,"fork":false,"pushed_at":"2023-11-06T09:36:53.000Z","size":28,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-08T10:39:54.797Z","etag":null,"topics":["component","devops","framework","fulfillment","python","rndi"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IM-Cloud-Spain-Connectors.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-01T10:22:00.000Z","updated_at":"2023-07-07T17:37:31.000Z","dependencies_parsed_at":"2023-11-06T10:46:18.444Z","dependency_job_id":null,"html_url":"https://github.com/IM-Cloud-Spain-Connectors/python-connect-devops-fulfillment-framework","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IM-Cloud-Spain-Connectors%2Fpython-connect-devops-fulfillment-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IM-Cloud-Spain-Connectors%2Fpython-connect-devops-fulfillment-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IM-Cloud-Spain-Connectors%2Fpython-connect-devops-fulfillment-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IM-Cloud-Spain-Connectors%2Fpython-connect-devops-fulfillment-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IM-Cloud-Spain-Connectors","download_url":"https://codeload.github.com/IM-Cloud-Spain-Connectors/python-connect-devops-fulfillment-framework/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240754295,"owners_count":19852186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","devops","framework","fulfillment","python","rndi"],"created_at":"2024-11-10T22:22:25.838Z","updated_at":"2025-02-25T21:44:29.290Z","avatar_url":"https://github.com/IM-Cloud-Spain-Connectors.png","language":"Python","readme":"# Python Connect DevOps Fulfillment Framework\n\n[![Test](https://github.com/othercodes/python-connect-devops-fulfillment-framework/actions/workflows/test.yml/badge.svg)](https://github.com/othercodes/python-connect-devops-fulfillment-framework/actions/workflows/test.yml)\n\nFramework to ease and speedup the development of a Connect DevOps Fulfillment Extension.\n\n## Installation\n\nThe easiest way to install the Connect DevOps Fulfillment Framework is to get the latest version from PyPI:\n\n```bash\n# using poetry\npoetry add rndi-connect-devops-fulfillment-framework\n# using pip\npip install rndi-connect-devops-fulfillment-framework\n```\n\n## Service Container\n\nThe service container is a powerful tool for managing class dependencies and performing dependency injection.\nDependency injection is a fancy phrase that essentially means this: class dependencies are \"injected\" into the class\nvia the constructor or, in some cases, \"setter\" methods.\n\n```python\nfrom rndi.cache.contracts import Cache\nfrom rndi.connect.business_transactions.adapters import BackgroundTransaction\n\n\nclass CreateUserTransaction(BackgroundTransaction):\n    def __init__(self, cache: Cache):\n        self.cache = cache\n```\n\nIn this example, the `CreateUserTransaction` needs to use retrieve some data from the cache. So, we will inject a\nservice that is able to retrieve the data from cache. In this context, our Cache most likely uses SQLiteCache to get\ndata from cache. However, since the cache adapter is injected, we are able to easily swap it out with another\nimplementation. We are also able to easily \"mock\", or create a dummy implementation of the Cache when testing our\napplication.\n\nFor more information about the Service Container please check [DI Container](https://github.com/).\n\n## Service Providers\n\nService providers are the central place of all fulfillment extensions. Each transaction services and core services, are\nbootstrapped via service providers.\n\nBut, what do we mean by \"bootstrapped\"? In general, we mean registering things,\nincluding registering service container bindings and middlewares. Service providers are the central place to configure\nyour application.\n\n```python\nfrom logging import LoggerAdapter\n\nfrom rndi.cache.adapters.sqlite.adapter import provide_sqlite_cache_adapter\nfrom rndi.cache.contracts import Cache\nfrom rndi.cache.provider import provide_cache\nfrom rndi.dicontainer.adapter import BaseServiceProvider as ServiceProvider\n\n\nclass CacheServiceProvider(ServiceProvider):\n    def provide_cache(self, config: dict, logger: LoggerAdapter) -\u003e Cache:\n        return provide_cache(config, logger, {\n            'sqlite': provide_sqlite_cache_adapter,\n        })\n\n```\n\nThe example above allows the usage of different cache adapters.\n\nFor more information about the Service Container please check [Service Providers](https://github.com/).\n\n## Transactions\n\nOnce the package is installed, you need to start declaring your transactions.\n\n```python\nfrom connect.eaas.core.responses import BackgroundResponse\nfrom rndi.connect.business_transactions.adapters import BackgroundTransaction\nfrom rndi.connect.business_transactions.contracts import TBackgroundResponse\n\n\nclass SomeCoreTransaction(BackgroundTransaction):\n    def __init__(self, client, logger, config, cache):\n        self.client = client\n        self.logger = logger\n        self.config = config\n        self.cache = cache\n\n    def name(self) -\u003e str:\n        return 'Sample Transaction'\n\n    def should_execute(self, request: dict) -\u003e bool:\n        return True\n\n    def execute(self, request: dict) -\u003e TBackgroundResponse:\n        print(\"Running Execute!\")\n        return BackgroundResponse.done()\n\n    def compensate(self, request: dict, e: Exception) -\u003e TBackgroundResponse:\n        raise e\n\n```\n\n## Sagas\n\nNext we need to declare the complete flow or `Saga` that will contain the different transactions:\n\n```python\nfrom typing import List, Type\nfrom rndi.connect.devops_fulfillment_framework.application import Saga\nfrom rndi.connect.business_transaction_middleware.middleware import Middleware\nfrom rndi.connect.business_transactions.adapters import BackgroundTransaction\nfrom extension.transactions import SomeCoreTransaction\n\n\nclass PurchaseSaga(Saga):\n    def middlewares(self, request: dict) -\u003e List[Type[Middleware]]:\n        return []\n\n    def transactions(self, request: dict) -\u003e List[Type[BackgroundTransaction]]:\n        return [\n            SomeCoreTransaction,\n        ]\n\n```\n\nFinally, we just need to execute the saga in the correct method of the fulfillment extension:\n\n```python\nfrom connect.eaas.core.decorators import event\nfrom connect.eaas.core.extension import EventsApplicationBase\nfrom extension.sagas import PurchaseSaga\n\n\nclass SampleFulfillmentExtensionEventsApplication(EventsApplicationBase):\n    @event('asset_purchase_request_processing', statuses=['pending'])\n    def handle_asset_purchase_request_processing(self, request):\n        self.logger.info(f\"Obtained request with id {request['id']}\")\n        return PurchaseSaga.make(self.config, self.client, self.logger).resolve(request)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fim-cloud-spain-connectors%2Fpython-connect-devops-fulfillment-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fim-cloud-spain-connectors%2Fpython-connect-devops-fulfillment-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fim-cloud-spain-connectors%2Fpython-connect-devops-fulfillment-framework/lists"}