Skip to content

Conversation

@CarlSchwan
Copy link
Member

@CarlSchwan CarlSchwan commented Aug 20, 2025

Summary

The new oc_previews table is optimized for storing previews and should decrease significantly the space taken by previews in the filecache table.

This attend to reuse the IObjectStore abstraction over S3/Swift/Azure but currently only support one single bucket configuration.

TODO

  • Implement multibucket configuration
  • Implement multibucket configuration where previews are stored in different bucket than the original files
  • Add migration for local storage
  • Add migration for object store storage
  • Add migration for multibucket object store storage
  • Make migration efficient
  • Adapt/Add unit tests
  • Re-thing BackgroundCleanupJob and other jobs and commands

TODO moved to seperate MR

  • Sharding: we want to do the sharding on the file_id table. Likely could be done with a tool like citus or vitess. Need some research
  • Server side encryption: currently we don't use SSE on the previews. If we end up implementing SSE for previews, we should use the same key file as the original files and add a seperate IPreviewStorage implementation using the IEncryptionModule. I already added an encrypted bool to the oc_previews table in preparation as it would be needed anyway for the migration

Checklist

@CarlSchwan CarlSchwan added this to the Nextcloud 33 milestone Aug 20, 2025
@CarlSchwan CarlSchwan self-assigned this Aug 20, 2025
@CarlSchwan CarlSchwan added the 2. developing Work in progress label Aug 20, 2025
Copy link
Collaborator

@Altahrim Altahrim left a comment

Choose a reason for hiding this comment

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

Quick thoughts on the new table

@CarlSchwan CarlSchwan force-pushed the preview-db-rework branch 3 times, most recently from 43b105b to 0447f56 Compare August 27, 2025 15:14
@CarlSchwan CarlSchwan force-pushed the preview-db-rework branch 2 times, most recently from 663dfd5 to e55c56d Compare August 28, 2025 17:42
@CarlSchwan
Copy link
Member Author

@icewind1991 some questions for you :)

  • With allow configuring multiple object store backends #52786 there is now the possibility of using multiple backends per user. The current mapping is done using user configs (oc_preferences) and previews are still stored in the 'root' object store. Should we add a column to the preview table for the backend used (e.g. 'default', 'new', 'old', 'root', ...) to allow an easier migration of the previews in the future? Or do we keeping using only the 'root' backend for previews?

  • Multi bucket support. Currently either all the previews are stored on the root bucket or with an opt-in flag can be spread out in 256. I keep the exact same mapping in the new system, does it make sense? Or do we want to use the opportunity of having a breaking change to change that?

  • Sharding: I added a storage_id field to the column with sharding in mind. I didn't configure yet anything else or test it. Should I had it to SHARD_PRESETS in Connection.php?

  • Generally how do you feel about the direction this is going?

@github-actions
Copy link
Contributor

Possible performance regression detected

Show Output
An unhandled exception has been thrown:
TypeError: array_map(): Argument #2 ($array) must be of type array, null given in /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php:35
Stack trace:
#0 /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php(35): array_map()
#1 /home/runner/work/server/server/3rdparty/symfony/console/Command/Command.php(326): OCAProfilerCommandCompare->execute()
#2 /home/runner/work/server/server/core/Command/Base.php(218): SymfonyComponentConsoleCommandCommand->run()
#3 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(1078): OCCoreCommandBase->run()
#4 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(324): SymfonyComponentConsoleApplication->doRunCommand()
#5 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(175): SymfonyComponentConsoleApplication->doRun()
#6 /home/runner/work/server/server/lib/private/Console/Application.php(187): SymfonyComponentConsoleApplication->run()
#7 /home/runner/work/server/server/console.php(91): OCConsoleApplication->run()
#8 /home/runner/work/server/server/occ(33): require_once('...')
#9 {main}

1 similar comment
@github-actions
Copy link
Contributor

Possible performance regression detected

