Skip to content

Conversation

@drallgood
Copy link

@drallgood drallgood commented Nov 19, 2025

This allows off-site media storage without local cache by making the local media directory behave like any other MediaStorageProvider. When no local directory is configured, media is stored directly to remote providers only, with temporary files used for thumbnail generation when needed.

fixes #16751

Pull Request Checklist

  • Pull request is based on the develop branch
  • Pull request includes a changelog file. The entry should:
    • Be a short description of your change which makes sense to users. "Fixed a bug that prevented receiving messages from other servers." instead of "Moved X method from EventStore to EventWorkerStore.".
    • Use markdown where necessary, mostly for code blocks.
    • End with either a period (.) or an exclamation mark (!).
    • Start with a capital letter.
    • Feel free to credit yourself, by adding a sentence "Contributed by @github_username." or "Contributed by [Your Name]." to the end of the entry.
  • Code style is correct (run the linters)

… as optional storage provider

This allows off-site media storage without local cache by making the local
media directory behave like any other MediaStorageProvider. When no local
directory is configured, media is stored directly to remote providers only,
with temporary files used for thumbnail generation when needed.
@CLAassistant
Copy link

CLAassistant commented Nov 19, 2025

CLA assistant check
All committers have signed the CLA.

… as optional storage provider

This allows off-site media storage without local cache by making the local
media directory behave like any other MediaStorageProvider. When no local
directory is configured, media is stored directly to remote providers only,
with temporary files used for thumbnail generation when needed.

Also fixes URL cache thumbnails to be served directly from local filesystem
instead of being incorrectly routed through storage providers.
These were auto-formatted changes that weren't intended to be committed.
@drallgood drallgood changed the title WIP: Implement synapse issue #16751: Treat local_media_directory as optional storage provider Implement synapse issue #16751: Treat local_media_directory as optional storage provider Nov 19, 2025
@drallgood drallgood marked this pull request as ready for review November 19, 2025 22:26
@drallgood drallgood requested a review from a team as a code owner November 19, 2025 22:26
Add type ignore comment for os.path.join call since local_provider check
guarantees local_media_directory is not None.
Copy link
Member

@anoadragon453 anoadragon453 left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution. Several questions below.

From the linked issues, I think broadly what we're aiming for is to satisfy the use-case where media isn't stored on disk at all, and is only stored on (typically) remote providers.

"nit" below means a non-blocking change. Typically related to code style or readability.

Address code review feedback:
- Add enable_local_media_storage config option to disable local media store
- Refactor MediaStorage.__init__ to accept local_provider as optional FileStorageProviderBackend argument
- Rename fname to media_filepath and eliminate dirname variable
- Deduplicate spam check code in store_into_file
- Delete temp files immediately after upload to storage providers
- Fix fetch_media to check local_provider first
- Remove unnecessary list() wrapper
- Revert storage_providers type to Sequence[StorageProvider]
- Update tests to use new MediaStorage constructor signature
When no local provider is configured, temp files are now automatically
cleaned up after use. This addresses the reviewer feedback about temp
files building up on disk over time.

The method now yields the file path within a context manager, and
callers must use `async with` to ensure proper cleanup.
@drallgood
Copy link
Author

@anoadragon453 thanks for the review. I reworked the suggested parts and found another area (the thumbnail generation) that needed fixing.

Hope this is better? 😄

@anoadragon453 anoadragon453 self-requested a review December 11, 2025 16:37
Copy link
Member

@anoadragon453 anoadragon453 left a comment

Choose a reason for hiding this comment

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

Looking mostly good now! Thanks for making those changes.

Couple more things, plus the following unit tests are currently failing:

  • tests.replication.test_multi_media_repo.AuthenticatedMediaRepoShardTestCase.test_download_simple_file_race
  • tests.replication.test_multi_media_repo.MediaRepoShardTestCase.test_download_simple_file_race

These tests assume that the files we fetch remain on disk, and this assumption should continue to hold as enable_local_media_storage is True in tests.


It'd also be good to see some tests with enable_local_media_storage set to False, so we can check the happy path works, and that files aren't pooling up on disk.

Note that you can use the @override_config decorator on tests to dynamically modify homeserver configuration for just that test case.

on disk.
Actually yields a 2-tuple (file, media_filepath,), where file is a file
like object that can be written to and media_filepath is the absolute path
of file on disk.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
of file on disk.
of the file on disk.

Comment on lines 636 to +642
# First let's check that we do actually have the original image
# still. This will throw a 404 if we don't.
# TODO: We should refetch the thumbnails for remote media.
await self.media_storage.ensure_media_is_in_local_cache(
async with self.media_storage.ensure_media_is_in_local_cache(
FileInfo(server_name, file_id, url_cache=url_cache)
)
):
pass
Copy link
Member

Choose a reason for hiding this comment

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

Looks like this can be removed. Both generate_remote_exact_thumbnail and generate_local_exact_thumbnail start with a call to ensure_media_is_in_local_cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transform MediaStorage.local_media_directory into an optional storage provider

4 participants