Skip to main content

spakky-saga

Spakky Framework를 위한 분산 트랜잭션 사가 오케스트레이션입니다. @Saga와 @saga_step으로 보상 기반 workflow를 DI-managed application component로 선언합니다.

설치

pip install spakky-saga

주요 기능

  • @Saga stereotype: saga orchestrator class를 표시합니다(@Pod 확장).
  • AbstractSaga[SagaDataT]: flow() 추상 메서드와 execute() entry point를 가진 generic base class입니다.
  • @saga_step decorator: instance method에서 >>, &, | 연산자를 활성화하는 typed descriptor입니다.
  • Flow DSL: 연산자 또는 builder 함수(saga_flow, step, parallel)로 선언적 구성
  • Error strategy: Compensate(기본값), Skip, ExponentialBackoff을 포함한 Retry(max_attempts, backoff, then)을 제공합니다.
  • Timeout: step별 timeout=과 saga별 SagaFlow.timeout() 지원
  • 병렬 실행: asyncio.gather 기반 group(& operator / parallel())
  • 보상: 실패 시 commit된 step을 역순으로 자동 rollback
  • AuthContextSnapshot 전파: AbstractSagaData.auth_context_snapshot signed envelope를 실행, retry, parallel, compensation 동안 유지하고 protected saga step을 enforcement합니다.
  • SagaResult[T]: status, data, failed_step, error, history, elapsed를 담는 non-throwing result
  • 구조화 로깅: [saga=... step=... status=... elapsed=...ms] format

빠른 시작

SagaData 정의

from spakky.saga import AbstractSagaData


class OrderSagaData(AbstractSagaData):
    order_id: int
    customer_id: int
    ticket_id: int | None = None

Saga 정의

from spakky.saga import AbstractSaga, Saga, SagaFlow, saga_step


@Saga()
class CreateOrderSaga(AbstractSaga[OrderSagaData]):
    @saga_step
    async def issue_ticket(self, data: OrderSagaData) -> OrderSagaData:
        ...

    @saga_step
    async def cancel_ticket(self, data: OrderSagaData) -> None:
        ...

    @saga_step
    async def reserve_stock(self, data: OrderSagaData) -> OrderSagaData:
        ...

    def flow(self) -> SagaFlow[OrderSagaData]:
        return SagaFlow(
            items=(
                self.issue_ticket >> self.cancel_ticket,  # Transaction
                self.reserve_stock,                        # SagaStep (no compensation)
            )
        )

실행

result = await saga.execute(OrderSagaData(order_id=1, customer_id=42))
if result.status is SagaStatus.COMPLETED:
    ...

Protected Saga Step

from spakky.auth import protected, require_scope
from spakky.saga import SagaAuthExecutionContext


@Saga()
class ProtectedOrderSaga(AbstractSaga[OrderSagaData]):
    @saga_step
    @protected
    @require_scope("orders:write")
    async def issue_ticket(self, data: OrderSagaData) -> OrderSagaData:
        ...


result = await saga.execute(
    OrderSagaData(order_id=1, customer_id=42, auth_context_snapshot="signed-envelope"),
    auth_context=SagaAuthExecutionContext(
        snapshot_verifier=snapshot_verifier,
        scope_checker=scope_checker,
    ),
)

Protected step은 raw bearer token을 받지 않고 signed AuthContextSnapshot envelope를 검증합니다. missing, invalid, expired snapshot은 CHALLENGE decision으로 step failure가 되며, provider unavailable은 ERROR decision으로 기존 saga failure/compensation policy를 따릅니다.

Builder 함수 대안

from spakky.saga import Retry, parallel, saga_flow, step


flow = saga_flow(
    step(issue_ticket_fn, compensate=cancel_ticket_fn),
    parallel(reserve_stock_fn, charge_payment_fn),
    step(confirm_order_fn, on_error=Retry(max_attempts=3)),
)

Flow 연산자

연산자 의미 결과 타입
>> compensate 함수 바인딩 Transaction[T]
& 병렬 실행 Parallel[T]
| 에러 전략 부착 좌변과 동일한 타입 + on_error

Error Strategy

Strategy Signature 설명
Compensate() (기본값) 역순 compensation 실행
Skip() — 실패를 무시하고 계속 진행
Retry(max_attempts, backoff, then) Retry(3, ExponentialBackoff(1.0), Compensate()) N회 재시도 후 then 전략 적용
ExponentialBackoff(base=1.0) — retry 사이에 base * 2^(attempt-1) delay 적용

API 레퍼런스

