victor HF Staff commited on
Commit
425876c
·
1 Parent(s): 8369e30

perf: in-memory feed cache — load once at startup, append on upload, zero disk reads

Browse files
Files changed (1) hide show
  1. app.py +36 -36
app.py CHANGED
@@ -355,7 +355,9 @@ def create(
355
  f.write(thumb_bytes)
356
  has_thumb = True
357
 
358
- # Save metadata
 
 
359
  meta = {
360
  "id": song_id,
361
  "title": title,
@@ -363,15 +365,19 @@ def create(
363
  "tags": tags,
364
  "lyrics": lyrics,
365
  "duration": audio_duration,
 
 
366
  "has_thumb": has_thumb,
367
  "created_at": datetime.now(timezone.utc).isoformat(),
368
  }
369
  with open(f"{song_dir}/meta.json", "w") as f:
370
  json.dump(meta, f, indent=2)
371
 
372
- result["community_url"] = f"{BUCKET_URL}/songs/{song_id}/{wav_name}"
373
- print(f"[create] Shared to community: {result['community_url']}")
374
- _invalidate_feed()
 
 
375
  except Exception as upload_err:
376
  print(f"[create] Community upload failed: {upload_err}")
377
 
@@ -406,43 +412,37 @@ def generate(
406
  raise
407
 
408
 
409
- # ── API: Community feed (cached) ──────────────────────────────────────────────
410
- import time as _time
411
- _feed_cache = {"data": "[]", "ts": 0}
412
- _FEED_TTL = 10 # seconds
413
 
414
- def _rebuild_feed() -> str:
415
- songs = []
416
  songs_dir = "/data/songs"
417
- if os.path.isdir(songs_dir):
418
- for song_id in os.listdir(songs_dir):
419
- meta_path = os.path.join(songs_dir, song_id, "meta.json")
420
- if os.path.isfile(meta_path):
421
- try:
422
- with open(meta_path) as f:
423
- meta = json.load(f)
424
- meta["audio_url"] = f"{BUCKET_URL}/songs/{song_id}/{song_id}.wav"
425
- thumb_path = os.path.join(songs_dir, song_id, "thumb.png")
426
- if os.path.isfile(thumb_path):
427
- meta["thumb_url"] = f"{BUCKET_URL}/songs/{song_id}/thumb.png"
428
- songs.append(meta)
429
- except Exception:
430
- pass
431
- songs.sort(key=lambda s: s.get("created_at", ""), reverse=True)
432
- return json.dumps(songs[:32])
433
-
434
- def _invalidate_feed():
435
- """Call after uploading a new song to bust the cache."""
436
- _feed_cache["ts"] = 0
437
 
438
  @app.api(name="community", concurrency_limit=4)
439
  def community() -> str:
440
- """List community songs from the bucket. Cached for 10s."""
441
- now = _time.monotonic()
442
- if now - _feed_cache["ts"] > _FEED_TTL:
443
- _feed_cache["data"] = _rebuild_feed()
444
- _feed_cache["ts"] = now
445
- return _feed_cache["data"]
446
 
447
 
448
  # ── Serve custom HTML frontend ────────────────────────────────────────────────
 
355
  f.write(thumb_bytes)
356
  has_thumb = True
357
 
358
+ # Save metadata to bucket (durability) + memory (instant reads)
359
+ audio_url = f"{BUCKET_URL}/songs/{song_id}/{wav_name}"
360
+ thumb_url = f"{BUCKET_URL}/songs/{song_id}/thumb.png" if has_thumb else None
361
  meta = {
362
  "id": song_id,
363
  "title": title,
 
365
  "tags": tags,
366
  "lyrics": lyrics,
367
  "duration": audio_duration,
368
+ "audio_url": audio_url,
369
+ "thumb_url": thumb_url,
370
  "has_thumb": has_thumb,
371
  "created_at": datetime.now(timezone.utc).isoformat(),
372
  }
373
  with open(f"{song_dir}/meta.json", "w") as f:
374
  json.dump(meta, f, indent=2)
375
 
376
+ # Prepend to in-memory feed (no re-scan needed)
377
+ _feed_songs.insert(0, meta)
378
+
379
+ result["community_url"] = audio_url
380
+ print(f"[create] Shared to community: {audio_url}")
381
  except Exception as upload_err:
382
  print(f"[create] Community upload failed: {upload_err}")
383
 
 
412
  raise
413
 
414
 
415
+ # ── Community feed (in-memory, loaded once at startup) ───────────────────────
416
+ _feed_songs = []
 
 
417
 
418
+ def _load_feed_from_disk():
419
+ """One-time scan at startup to populate memory from bucket."""
420
  songs_dir = "/data/songs"
421
+ if not os.path.isdir(songs_dir):
422
+ print("[feed] /data/songs not found, starting with empty feed")
423
+ return
424
+ for song_id in os.listdir(songs_dir):
425
+ meta_path = os.path.join(songs_dir, song_id, "meta.json")
426
+ if os.path.isfile(meta_path):
427
+ try:
428
+ with open(meta_path) as f:
429
+ meta = json.load(f)
430
+ meta["audio_url"] = f"{BUCKET_URL}/songs/{song_id}/{song_id}.wav"
431
+ thumb_path = os.path.join(songs_dir, song_id, "thumb.png")
432
+ if os.path.isfile(thumb_path):
433
+ meta["thumb_url"] = f"{BUCKET_URL}/songs/{song_id}/thumb.png"
434
+ _feed_songs.append(meta)
435
+ except Exception:
436
+ pass
437
+ _feed_songs.sort(key=lambda s: s.get("created_at", ""), reverse=True)
438
+ print(f"[feed] Loaded {len(_feed_songs)} songs into memory")
439
+
440
+ _load_feed_from_disk()
441
 
442
  @app.api(name="community", concurrency_limit=4)
443
  def community() -> str:
444
+ """List community songs served from memory, zero disk I/O."""
445
+ return json.dumps(_feed_songs[:50])
 
 
 
 
446
 
447
 
448
  # ── Serve custom HTML frontend ────────────────────────────────────────────────