vector-auditor / src /services /cloudinary.py
AkshayM
production hardening: circuit breakers, graceful degradation, health checks, parallel uploads, HF Spaces deploy config
fc2fe9f
Raw
History Blame Contribute Delete
2.61 kB
"""Cloudinary storage backend. Optional — only used when CLOUDINARY_* env vars are set."""
import io
import logging
import os
from typing import Optional
from .secrets import get_secret
logger = logging.getLogger("rga_auditor.cloudinary")
class CloudinaryStorage:
def __init__(self) -> None:
self._enabled = False
cloud_name = get_secret("CLOUDINARY_CLOUD_NAME") or os.getenv("CLOUDINARY_CLOUD_NAME")
api_key = get_secret("CLOUDINARY_API_KEY") or os.getenv("CLOUDINARY_API_KEY")
api_secret = get_secret("CLOUDINARY_API_SECRET") or os.getenv("CLOUDINARY_API_SECRET")
if not (cloud_name and api_key and api_secret):
logger.info("Cloudinary not configured — using local disk storage")
return
try:
import cloudinary
import cloudinary.uploader
cloudinary.config(cloud_name=cloud_name, api_key=api_key, api_secret=api_secret, secure=True)
self._uploader = cloudinary.uploader
self._enabled = True
logger.info("Cloudinary storage enabled (cloud=%s)", cloud_name)
except Exception as e:
logger.warning("Cloudinary init failed: %s", e)
@property
def is_enabled(self) -> bool:
return self._enabled
def upload(self, content: bytes, public_id: str, resource_type: str = "raw") -> dict:
if not self._enabled:
raise RuntimeError("Cloudinary not configured")
return self._uploader.upload(
io.BytesIO(content),
public_id=public_id,
resource_type=resource_type,
overwrite=True,
)
def get_url(self, public_id: str, resource_type: str = "raw") -> str:
if not self._enabled:
return ""
import cloudinary
return cloudinary.CloudinaryResource(public_id=public_id, resource_type=resource_type).build_url()
def get_signed_url(self, public_id: str, resource_type: str = "image", format: str = "pdf", version: str = None) -> str:
if not self._enabled:
return ""
from cloudinary.utils import cloudinary_url
opts = dict(
resource_type=resource_type,
type="upload",
format=format,
sign_url=True,
)
if version:
opts["version"] = version
url, _ = cloudinary_url(public_id, **opts)
return url
_storage: Optional[CloudinaryStorage] = None
def get_cloudinary() -> CloudinaryStorage:
global _storage
if _storage is None:
_storage = CloudinaryStorage()
return _storage