samwaugh commited on
Commit
a8562ee
·
1 Parent(s): 586c545

Try again

Browse files
Files changed (2) hide show
  1. backend/runner/app.py +41 -27
  2. backend/runner/config.py +6 -3
backend/runner/app.py CHANGED
@@ -72,10 +72,22 @@ if STUB_MODE or tasks is None:
72
  # Flask application & thread pool setup #
73
  # --------------------------------------------------------------------------- #
74
  app = Flask(__name__)
75
- CORS(app, resources={r"/*": {"origins": "*"}}) # allow SPA on :5173
 
 
 
 
 
 
 
 
 
 
76
 
77
  # Thread pool to handle background inference tasks
78
- executor = ThreadPoolExecutor(max_workers=4)
 
 
79
 
80
  # Use the Space data volume, not the repo folder
81
  from .config import (
@@ -136,11 +148,17 @@ def serve_css(filename):
136
  css_dir = Path(__file__).parent.parent.parent / "frontend" / "css"
137
  return send_from_directory(css_dir, filename)
138
 
 
139
  @app.route("/js/<path:filename>")
140
  def serve_js(filename):
141
- """Serve JavaScript files."""
142
- js_dir = Path(__file__).parent.parent.parent / "frontend" / "js"
143
- return send_from_directory(js_dir, filename)
 
 
 
 
 
144
 
145
  @app.route("/images/<path:filename>")
146
  def serve_images(filename):
@@ -151,37 +169,25 @@ def serve_images(filename):
151
 
152
  @app.route("/presign", methods=["POST"])
153
  def presign_upload():
154
- """
155
- Body: { "fileName": "myfile.jpg" }
156
- Response: {
157
- "runId": "...",
158
- "imageKey": "artifacts/<id>.jpg",
159
- "upload": { "url": "...", "fields": { } }
160
- }
161
- """
162
  run_id = uuid.uuid4().hex
163
  image_key = f"artifacts/{run_id}.jpg"
164
 
165
- # Fix: Use the correct Hugging Face Space URL
166
- # In Hugging Face Spaces, we need to construct the URL properly
167
- if os.getenv("HF_SPACE_URL"):
168
- # Use environment variable if set
169
- base_url = os.getenv("HF_SPACE_URL")
170
  else:
171
- # Fallback: try to get from request headers or use default
172
- base_url = request.headers.get('X-Forwarded-Proto', 'https') + "://" + request.headers.get('X-Forwarded-Host', request.host)
173
 
174
  upload_url = f"{base_url}/upload/{run_id}"
175
 
176
- response = jsonify({
177
  "runId": run_id,
178
  "imageKey": image_key,
179
- "upload": {
180
- "url": upload_url,
181
- "fields": {},
182
- },
183
  })
184
- return response
185
 
186
 
187
  @app.route("/upload/<run_id>", methods=["POST"])
@@ -557,5 +563,13 @@ def serve_marker_image(work_id: str, filename: str):
557
  # --------------------------------------------------------------------------- #
558
  if __name__ == "__main__": # invoked via python -m …
559
  # Use PORT environment variable for Hugging Face Spaces
560
- port = int(os.getenv("PORT", 8000))
561
  app.run(host="0.0.0.0", port=port, debug=False)
 
 
 
 
 
 
 
 
 
72
  # Flask application & thread pool setup #
73
  # --------------------------------------------------------------------------- #
74
  app = Flask(__name__)
75
+ # Configure CORS for HF Spaces
76
+ CORS(app, resources={
77
+ r"/*": {
78
+ "origins": [
79
+ "https://huggingface.co",
80
+ "https://*.hf.space",
81
+ "http://localhost:5173", # Local development
82
+ "http://localhost:3000" # Local development
83
+ ]
84
+ }
85
+ })
86
 
87
  # Thread pool to handle background inference tasks
88
+ # Reduce workers for HF Spaces memory constraints
89
+ max_workers = int(os.getenv("MAX_WORKERS", "2")) # Default to 2 for HF Spaces
90
+ executor = ThreadPoolExecutor(max_workers=max_workers)
91
 
92
  # Use the Space data volume, not the repo folder
93
  from .config import (
 
148
  css_dir = Path(__file__).parent.parent.parent / "frontend" / "css"
149
  return send_from_directory(css_dir, filename)
150
 
151
+ # Serve static frontend files with proper error handling
152
  @app.route("/js/<path:filename>")
153
  def serve_js(filename):
154
+ try:
155
+ js_dir = Path(__file__).parent.parent.parent / "frontend" / "js"
156
+ if not js_dir.exists():
157
+ return "JavaScript directory not found", 404
158
+ return send_from_directory(js_dir, filename)
159
+ except Exception as e:
160
+ print(f"Error serving JS file {filename}: {e}")
161
+ return "Internal server error", 500
162
 
163
  @app.route("/images/<path:filename>")
164
  def serve_images(filename):
 
169
 
170
  @app.route("/presign", methods=["POST"])
171
  def presign_upload():
 
 
 
 
 
 
 
 
172
  run_id = uuid.uuid4().hex
173
  image_key = f"artifacts/{run_id}.jpg"
174
 
175
+ # Use HF Spaces environment variables
176
+ if os.getenv("SPACE_URL"):
177
+ base_url = os.getenv("SPACE_URL")
178
+ elif os.getenv("SPACE_HOST"):
179
+ base_url = f"https://{os.getenv('SPACE_HOST')}"
180
  else:
181
+ # Fallback for local development
182
+ base_url = request.host_url.rstrip("/")
183
 
184
  upload_url = f"{base_url}/upload/{run_id}"
185
 
186
+ return jsonify({
187
  "runId": run_id,
188
  "imageKey": image_key,
189
+ "upload": {"url": upload_url, "fields": {}},
 
 
 
190
  })
 
191
 
192
 
193
  @app.route("/upload/<run_id>", methods=["POST"])
 
563
  # --------------------------------------------------------------------------- #
564
  if __name__ == "__main__": # invoked via python -m …
565
  # Use PORT environment variable for Hugging Face Spaces
566
+ port = int(os.getenv("PORT", 7860)) # Default to 7860 for HF Spaces
567
  app.run(host="0.0.0.0", port=port, debug=False)
568
+
569
+ @app.errorhandler(413) # Payload too large
570
+ def too_large(e):
571
+ return jsonify({"error": "File too large for HF Spaces"}), 413
572
+
573
+ @app.errorhandler(500)
574
+ def internal_error(e):
575
+ return jsonify({"error": "Internal server error"}), 500
backend/runner/config.py CHANGED
@@ -10,11 +10,14 @@ from pathlib import Path
10
  PROJECT_ROOT = Path(__file__).resolve().parents[2]
11
  DATA_READ_ROOT = PROJECT_ROOT / "data"
12
 
13
- # WRITE root (Space volume or tmp - writable)
14
- WRITE_ROOT = Path(os.getenv("WRITE_ROOT", os.getenv("DATA_ROOT", "/data")))
15
  if not WRITE_ROOT.exists() or not os.access(WRITE_ROOT, os.W_OK):
16
- print(f"⚠️ WRITE_ROOT {WRITE_ROOT} not writable, falling back to /tmp")
17
  WRITE_ROOT = Path("/tmp")
 
 
 
18
  else:
19
  print(f"✅ Using WRITE_ROOT: {WRITE_ROOT}")
20
 
 
10
  PROJECT_ROOT = Path(__file__).resolve().parents[2]
11
  DATA_READ_ROOT = PROJECT_ROOT / "data"
12
 
13
+ # WRITE root (Space volume - writable)
14
+ WRITE_ROOT = Path(os.getenv("HF_HOME", "/data"))
15
  if not WRITE_ROOT.exists() or not os.access(WRITE_ROOT, os.W_OK):
16
+ print(f"⚠️ WRITE_ROOT {WRITE_ROOT} not writable, trying /tmp")
17
  WRITE_ROOT = Path("/tmp")
18
+ if not os.access(WRITE_ROOT, os.W_OK):
19
+ print(f"❌ Neither /data nor /tmp are writable")
20
+ raise RuntimeError("No writable directory available")
21
  else:
22
  print(f"✅ Using WRITE_ROOT: {WRITE_ROOT}")
23