Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ license = "Apache-2.0"
keywords = ["opentelemetry", "tracing", "observability", "durable-execution"]
authors = [{ name = "AWS durable-execution-dev", email = "durable-execution-dev@amazon.com" }]
classifiers = [
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import tomllib
from pathlib import Path


PACKAGE_ROOT = Path(__file__).resolve().parents[1]


def test_package_is_marked_production_stable() -> None:
with (PACKAGE_ROOT / "pyproject.toml").open("rb") as pyproject:
classifiers = tomllib.load(pyproject)["project"]["classifiers"]

assert "Development Status :: 5 - Production/Stable" in classifiers
assert "Development Status :: 4 - Beta" not in classifiers
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import functools
import json
import logging
import warnings
from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any
Expand Down Expand Up @@ -178,8 +177,7 @@ def durable_execution(
Args:
func: The user function to decorate
boto3_client: Optional boto3 Lambda client to use
plugins: Optional list of plugins to use (EXPERIMENTAL: This
feature has known issues and this parameter may change or be removed.)
plugins: Optional list of instrumentation plugins to use
"""
# Decorator called with parameters
if func is None:
Expand All @@ -190,13 +188,6 @@ def durable_execution(

logger.debug("Starting durable execution handler...")

if plugins:
warnings.warn(
"The 'plugins' parameter is provisional and may be altered or removed.",
category=FutureWarning,
stacklevel=2, # point the warning to the caller of durable_execution
)

plugin_executor = PluginExecutor(load_configured_plugins(plugins))

@plugin_executor.handle_durable_output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,18 @@ class OperationInfo:
is_replayed: bool
status: OperationStatus
end_time: datetime.datetime | None = field(default=None, kw_only=True)
result: str | None = field(default=None, kw_only=True)
error: ErrorObject | None = field(default=None, kw_only=True)
result: str | None = field(
default=None,
kw_only=True,
metadata={"experimental": True},
)
"""EXPERIMENTAL: The serialized operation result, when available."""
error: ErrorObject | None = field(
default=None,
kw_only=True,
metadata={"experimental": True},
)
"""EXPERIMENTAL: The operation error, when available."""
attempt: int | None = field(default=None, kw_only=True)

@staticmethod
Expand Down Expand Up @@ -175,7 +185,11 @@ class InvocationStartInfo(InvocationInfo):
@dataclass(frozen=True)
class InvocationEndInfo(InvocationInfo):
status: InvocationStatus = field(kw_only=True)
error: ErrorObject | None = None
error: ErrorObject | None = field(
default=None,
metadata={"experimental": True},
)
"""EXPERIMENTAL: The invocation error, when available."""

@classmethod
def from_durable_execution_invocation_output(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import datetime
import json
import time
import warnings
from typing import Any
from unittest.mock import Mock, patch

Expand Down Expand Up @@ -2914,12 +2915,13 @@ def test_durable_execution_loads_plugins_when_handler_is_initialized():
resolved_plugin = _RecordingPlugin()

with (
warnings.catch_warnings(),
patch(
"aws_durable_execution_sdk_python.execution.load_configured_plugins",
return_value=[explicit_plugin, resolved_plugin],
) as load_plugins,
pytest.warns(FutureWarning),
):
warnings.simplefilter("error", FutureWarning)

@durable_execution(plugins=[explicit_plugin])
def test_handler(event: Any, context: DurableContext) -> dict:
Expand Down
25 changes: 25 additions & 0 deletions packages/aws-durable-execution-sdk-python/tests/plugin_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime
import logging
import unittest
from dataclasses import fields
from unittest.mock import MagicMock

from aws_durable_execution_sdk_python.identifier import OperationIdentifier
Expand All @@ -18,6 +19,7 @@
from aws_durable_execution_sdk_python.plugin import (
DurableInstrumentationPlugin,
InvocationEndInfo,
InvocationInfo,
InvocationStartInfo,
OperationChangeInfo,
OperationEndInfo,
Expand Down Expand Up @@ -110,6 +112,29 @@


class TestDataClasses(unittest.TestCase):
def test_payload_fields_are_marked_experimental(self):
plugin_info_types = (
OperationInfo,
OperationStartInfo,
OperationEndInfo,
OperationChangeInfo,
UserFunctionStartInfo,
UserFunctionEndInfo,
InvocationInfo,
InvocationStartInfo,
InvocationEndInfo,
)
payload_field_terms = ("input", "output", "result", "error")

for info_type in plugin_info_types:
for info_field in fields(info_type):
if any(term in info_field.name for term in payload_field_terms):
self.assertIs(
info_field.metadata.get("experimental"),
True,
f"{info_type.__name__}.{info_field.name}",
)

def test_operation_start_info(self):
self.assertEqual(OPERATION_START_INFO.sub_type, OperationSubType.CALLBACK)
self.assertEqual(OPERATION_START_INFO.name, "my-op")
Expand Down
Loading