fix: smuggle storage id to metadata insert queries

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2024-10-03 17:35:56 +02:00
parent 31f4f67c0c
commit 19ec79b313
No known key found for this signature in database
GPG key ID: 42B69D8A64526EFB
5 changed files with 41 additions and 1 deletions

View file

@ -8,6 +8,7 @@
namespace OCA\DAV\Connector\Sabre;
use OC\AppFramework\Http\Request;
use OC\FilesMetadata\Model\FilesMetadata;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCP\Constants;
use OCP\Files\ForbiddenException;
@ -575,7 +576,9 @@ class FilesPlugin extends ServerPlugin {
$propPatch->handle(
$mutation,
function (mixed $value) use ($accessRight, $knownMetadata, $node, $mutation, $filesMetadataManager): bool {
/** @var FilesMetadata $metadata */
$metadata = $filesMetadataManager->getMetadata((int)$node->getFileId(), true);
$metadata->setStorageId($node->getNode()->getStorage()->getCache()->getNumericStorageId());
$metadataKey = substr($mutation, strlen(self::FILE_METADATA_PREFIX));
// confirm metadata key is editable via PROPPATCH

View file

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace OCA\Files\Listener;
use OC\FilesMetadata\Model\FilesMetadata;
use OCA\Files\Service\LivePhotosService;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
@ -154,10 +155,14 @@ class SyncLivePhotosListener implements IEventListener {
* We have everything to update metadata and keep the link between the 2 copies.
*/
$newPeerFile = $peerFile->copy($targetParent->getPath() . '/' . $peerTargetName);
/** @var FilesMetadata $targetMetadata */
$targetMetadata = $this->filesMetadataManager->getMetadata($targetFile->getId(), true);
$targetMetadata->setStorageId($targetFile->getStorage()->getCache()->getNumericStorageId());
$targetMetadata->setString('files-live-photo', (string)$newPeerFile->getId());
$this->filesMetadataManager->saveMetadata($targetMetadata);
/** @var FilesMetadata $peerMetadata */
$peerMetadata = $this->filesMetadataManager->getMetadata($newPeerFile->getId(), true);
$peerMetadata->setStorageId($newPeerFile->getStorage()->getCache()->getNumericStorageId());
$peerMetadata->setString('files-live-photo', (string)$targetFile->getId());
$this->filesMetadataManager->saveMetadata($peerMetadata);
}

View file

@ -77,10 +77,13 @@ class FilesMetadataManager implements IFilesMetadataManager {
int $process = self::PROCESS_LIVE,
string $namedEvent = '',
): IFilesMetadata {
$storageId = $node->getStorage()->getCache()->getNumericStorageId();
try {
/** @var FilesMetadata $metadata */
$metadata = $this->metadataRequestService->getMetadataFromFileId($node->getId());
$metadata->setStorageId($storageId);
} catch (FilesMetadataNotFoundException) {
$metadata = new FilesMetadata($node->getId());
$metadata = new FilesMetadata($node->getId(), $storageId);
}
// if $process is LIVE, we enforce LIVE

View file

@ -30,6 +30,7 @@ class FilesMetadata implements IFilesMetadata {
public function __construct(
private int $fileId = 0,
private ?int $storageId = null,
) {
}
@ -42,6 +43,14 @@ class FilesMetadata implements IFilesMetadata {
return $this->fileId;
}
public function getStorageId(): ?int {
return $this->storageId;
}
public function setStorageId(int $storageId): void {
$this->storageId = $storageId;
}
/**
* @inheritDoc
* @return int timestamp

View file

@ -28,6 +28,24 @@ class MetadataRequestService {
) {
}
private function getStorageId(IFilesMetadata $filesMetadata): int {
if ($filesMetadata instanceof FilesMetadata && $filesMetadata->getStorageId()) {
return $filesMetadata->getStorageId();
}
// all code paths that lead to saving metadata *should* have the storage id set
// this fallback is there just in case
$query = $this->dbConnection->getQueryBuilder();
$query->select('storage')
->from('filecache')
->where($query->expr()->eq('fileid', $query->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT)));
$storageId = $query->executeQuery()->fetchColumn();
if ($filesMetadata instanceof FilesMetadata) {
$filesMetadata->setStorageId($storageId);
}
return $storageId;
}
/**
* store metadata into database
*
@ -38,6 +56,7 @@ class MetadataRequestService {
public function store(IFilesMetadata $filesMetadata): void {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert(self::TABLE_METADATA)
->hintShardKey('storage', $this->getStorageId($filesMetadata))
->setValue('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT))
->setValue('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize())))
->setValue('sync_token', $qb->createNamedParameter($this->generateSyncToken()))
@ -134,6 +153,7 @@ class MetadataRequestService {
$expr = $qb->expr();
$qb->update(self::TABLE_METADATA)
->hintShardKey('files_metadata', $this->getStorageId($filesMetadata))
->set('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize())))
->set('sync_token', $qb->createNamedParameter($this->generateSyncToken()))
->set('last_update', $qb->createFunction('NOW()'))