mirror of
https://github.com/nextcloud/documentation.git
synced 2025-12-12 07:29:47 +07:00
97 lines
3.5 KiB
ReStructuredText
97 lines
3.5 KiB
ReStructuredText
.. _collection_preload:
|
|
|
|
=================================
|
|
WebDAV collection preload events
|
|
=================================
|
|
|
|
Overview
|
|
--------
|
|
|
|
During a WebDAV PROPFIND on a SabreDAV collection with ``Depth > 0``,
|
|
Nextcloud emits a preload event so DAV plugins can fetch data for the
|
|
collection's children in one go. The goal is to avoid N+1 database queries by
|
|
preloading what your property handlers need before per-node property handling
|
|
starts. In practice, this means your plugin can fill a cache up front, then
|
|
read from it in the usual ``propFind`` handlers for a faster and more
|
|
efficient response.
|
|
|
|
When the event is emitted
|
|
-------------------------
|
|
|
|
The event is emitted during PROPFIND requests, before the ``propFind`` event,
|
|
for nodes implementing ``Sabre\DAV\ICollection`` with ``Depth > 0``.
|
|
|
|
The event may be emitted multiple times for a given request path; plugins should
|
|
check their caches to avoid duplicate work.
|
|
|
|
Subscribing to the event in a plugin
|
|
------------------------------------
|
|
|
|
Register a listener in your implementation of Sabre's ``ServerPlugin::initialize()`` method:
|
|
|
|
.. code-block:: php
|
|
|
|
use Sabre\DAV\ICollection;
|
|
use Sabre\DAV\PropFind;
|
|
use Sabre\DAV\ServerPlugin;
|
|
|
|
class MyDavPlugin extends ServerPlugin {
|
|
|
|
public function initialize(\Sabre\DAV\Server $server): void {
|
|
// Called before per-node property handlers
|
|
$server->on('preloadCollection', $this->preloadCollection(...));
|
|
|
|
// Your usual property handlers
|
|
$server->on('propFind', $this->handleGetProperties(...));
|
|
}
|
|
|
|
private function preloadCollection(PropFind $propFind, ICollection $collection): void {
|
|
// Only preload when your properties were actually requested
|
|
$requested = [
|
|
'{http://appdomain.example/ns}your-prop',
|
|
'{http://appdomain.example/ns}another-prop',
|
|
];
|
|
$anyRequested = array_reduce(
|
|
$requested,
|
|
fn($result, $property) => $result || $propFind->getStatus($property) !== null,
|
|
false
|
|
);
|
|
if (!$anyRequested) {
|
|
return;
|
|
}
|
|
|
|
// Fetch data for the collection and its children in bulk
|
|
// and cache results for use in your propFind handler
|
|
$this->cache = $this->bulkLoadDataForCollection($collection); // implement your own caching
|
|
}
|
|
|
|
private function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node): void {
|
|
// Read and return values from $this->cache to avoid per-node queries
|
|
|
|
// Handle per-node property loading here to support Depth = 0
|
|
// and cases where the 'preloadCollection' event is not emitted.
|
|
}
|
|
|
|
}
|
|
|
|
|
|
Built-in examples
|
|
-----------------
|
|
|
|
- Tags: ``OCA\DAV\Connector\Sabre\TagsPlugin`` preloads tags and favorite
|
|
info for a folder and its children.
|
|
- Shares: ``OCA\DAV\Connector\Sabre\SharesPlugin`` preloads share types and
|
|
sharees for items within a folder.
|
|
- Comments: ``OCA\DAV\Connector\Sabre\CommentPropertiesPlugin`` preloads unread
|
|
comment counts for items within a folder.
|
|
|
|
Best practices
|
|
--------------
|
|
|
|
- Check requested properties: Use ``$propFind->getStatus('{ns}property')`` to
|
|
confirm that your properties were actually requested before querying.
|
|
- Cache results: The event can fire multiple times; cache by file ID or path
|
|
to avoid redundant work during the same request.
|
|
- Scope your preload: Only fetch data for the current collection and (at most)
|
|
its direct children; avoid fetching across the whole tree.
|