Skip to content

Commit 6bb9ea2

Browse files
committed
feat: implement Direct-to-R2 upload on worker to bypass Base64 bottleneck
1 parent 16c5040 commit 6bb9ea2

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ numpy<2
22
opencv-python-headless==4.10.0.84
33
Pillow==10.4.0
44
tqdm==4.64.0
5+
boto3==1.34.106

rp_handler.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,56 @@
22
import sys
33
import base64
44
import urllib.request
5+
import boto3
6+
from botocore.config import Config
57

68
import cv2
79
import numpy as np
810
import torch
911
import runpod
1012

13+
# Initialize S3 client for R2 (Lazy)
14+
s3_client = None
15+
16+
def get_s3_client():
17+
global s3_client
18+
if s3_client is None:
19+
access_key = os.environ.get("R2_ACCESS_KEY_ID")
20+
secret_key = os.environ.get("R2_SECRET_ACCESS_KEY")
21+
endpoint = os.environ.get("R2_ENDPOINT")
22+
if all([access_key, secret_key, endpoint]):
23+
s3_client = boto3.client(
24+
"s3",
25+
endpoint_url=endpoint,
26+
aws_access_key_id=access_key,
27+
aws_secret_access_key=secret_key,
28+
config=Config(signature_version="s3v4"),
29+
region_name="auto",
30+
)
31+
return s3_client
32+
33+
def upload_to_r2(buffer, key, content_type="image/jpeg"):
34+
client = get_s3_client()
35+
if client is None:
36+
return None
37+
38+
bucket = os.environ.get("R2_BUCKET_NAME", "stockgen-ai")
39+
try:
40+
client.put_object(
41+
Bucket=bucket,
42+
Key=key,
43+
Body=buffer,
44+
ContentType=content_type,
45+
CacheControl="public, max-age=31536000"
46+
)
47+
custom_domain = os.environ.get("R2_CUSTOM_DOMAIN")
48+
if custom_domain:
49+
return f"{custom_domain.rstrip('/')}/{key}"
50+
return f"{os.environ.get('R2_ENDPOINT').rstrip('/')}/{bucket}/{key}"
51+
except Exception as e:
52+
print(f"❌ R2 Upload Failed: {str(e)}")
53+
return None
54+
1155
# Patch basicsr compatibility with newer PyTorch/torchvision
1256
import torchvision.transforms.functional as F_tv
1357
import types
@@ -240,13 +284,24 @@ def handler(job):
240284
if not success:
241285
return {"error": "Failed to encode output image"}
242286

287+
# Direct-to-R2 Upload Logic
288+
r2_url = None
289+
r2_key = job_input.get("r2_key") # Target path like "users/uid/batches/bid/jid.jpg"
290+
291+
if r2_key:
292+
print(f"☁️ [Direct-to-R2] Uploading result to: {r2_key}")
293+
r2_url = upload_to_r2(encoded_img.tobytes(), r2_key)
294+
if r2_url:
295+
print(f"✅ [Direct-to-R2] Success: {r2_url}")
296+
243297
b64 = base64.b64encode(encoded_img).decode("utf-8")
244298

245299
h, w = img.shape[:2]
246300
oh, ow = output.shape[:2]
247301

248302
return {
249-
"image": b64,
303+
"image": b64 if not r2_url else None, # Skip Base64 if R2 success to save bandwidth
304+
"r2_url": r2_url,
250305
"image_format": "jpg",
251306
"model": model_name,
252307
"face_enhance_applied": face_enhance,

0 commit comments

Comments
 (0)