[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-dd128aad-fdd4-49d4-8d8e-e8d962339679":3,"$f3Yim5Wsz2nCgcl5DcxdOaS5qy-OSPZlZDP_rgkMxY6M":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"dd128aad-fdd4-49d4-8d8e-e8d962339679","saga-orchestration","分布式事务和长时间运行的业务流程管理模式。","cat_life_career","mod_other","sickn33,other","---\nname: saga-orchestration\ndescription: \"Patterns for managing distributed transactions and long-running business processes.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# Saga Orchestration\n\nPatterns for managing distributed transactions and long-running business processes.\n\n## Do not use this skill when\n\n- The task is unrelated to saga orchestration\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Coordinating multi-service transactions\n- Implementing compensating transactions\n- Managing long-running business workflows\n- Handling failures in distributed systems\n- Building order fulfillment processes\n- Implementing approval workflows\n\n## Core Concepts\n\n### 1. Saga Types\n\n```\nChoreography                    Orchestration\n┌─────┐  ┌─────┐  ┌─────┐     ┌─────────────┐\n│Svc A│─►│Svc B│─►│Svc C│     │ Orchestrator│\n└─────┘  └─────┘  └─────┘     └──────┬──────┘\n   │        │        │               │\n   ▼        ▼        ▼         ┌─────┼─────┐\n Event    Event    Event       ▼     ▼     ▼\n                            ┌────┐┌────┐┌────┐\n                            │Svc1││Svc2││Svc3│\n                            └────┘└────┘└────┘\n```\n\n### 2. Saga Execution States\n\n| State            | Description                    |\n| ---------------- | ------------------------------ |\n| **Started**      | Saga initiated                 |\n| **Pending**      | Waiting for step completion    |\n| **Compensating** | Rolling back due to failure    |\n| **Completed**    | All steps succeeded            |\n| **Failed**       | Saga failed after compensation |\n\n## Templates\n\n### Template 1: Saga Orchestrator Base\n\n```python\nfrom abc import ABC, abstractmethod\nfrom dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import List, Dict, Any, Optional\nfrom datetime import datetime\nimport uuid\n\nclass SagaState(Enum):\n    STARTED = \"started\"\n    PENDING = \"pending\"\n    COMPENSATING = \"compensating\"\n    COMPLETED = \"completed\"\n    FAILED = \"failed\"\n\n\n@dataclass\nclass SagaStep:\n    name: str\n    action: str\n    compensation: str\n    status: str = \"pending\"\n    result: Optional[Dict] = None\n    error: Optional[str] = None\n    executed_at: Optional[datetime] = None\n    compensated_at: Optional[datetime] = None\n\n\n@dataclass\nclass Saga:\n    saga_id: str\n    saga_type: str\n    state: SagaState\n    data: Dict[str, Any]\n    steps: List[SagaStep]\n    current_step: int = 0\n    created_at: datetime = field(default_factory=datetime.utcnow)\n    updated_at: datetime = field(default_factory=datetime.utcnow)\n\n\nclass SagaOrchestrator(ABC):\n    \"\"\"Base class for saga orchestrators.\"\"\"\n\n    def __init__(self, saga_store, event_publisher):\n        self.saga_store = saga_store\n        self.event_publisher = event_publisher\n\n    @abstractmethod\n    def define_steps(self, data: Dict) -> List[SagaStep]:\n        \"\"\"Define the saga steps.\"\"\"\n        pass\n\n    @property\n    @abstractmethod\n    def saga_type(self) -> str:\n        \"\"\"Unique saga type identifier.\"\"\"\n        pass\n\n    async def start(self, data: Dict) -> Saga:\n        \"\"\"Start a new saga.\"\"\"\n        saga = Saga(\n            saga_id=str(uuid.uuid4()),\n            saga_type=self.saga_type,\n            state=SagaState.STARTED,\n            data=data,\n            steps=self.define_steps(data)\n        )\n        await self.saga_store.save(saga)\n        await self._execute_next_step(saga)\n        return saga\n\n    async def handle_step_completed(self, saga_id: str, step_name: str, result: Dict):\n        \"\"\"Handle successful step completion.\"\"\"\n        saga = await self.saga_store.get(saga_id)\n\n        # Update step\n        for step in saga.steps:\n            if step.name == step_name:\n                step.status = \"completed\"\n                step.result = result\n                step.executed_at = datetime.utcnow()\n                break\n\n        saga.current_step += 1\n        saga.updated_at = datetime.utcnow()\n\n        # Check if saga is complete\n        if saga.current_step >= len(saga.steps):\n            saga.state = SagaState.COMPLETED\n            await self.saga_store.save(saga)\n            await self._on_saga_completed(saga)\n        else:\n            saga.state = SagaState.PENDING\n            await self.saga_store.save(saga)\n            await self._execute_next_step(saga)\n\n    async def handle_step_failed(self, saga_id: str, step_name: str, error: str):\n        \"\"\"Handle step failure - start compensation.\"\"\"\n        saga = await self.saga_store.get(saga_id)\n\n        # Mark step as failed\n        for step in saga.steps:\n            if step.name == step_name:\n                step.status = \"failed\"\n                step.error = error\n                break\n\n        saga.state = SagaState.COMPENSATING\n        saga.updated_at = datetime.utcnow()\n        await self.saga_store.save(saga)\n\n        # Start compensation from current step backwards\n        await self._compensate(saga)\n\n    async def _execute_next_step(self, saga: Saga):\n        \"\"\"Execute the next step in the saga.\"\"\"\n        if saga.current_step >= len(saga.steps):\n            return\n\n        step = saga.steps[saga.current_step]\n        step.status = \"executing\"\n        await self.saga_store.save(saga)\n\n        # Publish command to execute step\n        await self.event_publisher.publish(\n            step.action,\n            {\n                \"saga_id\": saga.saga_id,\n                \"step_name\": step.name,\n                **saga.data\n            }\n        )\n\n    async def _compensate(self, saga: Saga):\n        \"\"\"Execute compensation for completed steps.\"\"\"\n        # Compensate in reverse order\n        for i in range(saga.current_step - 1, -1, -1):\n            step = saga.steps[i]\n            if step.status == \"completed\":\n                step.status = \"compensating\"\n                await self.saga_store.save(saga)\n\n                await self.event_publisher.publish(\n                    step.compensation,\n                    {\n                        \"saga_id\": saga.saga_id,\n                        \"step_name\": step.name,\n                        \"original_result\": step.result,\n                        **saga.data\n                    }\n                )\n\n    async def handle_compensation_completed(self, saga_id: str, step_name: str):\n        \"\"\"Handle compensation completion.\"\"\"\n        saga = await self.saga_store.get(saga_id)\n\n        for step in saga.steps:\n            if step.name == step_name:\n                step.status = \"compensated\"\n                step.compensated_at = datetime.utcnow()\n                break\n\n        # Check if all compensations complete\n        all_compensated = all(\n            s.status in (\"compensated\", \"pending\", \"failed\")\n            for s in saga.steps\n        )\n\n        if all_compensated:\n            saga.state = SagaState.FAILED\n            await self._on_saga_failed(saga)\n\n        await self.saga_store.save(saga)\n\n    async def _on_saga_completed(self, saga: Saga):\n        \"\"\"Called when saga completes successfully.\"\"\"\n        await self.event_publisher.publish(\n            f\"{self.saga_type}Completed\",\n            {\"saga_id\": saga.saga_id, **saga.data}\n        )\n\n    async def _on_saga_failed(self, saga: Saga):\n        \"\"\"Called when saga fails after compensation.\"\"\"\n        await self.event_publisher.publish(\n            f\"{self.saga_type}Failed\",\n            {\"saga_id\": saga.saga_id, \"error\": \"Saga failed\", **saga.data}\n        )\n```\n\n### Template 2: Order Fulfillment Saga\n\n```python\nclass OrderFulfillmentSaga(SagaOrchestrator):\n    \"\"\"Orchestrates order fulfillment across services.\"\"\"\n\n    @property\n    def saga_type(self) -> str:\n        return \"OrderFulfillment\"\n\n    def define_steps(self, data: Dict) -> List[SagaStep]:\n        return [\n            SagaStep(\n                name=\"reserve_inventory\",\n                action=\"InventoryService.ReserveItems\",\n                compensation=\"InventoryService.ReleaseReservation\"\n            ),\n            SagaStep(\n                name=\"process_payment\",\n                action=\"PaymentService.ProcessPayment\",\n                compensation=\"PaymentService.RefundPayment\"\n            ),\n            SagaStep(\n                name=\"create_shipment\",\n                action=\"ShippingService.CreateShipment\",\n                compensation=\"ShippingService.CancelShipment\"\n            ),\n            SagaStep(\n                name=\"send_confirmation\",\n                action=\"NotificationService.SendOrderConfirmation\",\n                compensation=\"NotificationService.SendCancellationNotice\"\n            )\n        ]\n\n\n# Usage\nasync def create_order(order_data: Dict):\n    saga = OrderFulfillmentSaga(saga_store, event_publisher)\n    return await saga.start({\n        \"order_id\": order_data[\"order_id\"],\n        \"customer_id\": order_data[\"customer_id\"],\n        \"items\": order_data[\"items\"],\n        \"payment_method\": order_data[\"payment_method\"],\n        \"shipping_address\": order_data[\"shipping_address\"]\n    })\n\n\n# Event handlers in each service\nclass InventoryService:\n    async def handle_reserve_items(self, command: Dict):\n        try:\n            # Reserve inventory\n            reservation = await self.reserve(\n                command[\"items\"],\n                command[\"order_id\"]\n            )\n            # Report success\n            await self.event_publisher.publish(\n                \"SagaStepCompleted\",\n                {\n                    \"saga_id\": command[\"saga_id\"],\n                    \"step_name\": \"reserve_inventory\",\n                    \"result\": {\"reservation_id\": reservation.id}\n                }\n            )\n        except InsufficientInventoryError as e:\n            await self.event_publisher.publish(\n                \"SagaStepFailed\",\n                {\n                    \"saga_id\": command[\"saga_id\"],\n                    \"step_name\": \"reserve_inventory\",\n                    \"error\": str(e)\n                }\n            )\n\n    async def handle_release_reservation(self, command: Dict):\n        # Compensating action\n        await self.release_reservation(\n            command[\"original_result\"][\"reservation_id\"]\n        )\n        await self.event_publisher.publish(\n            \"SagaCompensationCompleted\",\n            {\n                \"saga_id\": command[\"saga_id\"],\n                \"step_name\": \"reserve_inventory\"\n            }\n        )\n```\n\n### Template 3: Choreography-Based Saga\n\n```python\nfrom dataclasses import dataclass\nfrom typing import Dict, Any\nimport asyncio\n\n@dataclass\nclass SagaContext:\n    \"\"\"Passed through choreographed saga events.\"\"\"\n    saga_id: str\n    step: int\n    data: Dict[str, Any]\n    completed_steps: list\n\n\nclass OrderChoreographySaga:\n    \"\"\"Choreography-based saga using events.\"\"\"\n\n    def __init__(self, event_bus):\n        self.event_bus = event_bus\n        self._register_handlers()\n\n    def _register_handlers(self):\n        self.event_bus.subscribe(\"OrderCreated\", self._on_order_created)\n        self.event_bus.subscribe(\"InventoryReserved\", self._on_inventory_reserved)\n        self.event_bus.subscribe(\"PaymentProcessed\", self._on_payment_processed)\n        self.event_bus.subscribe(\"ShipmentCreated\", self._on_shipment_created)\n\n        # Compensation handlers\n        self.event_bus.subscribe(\"PaymentFailed\", self._on_payment_failed)\n        self.event_bus.subscribe(\"ShipmentFailed\", self._on_shipment_failed)\n\n    async def _on_order_created(self, event: Dict):\n        \"\"\"Step 1: Order created, reserve inventory.\"\"\"\n        await self.event_bus.publish(\"ReserveInventory\", {\n            \"saga_id\": event[\"order_id\"],\n            \"order_id\": event[\"order_id\"],\n            \"items\": event[\"items\"]\n        })\n\n    async def _on_inventory_reserved(self, event: Dict):\n        \"\"\"Step 2: Inventory reserved, process payment.\"\"\"\n        await self.event_bus.publish(\"ProcessPayment\", {\n            \"saga_id\": event[\"saga_id\"],\n            \"order_id\": event[\"order_id\"],\n            \"amount\": event[\"total_amount\"],\n            \"reservation_id\": event[\"reservation_id\"]\n        })\n\n    async def _on_payment_processed(self, event: Dict):\n        \"\"\"Step 3: Payment done, create shipment.\"\"\"\n        await self.event_bus.publish(\"CreateShipment\", {\n            \"saga_id\": event[\"saga_id\"],\n            \"order_id\": event[\"order_id\"],\n            \"payment_id\": event[\"payment_id\"]\n        })\n\n    async def _on_shipment_created(self, event: Dict):\n        \"\"\"Step 4: Complete - send confirmation.\"\"\"\n        await self.event_bus.publish(\"OrderFulfilled\", {\n            \"saga_id\": event[\"saga_id\"],\n            \"order_id\": event[\"order_id\"],\n            \"tracking_number\": event[\"tracking_number\"]\n        })\n\n    # Compensation handlers\n    async def _on_payment_failed(self, event: Dict):\n        \"\"\"Payment failed - release inventory.\"\"\"\n        await self.event_bus.publish(\"ReleaseInventory\", {\n            \"saga_id\": event[\"saga_id\"],\n            \"reservation_id\": event[\"reservation_id\"]\n        })\n        await self.event_bus.publish(\"OrderFailed\", {\n            \"order_id\": event[\"order_id\"],\n            \"reason\": \"Payment failed\"\n        })\n\n    async def _on_shipment_failed(self, event: Dict):\n        \"\"\"Shipment failed - refund payment and release inventory.\"\"\"\n        await self.event_bus.publish(\"RefundPayment\", {\n            \"saga_id\": event[\"saga_id\"],\n            \"payment_id\": event[\"payment_id\"]\n        })\n        await self.event_bus.publish(\"ReleaseInventory\", {\n            \"saga_id\": event[\"saga_id\"],\n            \"reservation_id\": event[\"reservation_id\"]\n        })\n```\n\n### Template 4: Saga with Timeouts\n\n```python\nclass TimeoutSagaOrchestrator(SagaOrchestrator):\n    \"\"\"Saga orchestrator with step timeouts.\"\"\"\n\n    def __init__(self, saga_store, event_publisher, scheduler):\n        super().__init__(saga_store, event_publisher)\n        self.scheduler = scheduler\n\n    async def _execute_next_step(self, saga: Saga):\n        if saga.current_step >= len(saga.steps):\n            return\n\n        step = saga.steps[saga.current_step]\n        step.status = \"executing\"\n        step.timeout_at = datetime.utcnow() + timedelta(minutes=5)\n        await self.saga_store.save(saga)\n\n        # Schedule timeout check\n        await self.scheduler.schedule(\n            f\"saga_timeout_{saga.saga_id}_{step.name}\",\n            self._check_timeout,\n            {\"saga_id\": saga.saga_id, \"step_name\": step.name},\n            run_at=step.timeout_at\n        )\n\n        await self.event_publisher.publish(\n            step.action,\n            {\"saga_id\": saga.saga_id, \"step_name\": step.name, **saga.data}\n        )\n\n    async def _check_timeout(self, data: Dict):\n        \"\"\"Check if step has timed out.\"\"\"\n        saga = await self.saga_store.get(data[\"saga_id\"])\n        step = next(s for s in saga.steps if s.name == data[\"step_name\"])\n\n        if step.status == \"executing\":\n            # Step timed out - fail it\n            await self.handle_step_failed(\n                data[\"saga_id\"],\n                data[\"step_name\"],\n                \"Step timed out\"\n            )\n```\n\n## Durable Execution Alternative\n\nThe templates above build saga infrastructure from scratch — saga stores, event publishers, compensation tracking. **Durable execution frameworks** (like DBOS) eliminate much of this boilerplate: the workflow runtime automatically persists state to a database, retries failed steps, and resumes from the last checkpoint after crashes. Instead of building a `SagaOrchestrator` base class, you write a workflow function with steps — the framework handles persistence, crash recovery, and exactly-once execution semantics. Consider durable execution when you want saga-like reliability without managing the coordination infrastructure yourself.\n\n## Best Practices\n\n### Do's\n\n- **Make steps idempotent** - Safe to retry\n- **Design compensations carefully** - They must work\n- **Use correlation IDs** - For tracing across services\n- **Implement timeouts** - Don't wait forever\n- **Log everything** - For debugging failures\n\n### Don'ts\n\n- **Don't assume instant completion** - Sagas take time\n- **Don't skip compensation testing** - Most critical part\n- **Don't couple services** - Use async messaging\n- **Don't ignore partial failures** - Handle gracefully\n\n## Related Skills\n\nWorks well with: `event-sourcing-architect`, `workflow-automation`, `dbos-*`\n\n## Resources\n\n- [Saga Pattern](https:\u002F\u002Fmicroservices.io\u002Fpatterns\u002Fdata\u002Fsaga.html)\n- [Designing Data-Intensive Applications](https:\u002F\u002Fdataintensive.net\u002F)\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,51,198,"2026-05-16 13:37:31",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"其他","other","mdi-page-next-outline","其他类型Skill",5,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"职场发展","career","mdi-briefcase-outline","面试准备、简历优化、职业规划",4,575,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"e0c21bf3-7c80-4179-bdc4-45f6fc051fd1","1.0.0","saga-orchestration.zip",5136,"uploads\u002Fskills\u002Fdd128aad-fdd4-49d4-8d8e-e8d962339679\u002Fsaga-orchestration.zip","88002d692e3952abb4b5649436ac12dadb37b01e1abeb86a5adcd1841233d947","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":17334},{\"path\":\"resources\u002Fimplementation-playbook.md\",\"isDirectory\":false,\"size\":859}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]