Show Output
An unhandled exception has been thrown:
TypeError: array_map(): Argument #2 ($array) must be of type array, null given in /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php:35
Stack trace:
#0 /home/runner/work/server/server/apps/profiler/lib/Command/Compare.php(35): array_map()
#1 /home/runner/work/server/server/3rdparty/symfony/console/Command/Command.php(326): OCAProfilerCommandCompare->execute()
#2 /home/runner/work/server/server/core/Command/Base.php(218): SymfonyComponentConsoleCommandCommand->run()
#3 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(1078): OCCoreCommandBase->run()
#4 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(324): SymfonyComponentConsoleApplication->doRunCommand()
#5 /home/runner/work/server/server/3rdparty/symfony/console/Application.php(175): SymfonyComponentConsoleApplication->doRun()
#6 /home/runner/work/server/server/lib/private/Console/Application.php(187): SymfonyComponentConsoleApplication->run()
#7 /home/runner/work/server/server/console.php(91): OCConsoleApplication->run()
#8 /home/runner/work/server/server/occ(33): require_once('...')
#9 {main}

@CarlSchwan CarlSchwan force-pushed the preview-db-rework branch 5 times, most recently from 9b52d71 to 7d3c7e8 Compare September 17, 2025 09:06
@CarlSchwan CarlSchwan added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Sep 17, 2025
@CarlSchwan CarlSchwan marked this pull request as ready for review September 17, 2025 09:14
@CarlSchwan CarlSchwan requested a review from a team as a code owner September 17, 2025 09:14
@CarlSchwan CarlSchwan requested review from icewind1991, provokateurin and yemkareems and removed request for a team September 17, 2025 09:14
Copy link
Contributor

@artonge artonge left a comment

Choose a reason for hiding this comment

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

- Do we have a way to garbage collect orphan previews? Was answered during our call.

Carl Schwan and others added 12 commits October 6, 2025 13:37
The new oc_previews table is optimized for storing previews and should
decrease significantly the space taken by previews in the filecache
table.

This attend to reuse the IObjectStore abstraction over S3/Swift/Azure
but currently only support one single bucket configuration.

Signed-off-by: Carl Schwan <[email protected]>
* Simplify migration by not moving the actual files and just updating
  the DB
* Don't store the storageid in the preview table as it is not needed
* Start adding tests

Signed-off-by: Carl Schwan <[email protected]>
Signed-off-by: Carl Schwan <[email protected]>
This work similarly to the move preview job to migrate the previews to
the new DB table and also reuse some code.

So when we are finding files in appdata/preview, try adding them to the
oc_previews table and delete them from the oc_filecache table.

Signed-off-by: Carl Schwan <[email protected]>
Allow to quickly query all the files from a specific mimetype like in
the ResetRenderedTexts command.

Signed-off-by: Carl Schwan <[email protected]>
@CarlSchwan CarlSchwan force-pushed the preview-db-rework branch 4 times, most recently from b1c9a14 to 9b63d58 Compare October 8, 2025 08:52
And move it to a different table so that we don't have to pay the
storage cost when not using it (most of the times).

Signed-off-by: Carl Schwan <[email protected]>
@Altahrim Altahrim merged commit 3aa0c23 into master Oct 8, 2025
213 of 221 checks passed
@Altahrim Altahrim deleted the preview-db-rework branch October 8, 2025 14:39
@szaimen
Copy link
Contributor

szaimen commented Oct 8, 2025

🎉🎉🎉🎉🎉

if (!$schema->hasTable('preview_versions')) {
$table = $schema->createTable('preview_versions');
$table->addColumn('id', Types::BIGINT, ['autoincrement' => true, 'notnull' => true, 'length' => 20, 'unsigned' => true]);
$table->addColumn('file_id', Types::BIGINT, ['notnull' => true, 'length' => 20, 'unsigned' => true]);
Copy link
Member

Choose a reason for hiding this comment

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

Uneducated guess, but an this smells like it will be the primary column to look up rows. Add an index?

Copy link
Member

Choose a reason for hiding this comment

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

The mapper confirms that an index on file_id+version would be beneficial :)

Copy link
Member

Choose a reason for hiding this comment

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

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split previews out of the filecache table

10 participants