Zhen Ye Claude Opus 4.6 commited on
Commit
8c60c06
·
1 Parent(s): 4c10904

feat(isr): add latest-frame storage for ISR cropping

Browse files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. jobs/storage.py +16 -0
jobs/storage.py CHANGED
@@ -39,6 +39,7 @@ class JobStorage:
39
  def __init__(self) -> None:
40
  self._jobs: Dict[str, JobInfo] = {}
41
  self._tracks: Dict[str, Dict[int, list]] = {} # job_id -> {frame_idx -> tracks}
 
42
  self._lock = RLock()
43
 
44
  def create(self, job: JobInfo) -> None:
@@ -69,6 +70,14 @@ class JobStorage:
69
  summary[idx] = count
70
  return summary
71
 
 
 
 
 
 
 
 
 
72
  def get(self, job_id: str) -> Optional[JobInfo]:
73
  with self._lock:
74
  return self._jobs.get(job_id)
@@ -85,6 +94,7 @@ class JobStorage:
85
  with self._lock:
86
  self._jobs.pop(job_id, None)
87
  self._tracks.pop(job_id, None)
 
88
  shutil.rmtree(get_job_directory(job_id), ignore_errors=True)
89
 
90
  def cleanup_expired(self, max_age: timedelta) -> None:
@@ -115,3 +125,9 @@ def set_track_data(job_id: str, frame_idx: int, tracks: list) -> None:
115
 
116
  def get_track_summary(job_id: str) -> dict:
117
  return get_job_storage().get_track_summary(job_id)
 
 
 
 
 
 
 
39
  def __init__(self) -> None:
40
  self._jobs: Dict[str, JobInfo] = {}
41
  self._tracks: Dict[str, Dict[int, list]] = {} # job_id -> {frame_idx -> tracks}
42
+ self._latest_frames: Dict[str, any] = {} # job_id -> np.ndarray
43
  self._lock = RLock()
44
 
45
  def create(self, job: JobInfo) -> None:
 
70
  summary[idx] = count
71
  return summary
72
 
73
+ def store_latest_frame(self, job_id: str, frame) -> None:
74
+ """Store the most recent frame for ISR cropping (no lock needed, single writer)."""
75
+ self._latest_frames[job_id] = frame
76
+
77
+ def get_latest_frame(self, job_id: str):
78
+ """Get the most recent frame for ISR cropping."""
79
+ return self._latest_frames.get(job_id)
80
+
81
  def get(self, job_id: str) -> Optional[JobInfo]:
82
  with self._lock:
83
  return self._jobs.get(job_id)
 
94
  with self._lock:
95
  self._jobs.pop(job_id, None)
96
  self._tracks.pop(job_id, None)
97
+ self._latest_frames.pop(job_id, None)
98
  shutil.rmtree(get_job_directory(job_id), ignore_errors=True)
99
 
100
  def cleanup_expired(self, max_age: timedelta) -> None:
 
125
 
126
  def get_track_summary(job_id: str) -> dict:
127
  return get_job_storage().get_track_summary(job_id)
128
+
129
+ def store_latest_frame(job_id: str, frame) -> None:
130
+ get_job_storage().store_latest_frame(job_id, frame)
131
+
132
+ def get_latest_frame(job_id: str):
133
+ return get_job_storage().get_latest_frame(job_id)