HCAI-Lab/w2-consensus-deepdive-unlearning-artifacts / social-data-attribution-w2 /scripts /modal /cache_manifest.py
| """One-time download of SOC-95 manifest parquets from R2 to a persistent volume. | |
| Usage: | |
| uv run modal run scripts/modal/cache_manifest.py | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| import os | |
| import time | |
| from pathlib import Path | |
| import modal | |
| logger = logging.getLogger("cache_manifest") | |
| R2_BUCKET_NAME = "soc127-dedup" | |
| R2_MANIFEST_PREFIX = "soc95-manifest/data" | |
| R2_ENDPOINT_URL = "https://0934ab8e84ac8f4e81decaf3eb121337.r2.cloudflarestorage.com" | |
| R2_SECRET_NAME = "r2-credentials" | |
| _local_path = Path(__file__).resolve() | |
| if len(_local_path.parents) > 2: | |
| _cache_image = modal.Image.debian_slim(python_version="3.12").pip_install( | |
| "boto3>=1.37.0" | |
| ) | |
| else: | |
| _cache_image = modal.Image.debian_slim(python_version="3.12") | |
| app = modal.App("soc134-cache-manifest") | |
| r2_secret = modal.Secret.from_name(R2_SECRET_NAME) | |
| manifest_volume = modal.Volume.from_name( | |
| "soc134-manifest-cache", create_if_missing=True | |
| ) | |
| MANIFEST_MOUNT = "/manifests" | |
| def _get_s3_client(): | |
| import boto3 | |
| env_aliases = { | |
| "AWS_ACCESS_KEY_ID": ("AWS_ACCESS_KEY_ID", "R2_ACCESS_KEY_ID", "access_key_id"), | |
| "AWS_SECRET_ACCESS_KEY": ( | |
| "AWS_SECRET_ACCESS_KEY", | |
| "R2_SECRET_ACCESS_KEY", | |
| "secret_access_key", | |
| ), | |
| } | |
| for target, aliases in env_aliases.items(): | |
| if target in os.environ and os.environ[target]: | |
| continue | |
| for alias in aliases: | |
| value = os.environ.get(alias) | |
| if value: | |
| os.environ[target] = value | |
| break | |
| endpoint = os.environ.get("AWS_ENDPOINT_URL", R2_ENDPOINT_URL) | |
| return boto3.client( | |
| "s3", | |
| endpoint_url=endpoint, | |
| aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"], | |
| aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"], | |
| region_name="auto", | |
| ) | |
| def list_manifest_keys() -> list[str]: | |
| s3 = _get_s3_client() | |
| keys: list[str] = [] | |
| prefix = R2_MANIFEST_PREFIX.rstrip("/") + "/" | |
| paginator = s3.get_paginator("list_objects_v2") | |
| for page in paginator.paginate(Bucket=R2_BUCKET_NAME, Prefix=prefix): | |
| for obj in page.get("Contents", []): | |
| k = obj["Key"] | |
| if k.endswith(".parquet"): | |
| keys.append(k) | |
| return sorted(keys) | |
| def cache_manifest_chunk( | |
| keys: list[str], | |
| chunk_index: int, | |
| ) -> dict[str, object]: | |
| t0 = time.monotonic() | |
| s3 = _get_s3_client() | |
| downloaded = 0 | |
| skipped = 0 | |
| failed = 0 | |
| total_bytes = 0 | |
| errors: list[str] = [] | |
| for key in keys: | |
| dest = Path(MANIFEST_MOUNT) / key | |
| if dest.exists() and dest.stat().st_size > 0: | |
| skipped += 1 | |
| continue | |
| max_retries = 3 | |
| for attempt in range(max_retries): | |
| try: | |
| resp = s3.get_object(Bucket=R2_BUCKET_NAME, Key=key) | |
| data = resp["Body"].read() | |
| dest.parent.mkdir(parents=True, exist_ok=True) | |
| tmp = dest.with_suffix(".tmp") | |
| tmp.write_bytes(data) | |
| tmp.rename(dest) | |
| downloaded += 1 | |
| total_bytes += len(data) | |
| break | |
| except Exception as exc: | |
| if attempt == max_retries - 1: | |
| error_msg = f"{key}: {type(exc).__name__}: {exc}" | |
| errors.append(error_msg) | |
| failed += 1 | |
| else: | |
| time.sleep((attempt + 1) * 3) | |
| manifest_volume.commit() | |
| elapsed = time.monotonic() - t0 | |
| return { | |
| "chunk_index": chunk_index, | |
| "total_keys": len(keys), | |
| "downloaded": downloaded, | |
| "skipped": skipped, | |
| "failed": failed, | |
| "total_bytes": total_bytes, | |
| "elapsed_seconds": round(elapsed, 1), | |
| "errors": errors[:5], | |
| } | |
| def _slice_for_chunk(items: list[str], chunk_index: int, chunk_count: int) -> list[str]: | |
| chunk_size = len(items) // chunk_count | |
| remainder = len(items) % chunk_count | |
| start = chunk_index * chunk_size + min(chunk_index, remainder) | |
| end = start + chunk_size + (1 if chunk_index < remainder else 0) | |
| return items[start:end] | |
| def main( | |
| chunk_count: int = 64, | |
| dry_run: bool = False, | |
| ) -> None: | |
| print("Listing manifest parquets from R2...") | |
| all_keys = list_manifest_keys.remote() | |
| print(f"Found {len(all_keys):,} manifest parquet files") | |
| if dry_run: | |
| print("Dry run - not downloading") | |
| return | |
| chunks = [_slice_for_chunk(all_keys, i, chunk_count) for i in range(chunk_count)] | |
| non_empty = [(keys, i) for i, keys in enumerate(chunks) if keys] | |
| print(f"Launching {len(non_empty)} workers...") | |
| results = list(cache_manifest_chunk.starmap(non_empty)) | |
| total_downloaded = sum(r.get("downloaded", 0) for r in results) | |
| total_skipped = sum(r.get("skipped", 0) for r in results) | |
| total_failed = sum(r.get("failed", 0) for r in results) | |
| total_bytes = sum(r.get("total_bytes", 0) for r in results) | |
| print("\nManifest cache results:") | |
| print(f" Total files: {len(all_keys):,}") | |
| print(f" Downloaded: {total_downloaded:,}") | |
| print(f" Skipped: {total_skipped:,}") | |
| print(f" Failed: {total_failed:,}") | |
| print(f" Bytes written: {total_bytes / (1024**2):.1f} MB") | |
| if total_failed > 0: | |
| for r in results: | |
| for err in r.get("errors", []): | |
| print(f" Error: {err}") | |
Xet Storage Details
- Size:
- 5.77 kB
- Xet hash:
- 5e5ff597a068369d2be792481aca9d0a436224d4c90b3008ba79f5c4c7a0d89b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.