Skip to content

Commit 0ebb20b

Browse files
committed
fixup! feat(database): introduce Snowflake IDs generator
Signed-off-by: Benjamin Gaussorgues <[email protected]>
1 parent c8c92ef commit 0ebb20b

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

core/Command/SnowflakeDecodeId.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99
namespace OC\Core\Command;
1010

11-
use OC\SnowflakeId;
11+
use OC\Snowflake\Decoder;
1212
use Symfony\Component\Console\Helper\Table;
1313
use Symfony\Component\Console\Input\InputArgument;
1414
use Symfony\Component\Console\Input\InputInterface;
@@ -26,17 +26,17 @@ protected function configure(): void {
2626

2727
protected function execute(InputInterface $input, OutputInterface $output): int {
2828
$snowflakeId = $input->getArgument('snowflake-id');
29-
$snowflakeId = new SnowflakeId($snowflakeId);
29+
$data = (new Decoder)->decode($snowflakeId);
3030

3131
$rows = [
32-
['Snowflake ID', $snowflakeId->numeric()],
33-
['Seconds', $snowflakeId->seconds()],
34-
['Milliseconds', $snowflakeId->milliseconds()],
35-
['Created from CLI', $snowflakeId->isCli() ? 'yes' : 'no'],
36-
['Server ID', $snowflakeId->serverId()],
37-
['Sequence ID', $snowflakeId->sequenceId()],
38-
['Creation timestamp', $snowflakeId->createdAt()],
39-
['Creation date', date('Y-m-d H:i:s', (int)$snowflakeId->createdAt()) . '.' . $snowflakeId->milliseconds()],
32+
['Snowflake ID', $snowflakeId],
33+
['Seconds', $data['seconds']],
34+
['Milliseconds', $data['milliseconds']],
35+
['Created from CLI', $data['isCli'] ? 'yes' : 'no'],
36+
['Server ID', $data['serverId']],
37+
['Sequence ID', $data['sequenceId']],
38+
['Creation timestamp', $data['createdAt']->format('U.v')],
39+
['Creation date', $data['createdAt']->format('Y-m-d H:i:s.v')],
4040
];
4141

4242
$table = new Table($output);

lib/private/Snowflake/Generator.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
final class Generator implements IGenerator {
2424
public function __construct(
2525
private readonly ITimeFactory $timeFactory,
26+
private readonly APCuSequence $sequenceGenerator,
2627
) {
2728
}
2829

@@ -108,18 +109,23 @@ private function isCli(): bool {
108109
return PHP_SAPI === 'cli';
109110
}
110111

111-
private function getSequenceId(int $seconds, int $milliseconds, int $serverId): int {
112+
private function getSequenceId(int $seconds, int $milliseconds, int $serverId): int|false {
112113
$key = 'seq:' . $seconds . ':' . $milliseconds;
113114

114115
// Use APCu as fastest local cache, but not shared between processes in CLI
115-
if (!$this->isCli() && function_exists('apcu_inc')) {
116-
// TODO Try to detect reseted APCu cache
117-
$sequenceId = apcu_inc($key, ttl: 1);
118-
if ($sequenceId === false) {
119-
throw new \Exception('Failed to generate SnowflakeId with APCu');
116+
if (!$this->isCli() && function_exists('apcu_enabled') && apcu_enabled()) {
117+
if ((int)apcu_cache_info(true)['creation_time'] === $seconds) {
118+
// APCu cache was just started
119+
// It means a sequence was maybe deleted
120+
return false;
120121
}
121122

122-
return $sequenceId;
123+
$sequenceId = apcu_inc($key, success: $success, ttl: 1);
124+
if ($success === true) {
125+
return $sequenceId;
126+
}
127+
128+
throw new \Exception('Failed to generate SnowflakeId with APCu');
123129
}
124130

125131
// Otherwise, just return a random number

tests/lib/Snowflake/GeneratorTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/**
46
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
57
* SPDX-License-Identifier: AGPL-3.0-or-later

0 commit comments

Comments
 (0)