Skip to content

Experimental: AWS S3 storage driver#1388

Open
jmaeagle99 wants to merge 1 commit intotemporalio:mainfrom
jmaeagle99:s3-driver-extra
Open

Experimental: AWS S3 storage driver#1388
jmaeagle99 wants to merge 1 commit intotemporalio:mainfrom
jmaeagle99:s3-driver-extra

Conversation

@jmaeagle99
Copy link
Contributor

@jmaeagle99 jmaeagle99 commented Mar 23, 2026

What was changed

  • Add an AWS S3 storage driver integration module that ships with the Python SDK.
    • Driver can consume arbitrary clients via an S3StorageDriverClient implementation.
    • Module provide a client implementation for the aioboto3 library.
    • Driver allows static setting of the bucket or a callable to dynamically determine the name of the target bucket for each uploaded payload.
    • Driver uploads payloads using content addressable storage under a structured object key format that allows for external lifecycle management.
    • Driver checks for key existence before attempting to upload large payloads.
    • Driver verifies integrity of externally retrieved payload as modified content would impact workflow determinism.
  • Add an aws-s3 extra to the temporalio package to assist in including the dependencies for the aioboto3 client implementation.
  • Add unit and integration tests that use the moto server to simulate an S3 server.

Why?

Provide a default driver for externally storing large payloads in AWS S3.

Checklist

  1. Closes S3 External Storage Driver - Python #1390

  2. How was this tested:

  • Existing tests
  • New S3 driver unit test and integration tests via moto AWS S3 HTTP service emulator
  • Manual testing targeting real AWS S3 bucket
  1. Any docs updates needed? Yes

@jmaeagle99 jmaeagle99 force-pushed the s3-driver-extra branch 5 times, most recently from 658d2e1 to 5d6cd7e Compare March 25, 2026 05:37
@jmaeagle99 jmaeagle99 marked this pull request as ready for review March 25, 2026 05:43
@jmaeagle99 jmaeagle99 requested a review from a team as a code owner March 25, 2026 05:43
@jmaeagle99 jmaeagle99 changed the title Experimental: AWS S3 driver extra package Experimental: AWS S3 storage driver Mar 25, 2026
@@ -0,0 +1,13 @@
"""Amazon S3 storage driver for Temporal external payload storage."""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add experimental

self,
client: S3StorageDriverClient,
bucket: str | Callable[[StorageDriverStoreContext, Payload], str],
driver_name: str | None = None,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set default here and validate non-empty in init

a bucket name. A callable allows dynamic per-payload bucket
selection.
driver_name: Name of this driver instance. Defaults to
``"aws.s3driver"``. Override only when registering
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only need to override when registering multiple of the same type.


digest_segments = f"/d/sha256/{hash_digest}"

key = f"v0{namespace_segments}{context_segments}{digest_segments}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate that missing segments or invalid characters are sanitized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially for user provided information such as workflow ID and activity ID.

This API is experimental.
"""

def __init__(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra config knobs:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disable hash check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disable object existence check

def new_aioboto3_client(client: S3Client) -> Aioboto3StorageDriverClient:
"""Create an :class:`S3StorageDriverClient` from an aioboto3 S3 client.

This is a convenience factory. Equivalent to ``Aioboto3StorageDriverClient(client)``.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

async def object_exists(self, *, bucket: str, key: str) -> bool:
"""Check existence via aioboto3's ``head_object``."""
try:
await self._client.head_object(Bucket=bucket, Key=key)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an exists method that doesn't raise?

Comment on lines +25 to +26
async with session.client("s3") as s3_client:
driver = S3StorageDriver(client=s3_client, bucket="my-temporal-payloads")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix to use new_aioboto3_client method

),
)
session = aioboto3.Session()
async with session.client("s3") as s3_client:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use new_aioboto3_client method

@@ -0,0 +1,454 @@
"""Worker integration tests for S3StorageDriver key structure.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to tests/contrib/aws/s3driver

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

S3 External Storage Driver - Python

1 participant