Skip to content

Conversation

grdsdev
Copy link
Contributor

@grdsdev grdsdev commented Sep 23, 2025

RFC: TUS Resumable Upload Protocol Implementation

Summary

This PR introduces a Swift implementation of the TUS (Tus Resumable Upload Protocol) 1.0.0 for the Supabase Storage module. This is a port of the existing Kotlin implementation from the community supabase-kt library.

Background

The TUS protocol enables resumable file uploads, allowing clients to pause and resume uploads even after network interruptions or application restarts. This is particularly valuable for:

  • Large file uploads that may take significant time
  • Mobile applications with unstable network connections
  • Applications where upload reliability is critical

Implementation

This implementation is a direct port of the Kotlin TUS implementation from:

Key Components

  • Fingerprint: Upload identification using source path and file size
  • ResumableCache: Protocol and types for caching upload sessions with disk-based persistence
  • ResumableClient: Core TUS protocol client implementation with proper header handling
  • ResumableUpload: Upload management with chunked streaming, pause/resume, and retry logic
  • ResumableUploadState: State representation with real-time progress tracking

Features

Resumable Uploads: Automatic resumption from last uploaded offset
Progress Tracking: Real-time progress updates via AsyncStream
Pause/Resume: Programmatic control over upload state
Retry Logic: Configurable retry attempts with exponential backoff
Thread Safety: Actor-based design for concurrent access
Disk Persistence: Upload sessions survive app restarts
TUS 1.0.0 Compliance: Full protocol implementation

Usage Example

// Create a resumable upload
let upload = try storageApi.from("bucket")
  .createResumableUpload(
    path: "large-file.mp4",
    data: fileData,
    options: ResumableUploadOptions(
      chunkSize: 6 * 1024 * 1024, // 6MB chunks
      retryLimit: 3
    )
  )

// Monitor progress
Task {
  for await state in upload.state {
    print("Progress: \(state.progress * 100)%")
    
    if state.isDone {
      print("Upload completed!")
      break
    }
  }
}

// Start the upload
try await upload.start()

// Pause/resume as needed
upload.pause()
try await upload.start() // Resume from last offset

API Design

The implementation follows Swift conventions while maintaining compatibility with the TUS protocol:

  • Uses actor for thread-safe state management
  • Leverages AsyncStream for reactive progress updates
  • Integrates seamlessly with existing StorageFileApi
  • Provides type-safe configuration options

Testing

  • Unit tests for core components
  • Integration tests with TUS server
  • Network interruption scenarios
  • Large file upload validation
  • Memory usage profiling

Migration Path

This is an additive feature that doesn't break existing upload functionality. Developers can opt-in to resumable uploads when needed while continuing to use standard uploads for smaller files.

Questions for Review

  1. API Surface: Should resumable uploads be the default for files above a certain size threshold?
  2. Cache Strategy: Is disk-based caching the right default, or should we offer both memory and disk options?
  3. Error Handling: Are the current retry strategies sufficient for production use?
  4. Integration: Should this be integrated directly into the existing upload() methods or kept as separate API?

Related Links

🤖 Generated with Claude Code

grdsdev and others added 2 commits September 23, 2025 07:55
Add complete TUS (Tus Resumable Upload Protocol) 1.0.0 implementation for Storage module:

- Fingerprint: Upload identification using source path and file size
- ResumableCache: Protocol and types for caching upload sessions
- MemoryResumableCache: Thread-safe actor-based in-memory cache
- ResumableUploadState: State representation with progress tracking
- ResumableClient: Core TUS protocol client implementation
- ResumableUpload: Upload management with chunked streaming and retry logic

Features:
- Resumable uploads with automatic retry on failure
- Progress tracking via AsyncStream
- Pause/resume functionality
- Thread-safe memory caching
- Integration with existing StorageFileApi

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

Co-Authored-By: Claude <[email protected]>
- Remove unnecessary public modifiers for internal types
- Add DiskResumableCache as default cache implementation
- Simplify Fingerprint interface by removing CustomStringConvertible
- Make cancel() method synchronous for better usability
- Switch default cache from memory to disk-based storage

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

Co-Authored-By: Claude <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant