Skip to content

Commit 15cdbe8

Browse files
committed
sync token
Signed-off-by: Maxence Lange <[email protected]>
1 parent 184157a commit 15cdbe8

4 files changed

Lines changed: 45 additions & 35 deletions

File tree

lib/private/FilesMetadata/FilesMetadataManager.php

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OC\FilesMetadata\Service\MetadataRequestService;
1414
use OCP\BackgroundJob\IJobList;
1515
use OCP\DB\Exception;
16+
use OCP\DB\Exception as DBException;
1617
use OCP\DB\QueryBuilder\IQueryBuilder;
1718
use OCP\EventDispatcher\IEventDispatcher;
1819
use OCP\Files\Events\Node\NodeCreatedEvent;
@@ -107,23 +108,19 @@ public function saveMetadata(IFilesMetadata $filesMetadata): void {
107108
}
108109

109110
try {
110-
// if update request changed no rows, means that new entry is needed, or sync_token not valid anymore
111-
$updated = $this->metadataRequestService->updateMetadata($filesMetadata);
112-
if ($updated === 0) {
111+
if ($filesMetadata->getSyncToken() === '') {
113112
$this->metadataRequestService->store($filesMetadata);
113+
} else {
114+
$this->metadataRequestService->updateMetadata($filesMetadata);
114115
}
115-
} catch (\OCP\DB\Exception $e) {
116-
// if duplicate, only means a desync during update. cancel update process.
117-
if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
118-
$this->logger->warning(
119-
'issue while saveMetadata', ['exception' => $e, 'metadata' => $filesMetadata]
120-
);
121-
}
116+
} catch (DBException $e) {
117+
// most of the logged exception are the result of race condition
118+
// between 2 simultaneous process trying to create/update metadata
119+
$this->logger->warning('issue while saveMetadata', ['exception' => $e, 'metadata' => $filesMetadata]);
122120

123121
return;
124122
}
125123