Stereotype / Base

기호 설명
@Saga() saga orchestrator class용 stereotype(@Pod 확장)
AbstractSaga[SagaDataT] flow() 추상 메서드와 execute()를 가진 ABC 기반 클래스
@saga_step >>, &, `
AbstractSagaData base data model(@immutable + AbstractDomainModel, saga_id: UUID 자동 생성, auth_context_snapshot envelope 전파)
SagaAuthExecutionContext protected saga step enforcement에 사용할 snapshot verifier/checker port 묶음

Flow 타입

기호 설명
SagaFlow[T] 최상위 flow 정의(items, saga_timeout, compensation_failure_handler)
SagaStep[T] compensation 없는 단일 action
Transaction[T] action + compensate 쌍
Parallel[T] step/transaction 동시 실행 그룹
FlowItem[T] flow 구성 가능 item의 union
ActionFn[T] / CompensateFn[T] action / compensate callable용 type alias
SagaDataT AbstractSagaData에 bound된 TypeVar

Builder

함수 설명
saga_flow(*items) 순차 item으로 SagaFlow 생성
step(action, *, compensate=, on_error=, timeout=) SagaStep 또는 Transaction 생성
parallel(*items) Parallel group 생성(최소 2개 item 필요)

실행

기호 설명
run_saga_flow(flow, data, *, saga_name=) flow 실행 후 SagaResult 반환
AbstractSaga.execute(data) type(self).__name__을 사용하는 run_saga_flow 얇은 wrapper

Result 타입

기호 설명
SagaResult[T] status, data, failed_step, error, history, elapsed
StepRecord name, status, elapsed — per-step execution record
StepStatus COMMITTED, FAILED, COMPENSATED
SagaStatus STARTED, RUNNING, COMPENSATING, COMPLETED, FAILED, TIMED_OUT

에러

에러 설명
AbstractSpakkySagaError 모든 saga error의 ABC 기반 클래스
SagaFlowDefinitionError 유효하지 않은 saga flow 정의(정적 검증)
SagaCompensationFailedError rollback 중 compensation 실패
SagaStepTimeoutError step timeout 초과 시 내부에서 발생(on_error로 라우팅)
SagaParallelMergeConflictError 병렬 step이 data merge 중 같은 필드 변경
SagaEngineNotConnectedError saga engine 연결 전에 execute()가 호출됨

관련 문서

  • ADR-0007 — architecture decision record
  • spakky-domain — AbstractSagaData의 부모인 AbstractDomainModel 제공

개발 검증

패키지 단위 검증은 해당 패키지 디렉토리에서 실행합니다.

uv run ruff format .
uv run ruff check .
uv run pyrefly check
uv run pytest

pytest는 각 패키지 pyproject.toml의 coverage 설정을 사용합니다.

라이선스

MIT License

Metadata

Release files for spakky-saga 8.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spakky-saga 8.1.0
File Size Uploaded
spakky_saga-8.1.0.tar.gz 16.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for spakky-saga 8.1.0
File Interpreter ABI Platform
spakky_saga-8.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.4 kB

Release files / spakky_saga-8.1.0.tar.gz

Download URL spakky_saga-8.1.0.tar.gz
Size 16.2 kB
Tags Source
SHA-256 checksum
How to use checksums
198643fa05e3a7066a1e56927c05dce423e8f6b409e960250208657b31d60536
BLAKE2b-256 checksum
How to use checksums
9a3106151bc0256b2f49acab5dbe0292a79bbedf3386111dfc8f2ac543847663
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.

Transparency log

Release files / spakky_saga-8.1.0-py3-none-any.whl

Download URL spakky_saga-8.1.0-py3-none-any.whl
Size 21.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f4660e4e9cbae568470fa6c6c4307c754bcdbf78f50cc63156fce6d28254bff0
BLAKE2b-256 checksum
How to use checksums
2277ab4a9bdf25ffca8ffd0b304cedc84c8adcb4c6c603ccf09542b8655291a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

8.1.0 This release

2 release files

8.0.0

2 release files

7.2.0

2 release files

7.1.1

2 release files

7.1.0

2 release files

7.0.0

2 release files

6.13.0

2 release files

6.12.0

2 release files

6.11.0

2 release files

6.10.1

2 release files

6.10.0

2 release files

6.9.1

2 release files

6.9.0

2 release files

6.8.0

2 release files

6.7.0

2 release files

6.6.1

2 release files

6.6.0

2 release files

6.5.0

2 release files

6.4.0

2 release files

6.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page