Skip to content

Set immutable cache-control on R2 media uploads - #54

Open
G3root wants to merge 1 commit into
mainfrom
r2-immutable-cache-control
Open

Set immutable cache-control on R2 media uploads#54
G3root wants to merge 1 commit into
mainfrom
r2-immutable-cache-control

Conversation

@G3root

@G3root G3root commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Summary

Avatar/logo/editor-media uploads currently go through S3FileSystem.writeFile, which cannot set object metadata — so nothing carries a Cache-Control header and browsers/CDN only get weak heuristic caching.

Switch to direct S3.putObject so every uploaded object carries:

  • Cache-Control: public, max-age=31536000, immutable
  • an explicit Content-Type derived from the file extension

Object keys already embed a timestamp + UUID, so content at any given URL never changes. Caching forever is therefore safe: a new avatar just writes a new URL to the database and abandons the old one — no SWR tags, no cache purging, and revalidations stop hitting the bucket after the first fetch per URL.

Changes

  • packages/domain/src/services/s3.ts
    • Replace the three fileSystem.writeFile calls with s3.putObject + CacheControl/ContentType metadata
    • Drop the S3FileSystem layer (existed only for bucket writes); S3UploadServiceLive now provides S3Layer directly
    • Add extension → content-type map (gif/jpg/png/webp)

Notes

  • Promoted editor media inherits metadata via copyObject's default COPY directive, so permanent assets are cached consistently.
  • Applies to new uploads only; old objects are versioned URLs that get abandoned/deleted anyway.
  • Local dev (MinIO) supports putObject with metadata, unchanged behavior.

Verification

  • packages/domain check-types ✅
  • packages/domain tests: 524 passed ✅
  • apps/server check-types ✅
  • apps/web astro check: 0 errors ✅

Summary by CodeRabbit

  • Improvements
    • File uploads now include the appropriate content type based on the file extension.
    • Uploaded files use one-year immutable caching for improved delivery performance.

Replace S3FileSystem.writeFile with direct S3.putObject so uploaded
objects carry immutable caching metadata. Object keys embed a timestamp
and UUID, so content at any URL never changes; caching forever means
browsers and the CDN never revalidate avatar/logo/media URLs, and no
SWR tags or cache purging are needed.

Also sets an explicit Content-Type from the file extension, which
writeFile could not express. Drops the S3FileSystem dependency from the
upload service since it existed only for bucket writes.
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fd2327ed-0f6a-464d-94b0-76dc01ee16c5

📥 Commits

Reviewing files that changed from the base of the PR and between d83654e and 2f6dce9.

📒 Files selected for processing (1)
  • packages/domain/src/services/s3.ts

📝 Walkthrough

Walkthrough

S3 uploads now use the direct AWS S3 client. The service derives content types from file extensions, applies immutable one-year caching, and removes the S3 filesystem dependency and runtime wiring.

Changes

Direct S3 Uploads

Layer / File(s) Summary
S3 upload metadata
packages/domain/src/services/s3.ts
The upload service uses the direct S3 client. It derives content types and applies immutable one-year caching.
Upload paths and runtime wiring
packages/domain/src/services/s3.ts
Profile images, organization logos, and editor media use s3.putObject. The live layer provides S3Layer directly.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 2f6dc

The change adds long-lived caching and explicit content types to newly uploaded media while preserving the existing versioned-URL behavior. No actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main user-facing change: immutable cache control for R2 media uploads.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch r2-immutable-cache-control

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@G3root

G3root commented Aug 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@G3root

G3root commented Aug 20, 2026

Copy link
Copy Markdown
Owner Author

@greptileai review

@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown

Greptile Summary

The PR replaces filesystem-backed R2 writes with direct S3 uploads so new profile images, organization logos, and editor media receive explicit content types and one-year immutable cache metadata.

  • Maps the supported image extensions to MIME types.
  • Adds CacheControl and ContentType to each upload request.
  • Simplifies the live service layer by removing the unused S3 filesystem adapter.

Confidence Score: 5/5

The PR appears safe to merge with no concrete blocking or independently actionable issue identified.

Current upload callers normalize validated image MIME types to the new mapping’s canonical extensions, direct S3 layer composition remains complete, and timestamp-plus-UUID keys prevent immutable caching from serving overwritten content.

Important Files Changed

Filename Overview
packages/domain/src/services/s3.ts Direct S3 uploads consistently provide bucket, body, content type, and immutable cache metadata; existing callers produce supported canonical extensions and generated keys remain unique.

Reviews (1): Last reviewed commit: "Set immutable cache-control on R2 media ..." | Re-trigger Greptile

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