126-
// $this->removeDeprecatedMetadata($filesMetadata);
127124
foreach ($filesMetadata->getIndexes() as $index) {
128125
try {
129126
$this->indexRequestService->updateIndex($filesMetadata, $index);

lib/private/FilesMetadata/Model/FilesMetadata.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public function import(array $data): IFilesMetadata {
5959
*/
6060
public function importFromDatabase(array $data, string $prefix = ''): IFilesMetadata {
6161
try {
62+
$this->syncToken = $data[$prefix . 'sync_token'];
6263
return $this->import(
6364
json_decode($data[$prefix . 'json'] ?? '[]',
6465
true,
@@ -346,7 +347,6 @@ public function getValueWrapper(string $key): MetadataValueWrapper {
346347
return $this->metadata[$key];
347348
}
348349

349-
350350
public function jsonSerialize(): array {
351351
$data = [];
352352
foreach ($this->metadata as $metaKey => $metaValueWrapper) {

lib/private/FilesMetadata/Service/MetadataRequestService.php

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace OC\FilesMetadata\Service;
66

7-
use JsonException;
87
use OC\FilesMetadata\Model\FilesMetadata;
98
use OCP\DB\Exception;
109
use OCP\DB\QueryBuilder\IQueryBuilder;
@@ -34,7 +33,7 @@ public function store(IFilesMetadata $filesMetadata): void {
3433
$qb->insert(self::TABLE_METADATA)
3534
->setValue('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT))
3635
->setValue('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize())))
37-
->setValue('sync_token', $qb->createNamedParameter($filesMetadata->getSyncToken()))
36+
->setValue('sync_token', $qb->createNamedParameter($this->generateSyncToken()))
3837
->setValue('last_update', $qb->createFunction('NOW()'));
3938
$qb->executeStatement();
4039
}
@@ -48,13 +47,17 @@ public function store(IFilesMetadata $filesMetadata): void {
4847
public function getMetadataFromFileId(int $fileId): IFilesMetadata {
4948
try {
5049
$qb = $this->dbConnection->getQueryBuilder();
51-
$qb->select('json')->from(self::TABLE_METADATA);
52-
$qb->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
50+
$qb->select('json', 'sync_token')->from(self::TABLE_METADATA);
51+
$qb->where(
52+
$qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))
53+
);
5354
$result = $qb->executeQuery();
5455
$data = $result->fetch();
5556
$result->closeCursor();
5657
} catch (Exception $e) {
57-
$this->logger->warning('exception while getMetadataFromDatabase()', ['exception' => $e, 'fileId' => $fileId]);
58+
$this->logger->warning(
59+
'exception while getMetadataFromDatabase()', ['exception' => $e, 'fileId' => $fileId]
60+
);
5861
throw new FilesMetadataNotFoundException();
5962
}
6063

@@ -68,7 +71,6 @@ public function getMetadataFromFileId(int $fileId): IFilesMetadata {
6871
return $metadata;
6972
}
7073

71-
7274
/**
7375
* @param int $fileId
7476
*
@@ -82,32 +84,43 @@ public function dropMetadata(int $fileId): void {
8284
$qb->executeStatement();
8385
}
8486

85-
private function removeDeprecatedMetadata(IFilesMetadata $filesMetadata): void {
86-
// TODO delete aussi les index generate a partir d'une string[]
87-
88-
$qb = $this->dbConnection->getQueryBuilder();
89-
$qb->delete(self::TABLE_METADATA_INDEX)
90-
->where($qb->expr()->eq('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT)))
91-
->andWhere($qb->expr()->notIn('file_id', $filesMetadata->getIndexes(), IQueryBuilder::PARAM_STR_ARRAY));
92-
$qb->executeStatement();
93-
}
94-
95-
9687
/**
9788
* @param IFilesMetadata $filesMetadata
9889
*
9990
* @return bool
10091
* @throws Exception
10192
*/
10293
public function updateMetadata(IFilesMetadata $filesMetadata): int {
103-
// TODO check sync_token on update
10494
$qb = $this->dbConnection->getQueryBuilder();
95+
$expr = $qb->expr();
96+
10597
$qb->update(self::TABLE_METADATA)
10698
->set('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize())))
107-
->set('sync_token', $qb->createNamedParameter('abc'))
99+
->set('sync_token', $qb->createNamedParameter($this->generateSyncToken()))
108100
->set('last_update', $qb->createFunction('NOW()'))
109-
->where($qb->expr()->eq('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT)));
101+
->where(
102+
$expr->andX(
103+
$expr->eq('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT)),
104+
$expr->eq('sync_token', $qb->createNamedParameter($filesMetadata->getSyncToken()))
105+
)
106+
);
110107

111108
return $qb->executeStatement();
112109
}
110+
111+
112+
private function generateSyncToken(): string {
113+
$chars = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
114+
115+
$str = '';
116+
$max = strlen($chars);
117+
for ($i = 0; $i < 7; $i++) {
118+
try {
119+
$str .= $chars[random_int(0, $max - 2)];
120+
} catch (Exception $e) {
121+
}
122+
}
123+
124+
return $str;
125+
}
113126
}

lib/public/FilesMetadata/Model/IFilesMetadata.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ public function getArray(string $key): array;
6969
public function getStringList(string $key): array;
7070
public function getIntList(string $key): array;
7171
public function getType(string $key): string;
72-
public function set(string $key, string $value): self;
73-
public function setInt(string $key, int $value): self;
74-
public function setFloat(string $key, float $value): self;
72+
public function set(string $key, string $value, bool $index = false): self;
73+
public function setInt(string $key, int $value, bool $index = false): self;
74+
public function setFloat(string $key, float $value, bool $index = false): self;
7575
public function setBool(string $key, bool $value): self;
7676
public function setArray(string $key, array $value): self;
7777
public function setStringList(string $key, array $value): self;

0 commit comments

Comments
 (0)