Skip to content

feat(service): Implement MultipartUploadBackend on InMemory and LocalFs#456

Merged
lcian merged 5 commits into
mainfrom
lcian/feat/multipart-upload-other-backends
May 12, 2026
Merged

feat(service): Implement MultipartUploadBackend on InMemory and LocalFs#456
lcian merged 5 commits into
mainfrom
lcian/feat/multipart-upload-other-backends

Conversation

@lcian
Copy link
Copy Markdown
Member

@lcian lcian commented May 4, 2026

⚠️ Stacked on #454

Implements MultipartUploadBackend on InMemoryBackend and LocalFsBackend, used for tests.
TieredStorage will come in the next PR.

InMemoryBackend now stores some auxiliary data structures dedicated to multipart uploads, while LocalFs uses a __multipart__/ directory where to store metadata and parts for each ongoing upload.

Close FS-349

@lcian lcian changed the title feat(multipart): implement MultipartUploadBackend for all backends feat(service): Implement MultipartUploadBackend on InMemory and LocalFs May 4, 2026
@lcian lcian changed the base branch from main to lcian/test/gcs-multipart May 4, 2026 09:43
@lcian lcian marked this pull request as ready for review May 4, 2026 09:55
@lcian lcian requested a review from a team as a code owner May 4, 2026 09:55
Comment thread objectstore-service/src/backend/in_memory.rs Outdated
Comment thread objectstore-service/src/backend/in_memory.rs Outdated
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 5, 2026

Comment thread objectstore-service/src/backend/local_fs.rs
Comment thread objectstore-service/src/backend/in_memory.rs
}

#[async_trait::async_trait]
impl MultipartUploadBackend for LocalFsBackend {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this impl will be pretty susceptible to 5XXs. operations don't acquire any sort of lock on the upload dir so a concurrent abort/complete request can remove the upload dir in the middle of other concurrent handlers. if/when we want this backend to be production-worthy we probably want to make sure races result in an appropriate 4XX

Copy link
Copy Markdown
Member Author

@lcian lcian May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yes I see what you mean. We need some sort of lock files. Filed as a follow-up we need to eventually do for self-hosted support: https://linear.app/getsentry/issue/PF-81/avoid-races-in-fs-backend

@lcian lcian force-pushed the lcian/test/gcs-multipart branch from 36f1380 to 0e21505 Compare May 12, 2026 09:54
Base automatically changed from lcian/test/gcs-multipart to main May 12, 2026 10:00
lcian added 2 commits May 12, 2026 12:43
…lidation

InMemoryBackend::complete_multipart was calling .remove() on the
multipart store before validating parts. If validation failed, the
upload was permanently destroyed and the client could not retry.

Changed to .get() for validation, only removing after successful
assembly. Added retry-after-failure test coverage for both InMemory
and LocalFs backends.
@lcian lcian force-pushed the lcian/feat/multipart-upload-other-backends branch from e8a193d to 803c658 Compare May 12, 2026 10:43
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 95.74830% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.91%. Comparing base (afc8a38) to head (78f0d7f).

Files with missing lines Patch % Lines
objectstore-service/src/backend/local_fs.rs 92.83% 22 Missing ⚠️
objectstore-service/src/backend/in_memory.rs 98.93% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #456      +/-   ##
==========================================
+ Coverage   86.45%   86.91%   +0.46%     
==========================================
  Files          77       77              
  Lines       10806    11394     +588     
==========================================
+ Hits         9342     9903     +561     
- Misses       1464     1491      +27     
Components Coverage Δ
Rust Backend 91.80% <95.74%> (+0.28%) ⬆️
Rust Client 80.10% <ø> (ø)
Python Client 86.36% <ø> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

upload_part and complete_multipart were buffering entire payloads in
memory. Both now use StreamReader + BufWriter + tokio::io::copy to
stream data to disk, matching the put_object pattern.
Comment thread objectstore-service/src/backend/in_memory.rs
Comment thread objectstore-service/src/backend/local_fs.rs
lcian added 2 commits May 12, 2026 13:09
Add a TODO to validate bytes copied against content_length once we
have a proper BadRequest error variant at the service layer.
S3 and GCS reject CompleteMultipartUpload requests where parts are
not in ascending order. Add TODOs to LocalFs and InMemory backends
to implement this validation once we have a proper client error variant.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 78f0d7f. Configure here.

Comment thread objectstore-service/src/backend/local_fs.rs
@lcian lcian merged commit 24b35be into main May 12, 2026
24 checks passed
@lcian lcian deleted the lcian/feat/multipart-upload-other-backends branch May 12, 2026 11:22
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.

2 participants