Skip to content

Releases: halcyon-past/quarantine

v1.2.0: Google Cloud Storage (GCS) Backend & Remote Cache Hardening

Choose a tag to compare

@halcyon-past halcyon-past released this 27 Sep 06:03

We are excited to announce the release of quarantine-py v1.2.0! 🚀📦

This release adds first-class support for Google Cloud Storage (GCS), enabling fleets of workers running in Google Cloud (Cloud Run, GKE, Compute Engine) or hybrid environments to share a centralized quarantine, while delivering defense-in-depth security hardening across all remote object storage backends.


🌟 What's New in v1.2.0

1. Pluggable Storage Backend for Google Cloud Storage (GCS)

  • Centralized quarantine on GCS: Use dir="gs://bucket/prefix" (or --dir, or $QUARANTINE_DIR) to point workers directly to a GCS bucket. Inspect and replay failed records locally or in CI from anywhere with standard Google Cloud credentials.
  • Zero-dependency core preserved: Core quarantine-py remains 100% dependency-free standard library Python. GCS support is enabled as an optional extra:
    pip install "quarantine-py[gcs]"
  • Robust atomic commit design: Mirrors the local folder and S3 architectures. Record IDs are claimed via GCS generation preconditions (if_generation_match=0), and meta.json is uploaded last as the atomic commit point. Readers never observe uncommitted or partial uploads (ADR 0007).
  • Documentation: Full setup, ADC authentication, and minimal IAM permissions (roles/storage.objectUser) documented in Remote Storage Documentation.

2. Remote Cache Security Hardening (GCS & S3)

  • Symlink hijacking prevention: Added strict validation against pre-existing symlinks at the cache directory and record directory targets, raising StorageError if any symlink is detected or escapes containment.
  • TOCTOU race protection: Implemented _safe_write_cache_file utilizing atomic directory handles (dir_fd / openat) with O_DIRECTORY | O_NOFOLLOW, preventing directory-swap TOCTOU races during remote object materialization.
  • Cache destination protection: Replaced silent skips with explicit StorageError exceptions if a cache file destination is a pre-existing symlink, blocking cache poisoning attempts.
  • Path traversal rejection: Strict basename validation prevents malformed keys (e.g. ../) from escaping the cache directory during download.

3. Remote Debris Lifecycle Cleanup

  • Retained malformed and traversal-named object keys in remote inventory listing (_list_objects()) across both GCS and S3 backends. Operations such as quarantine clear, delete(), and purge_temp() can now find, measure, and clean up orphaned remote debris from the bucket.

📦 Installation & Upgrade

pip install --upgrade "quarantine-py"
# With GCS support:
pip install --upgrade "quarantine-py[gcs]"
# With S3 support:
pip install --upgrade "quarantine-py[s3]"

For the complete list of changes, check out the Changelog.

v1.0.0: The Distributed Storage Upgrade

Choose a tag to compare

@halcyon-past halcyon-past released this 30 Aug 20:48
5146c3f

We are incredibly proud to announce the release of quarantine-py v1.0.0! 🚀🎉

This milestone release brings a massive architectural upgrade to the quarantine library, turning it from a local-only utility into a fleet-ready, distributed tool for handling pipeline errors.

🌟 What's New in v1.0.0

  • Pluggable Storage Backends & S3 Support: You can now configure the quarantine to save records directly to an Amazon S3 bucket (s3://bucket/prefix), allowing ephemeral workers in Kubernetes, AWS Lambda, or Docker to share a centralized quarantine. You can then inspect and replay failures straight from your local machine! The core library remains dependency-free; simply install the S3 backend via pip install "quarantine-py[s3]".
  • Framework Recipes: We've added a comprehensive set of Recipes detailing how to seamlessly integrate quarantine into various ecosystems. Whether you're running a Pandas ETL job, an Airflow task, a web scraper, or a FastAPI background worker, you'll find tested, drop-in integration patterns.
  • Rigorous Benchmarks: We introduced a reproducible pyperf benchmark suite to transparently document the minimal performance overhead of the @quarantine decorator on the success path. Read our Benchmarks page for the methodology and exact numbers.

🛠️ Architecture & Extensibility

  • Public Backend Interface: The new storage backend interface (StorageBackend, open_store, register_backend) is fully public. Third parties can now easily implement their own backends (e.g., GCS, Azure, Redis) and register custom URL schemas without touching the core package.
  • Atomic Commit Point Design: The S3 implementation features a robust commit point design utilizing S3 conditional writes. This guarantees atomicity and ensures that readers never observe a partial record (detailed in ADR 0007).

A huge thank you to everyone who contributed to getting quarantine-py to 1.0! For the complete list of historical changes, check out the Changelog.

v0.3.0: Reliability & Observability Improvements

Choose a tag to compare

@halcyon-past halcyon-past released this 30 Aug 14:32
2680662

We are thrilled to announce the release of quarantine-py v0.3.0! 🚀

This release brings major improvements to retry resilience, poison-item detection, and system observability, making it even easier to build robust and fault-tolerant data pipelines.

✨ What's New

  • Exponential backoff with jitter: The new backoff_factor and jitter parameters help prevent thundering herds when external services struggle, offering fine-grained control over transient retries.
  • Poison-item detection: The new dead_after configuration acts as a built-in circuit breaker for records that repeatedly fail, automatically skipping them in blanket retries while preserving their state.
  • Retry lifecycle hooks: Seamlessly integrate with your telemetry stack using the new on_retry_success and on_retry_failure callbacks.
  • Observability recipes: Check out our new Observability Guide for drop-in integration snippets covering Prometheus, Datadog, Sentry, and standard logging.
  • Documentation Site: Our documentation has been completely overhauled and is now beautifully powered by mkdocs-material.

🛠️ Fixes & Under-the-Hood Improvements

  • Rock-solid reliability: We've introduced a robust property-based testing suite via Hypothesis to ensure invariants hold across all inputs, alongside a comprehensive end-to-end regression suite.
  • Transparent design: New Architecture Decision Records (docs/adr/) document the why and how of our technical choices.
  • Security first: We've formalized our security posture with SECURITY.md, pinned CI actions, and enabled PyPI attestations.
  • Documentation fixes: Corrected garbled API and usage guides from the previous release.

For full details, please refer to the CHANGELOG. Thank you for using quarantine-py!

v0.2.0

Choose a tag to compare

@halcyon-past halcyon-past released this 25 Aug 13:25
b708f1d

Added

  • Local Web Dashboard: Added a quarantine ui CLI command that spins up a lightweight, zero-dependency local web server to view tracebacks and payloads in a clean browser interface, and allows clicking to retry them.
  • Transient Retries: Added built-in transient retries (retries and backoff config options) to retry transient failures before committing items to quarantine. Support added for both synchronous and asynchronous functions.

v0.1.3

Choose a tag to compare

@halcyon-past halcyon-past released this 24 Aug 17:49
142983c

Fixed

  • Fixed documentation to consistently reference the quarantine-py PyPI package and correct GitHub URLs.
  • Fixed a PermissionError on Windows when acquiring the .index.lock file concurrently.

v0.1.2

Choose a tag to compare

@halcyon-past halcyon-past released this 23 Aug 20:20

Fixed

  • Fixed project URLs in pyproject.toml to point to the correct halcyon-past GitHub repository instead of the original placeholder.

v0.1.1

Choose a tag to compare

@halcyon-past halcyon-past released this 23 Aug 20:12

Fixed

  • Fixed documentation relative links in the README so they resolve correctly on PyPI.
  • Updated package name to quarantine-py to avoid naming collision on PyPI.

v0.1.0

Choose a tag to compare

@halcyon-past halcyon-past released this 23 Aug 19:56