Skip to main content

Shared, settings-agnostic media primitives (object storage + job contracts) for m8 media services.

Project description

media-sdk-m8

Shared, settings-agnostic media primitives for the m8 media stack. Consumed by:

  • media-service-m8 — the live API (job producer)
  • media-worker-m8 — the async ARQ worker (job consumer)

The SDK is framework-agnostic (no FastAPI, no auth-sdk, no pydantic-settings) and imgtools-free. It owns no business logic, no database, and no preset knowledge — callers pass an explicit config object; the SDK never reads settings or env.

Contents

Object storage — media_sdk_m8.storage

ObjectStorage is a thin wrapper over the MinIO SDK. It is constructed from an explicit ObjectStorageConfig (endpoint, credentials, region, TLS, and the default presigned-URL lifetime), so it has no dependency on any service's settings module.

from media_sdk_m8 import ObjectStorage, ObjectStorageConfig

config = ObjectStorageConfig(
    endpoint="minio:9000",
    access_key="...",
    secret_key="...",
    secure=False,
    region="us-east-1",
    presigned_expire_seconds=300,
)
storage = ObjectStorage(config)

data = storage.get_object(bucket="private-media", object_key="key")
storage.put_object(
    bucket="public-media",
    object_key="key/variants/thumb_webp/thumb.webp",
    data=variant_bytes,
    content_type="image/webp",
)

Methods: stat_object, remove_object, get_object_head, get_object, list_object_keys, put_object, set_object_content_type, copy_object, post_upload_url, presigned_post_object, presigned_get_object.

list_object_keys(*, bucket, prefix="") recursively yields stored keys — the read primitive an orphan reconciler uses to find bytes that have no DB row.

Presigned-URL expiry defaults to config.presigned_expire_seconds and can be overridden per call via expires_seconds.

Browser-direct presigned URLs (public endpoint)

When the browser cannot resolve the internal MinIO host (e.g. minio:9000 in a container stack), set the two optional endpoint fields:

config = ObjectStorageConfig(
    endpoint="minio:9000",       # internal — service and worker only
    access_key="...",
    secret_key="...",
    secure=False,
    region="us-east-1",
    public_endpoint="127.0.0.1:9005",  # host:port, no scheme — browser-reachable
    public_secure=False,               # scheme for public URLs; falls back to `secure` when None
)
  • public_endpoint — the host the browser hits, in host:port form (no scheme). post_upload_url returns a URL built from this host/scheme; presigned_get_object is signed by a client bound to this endpoint (SigV4 GET signatures bind the Host, so the signing client must match the endpoint the browser sends the request to).
  • public_secure — TLS flag for the public endpoint. Falls back to secure when omitted.

All internal ops (stat_object, get_object, copy_object, etc.) always use endpoint, not public_endpoint. When public_endpoint is None (default), post_upload_url and presigned_get_object behave identically to before — compatible with proxy-through deployments and media-worker-m8.

Reverse-proxy requirement: a proxy (e.g. Traefik) forwarding requests to MinIO must preserve the Host header (passHostHeader: true in Traefik, which is its default) so the SigV4 signature validates on arrival.

Job contracts — media_sdk_m8.contracts

Self-contained Pydantic v2 models that form the producer↔consumer contract. The service builds and enqueues them; the worker deserializes and acts on them.

  • ScanJobPayload{ object_id, bucket, object_key, owner_user_id }
  • VariantSpec{ variant_name, output_options, target_bucket, target_key }; output_options is the imgtools-shaped dict (one format + name) built by the service, so the worker needs no preset or key knowledge.
  • VariantJobPayload{ job_id, media_object_id, source_bucket, source_object_key, specs }
  • OutboxEventPayload{ event_id, event_type, object_id, payload, created_at }; the outbound webhook contract. media-service-m8 writes one per state change to its transactional outbox and POSTs this HMAC-signed body to subscriber URLs, so a subscriber needs only this shape to verify and consume an event.

Development

pip install -e ".[dev]"
ruff format . && ruff check .
mypy media_sdk_m8 --ignore-missing-imports
bandit -r media_sdk_m8 --severity-level medium
pytest --cov=media_sdk_m8 --cov-report=term-missing --cov-fail-under=100

Published to PyPI on tagged release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

media_sdk_m8-0.5.0.tar.gz (52.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

media_sdk_m8-0.5.0-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file media_sdk_m8-0.5.0.tar.gz.

File metadata

  • Download URL: media_sdk_m8-0.5.0.tar.gz
  • Upload date:
  • Size: 52.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for media_sdk_m8-0.5.0.tar.gz
Algorithm Hash digest
SHA256 327904e1fff226629d6624948bab6fae86ea4f05dafeca5086158b098f6a5a16
MD5 b809505eb0e15f79ee3b87909cdae752
BLAKE2b-256 1051421b59663156a06af7ac32496fd1ce20f136e49db9635fcf5347f8b1ba9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for media_sdk_m8-0.5.0.tar.gz:

Publisher: PiPy.yml on mano8/media-sdk-m8

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file media_sdk_m8-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: media_sdk_m8-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 17.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for media_sdk_m8-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 41a7e14ccb061ea127d84bca9eb0982dc028ba0d16c01cff37866745b2f5e8c7
MD5 f8589dbff5523aa903cea390d2fdf978
BLAKE2b-256 b9b0f6392dd565d2dcdad5d5230d0bbd10358ff13d7bc8f9c6d2a788beb61c6d

See more details on using hashes here.

Provenance

The following attestation bundles were made for media_sdk_m8-0.5.0-py3-none-any.whl:

Publisher: PiPy.yml on mano8/media-sdk-m8

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page