audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: remove non-existent filesystem storage backend references (#819)

the streaming-uploads.md doc referenced a filesystem.py storage backend
that was either never implemented or removed at some point. only r2.py
exists in the storage directory.

removed:
- section 3 describing filesystem.py implementation
- references to "both backends" throughout the doc
- filesystem.py from the references section

closes #787

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

authored by

nate nowack
Claude Opus 4.5
and committed by
GitHub
f61ce5d1 27c42301

+5 -53
+5 -53
docs/backend/streaming-uploads.md
··· 34 34 ### goals achieved 35 35 1. constant memory usage regardless of file size 36 36 2. maintained backward compatibility (same file_id generation) 37 - 3. supports both R2 and filesystem backends 38 - 4. no changes to upload endpoint API 39 - 5. proper test coverage added 37 + 3. no changes to upload endpoint API 38 + 4. proper test coverage added 40 39 41 40 ### current flow (constant memory) 42 41 ```python ··· 151 150 return file_id 152 151 ``` 153 152 154 - ### 3. filesystem storage backend 155 - 156 - **file**: `src/backend/storage/filesystem.py` 157 - 158 - **implementation**: 159 - - uses `hash_file_chunked()` for constant memory hashing 160 - - uses `anyio` for async file I/O instead of blocking operations 161 - - writes file in chunks for constant memory usage 162 - - supports both audio and image files 163 - 164 - ```python 165 - # actual implementation (simplified) 166 - async def save(self, file: BinaryIO, filename: str) -> str: 167 - """save media file using streaming write. 168 - 169 - uses chunked hashing and async file I/O for constant 170 - memory usage regardless of file size. 171 - """ 172 - # compute hash in chunks (constant memory) 173 - file_id = hash_file_chunked(file)[:16] 174 - 175 - # determine file extension and type 176 - ext = Path(filename).suffix.lower() 177 - 178 - # try audio format first 179 - audio_format = AudioFormat.from_extension(ext) 180 - if audio_format: 181 - file_path = self.base_path / "audio" / f"{file_id}{ext}" 182 - else: 183 - # handle image formats... 184 - pass 185 - 186 - # write file using async I/O in chunks (constant memory, non-blocking) 187 - # file pointer already reset by hash_file_chunked 188 - async with await anyio.open_file(file_path, "wb") as dest: 189 - while True: 190 - chunk = file.read(CHUNK_SIZE) 191 - if not chunk: 192 - break 193 - await dest.write(chunk) 194 - 195 - return file_id 196 - ``` 197 - 198 - ### 4. upload endpoint 153 + ### 3. upload endpoint 199 154 200 155 **file**: `src/backend/api/tracks.py` 201 156 ··· 205 160 - keeps small files (<1MB) in memory 206 161 - automatically spools larger files to disk 207 162 - provides file-like interface that our streaming functions expect 208 - - works seamlessly with both storage backends 163 + - works seamlessly with R2 storage backend 209 164 210 165 ## testing 211 166 ··· 291 246 - memory usage stays constant (~10-16MB per upload) 292 247 - file_id generation remains consistent (backward compatible) 293 248 - supports concurrent uploads without OOM 294 - - both R2 and filesystem backends working correctly 295 249 296 250 ## backward compatibility 297 251 ··· 312 266 313 267 ### very large files (>100MB) 314 268 - boto3 automatically handles multipart upload 315 - - filesystem streaming works for any size 316 269 - only limited by storage capacity, not RAM 317 270 318 271 ### network failures during upload 319 272 - boto3 multipart upload can retry failed parts 320 - - filesystem writes are atomic per chunk 321 273 - FastAPI handles connection errors 322 274 323 275 ### concurrent uploads ··· 359 311 360 312 ## references 361 313 362 - - implementation: `src/backend/storage/r2.py`, `src/backend/storage/filesystem.py` 314 + - implementation: `src/backend/storage/r2.py` 363 315 - utilities: `src/backend/utilities/hashing.py` 364 316 - tests: `tests/utilities/test_hashing.py`, `tests/api/test_tracks.py` 365 317 - PR: #182