Merge pull request #60317 from nextcloud/fix/snowflake_server_id_doc
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, main, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, guests_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / changes (push) Waiting to run
Psalm static code analysis / static-code-analysis (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-security (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-ocp (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-ncu (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-strict (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-summary (push) Blocked by required conditions

fix(snowflake): fix wrong documentation about serverId
This commit is contained in:
Benjamin Gaussorgues 2026-05-12 14:16:31 +02:00 committed by GitHub
commit b438b345b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 18 additions and 20 deletions

View file

@ -40,14 +40,16 @@ final class ServerIdConfig implements ISetupCheck {
if ($serverid === PHP_INT_MIN) {
return SetupResult::info(
$this->l10n->t('Server identifier isnt configured. It is recommended if your Nextcloud instance is running on several PHP servers. Add a server ID in your configuration.'),
$this->l10n->t(
'Server identifier isnt configured. It is recommended if your Nextcloud instance is running on several PHP servers. Add a server ID in your configuration.',
),
$linkToDoc,
);
}
if ($serverid < 0 || $serverid > 1023) {
if ($serverid < 0 || $serverid > 511) {
return SetupResult::error(
$this->l10n->t('"%d" is not a valid server identifier. It must be between 0 and 1023.', [$serverid]),
$this->l10n->t('"%d" is not a valid server identifier. It must be between 0 and 511.', [$serverid]),
$linkToDoc,
);
}

View file

@ -50,7 +50,7 @@ $CONFIG = [
* It is useful when your Nextcloud instance is using different PHP servers.
* Once it's set it shouldn't be changed.
*
* Value must be an integer, comprised between 0 and 1023.
* Value must be an integer, comprised between 0 and 511.
*
* When config.php is shared between different servers, this value should be overriden with "NC_serverid=<int>" on each server.
* Note that it must be overriden for CLI and for your webserver.

View file

@ -28,7 +28,7 @@ final class SnowflakeDecoder implements ISnowflakeDecoder {
throw new \Exception('Invalid Snowflake ID: ' . $snowflakeId);
}
/** @var array{seconds: positive-int, milliseconds: int<0,999>, serverId: int<0, 1023>, sequenceId: int<0,4095>, isCli: bool} $data */
/** @var array{seconds: positive-int, milliseconds: int<0,999>, serverId: int<0, 511>, sequenceId: int<0,4095>, isCli: bool} $data */
$data = PHP_INT_SIZE === 8
? $this->decode64bits((int)$snowflakeId)
: $this->decode32bits($snowflakeId);

View file

@ -16,17 +16,16 @@ use OCP\AppFramework\Attribute\Consumable;
*
* Customized version of Snowflake IDs for Nextcloud:
* 1 bit : Unused, always 0, avoid issue with PHP signed integers.
* 31 bits: Timestamp from 2025-10-01. Allows to store a bit more than 68 years. Allows to find creation time.
* 10 bits: Milliseconds (between 0 and 999)
* 9 bits: Server ID, identify server which generated the ID (between 0 and 1023)
* 1 bit : CLI or Web (0 or 1)
* 12 bits: Sequence ID, usually a serial number of objects created in the same number on same server (between 0 and 4095)
* 31 bits: Timestamp from 2025-10-01. Allows to store a bit more than 68 years. Allows to find creation time.
* 10 bits: Milliseconds (between 0 and 999)
* 9 bits: Server ID, identify server which generated the ID (between 0 and 511)
* 1 bit : CLI or Web (0 or 1)
* 12 bits: Sequence ID, usually a serial number of objects created in the same number on same server (between 0 and 4095)
*
* @since 33.0.0
*/
#[Consumable(since: '33.0.0')]
interface ISnowflakeGenerator {
/**
* Offset applied on timestamps to keep it short
* Start from 2025-10-01 at 00:00:00

View file

@ -19,7 +19,7 @@ use OCP\AppFramework\Attribute\Consumable;
#[Consumable(since: '33.0.0')]
final readonly class Snowflake {
/**
* @psalm-param int<0,1023> $serverId
* @psalm-param int<0,511> $serverId
* @psalm-param int<0,4095> $sequenceId
* @psalm-param non-negative-int $seconds
* @psalm-param int<0,999> $milliseconds
@ -36,7 +36,7 @@ final readonly class Snowflake {
}
/**
* @psalm-return int<0,1023>
* @psalm-return int<0,511>
* @since 33.0.0
*/
public function getServerId(): int {

View file

@ -29,18 +29,15 @@ class GeneratorTest extends TestCase {
private ISequence&MockObject $sequence;
#[\Override]
public function setUp():void {
public function setUp(): void {
$this->decoder = new SnowflakeDecoder();
$this->config = $this->createMock(IConfig::class);
$this->config->method('getSystemValueInt')
->with('serverid')
->willReturn(42);
$this->config->method('getSystemValueInt')->with('serverid')->willReturn(42);
$this->sequence = $this->createMock(ISequence::class);
$this->sequence->method('isAvailable')->willReturn(true);
$this->sequence->method('nextId')->willReturn(421);
}
public function testGenerator(): void {
@ -54,7 +51,7 @@ class GeneratorTest extends TestCase {
// Check serverId
$this->assertGreaterThanOrEqual(0, $data->getServerId());
$this->assertLessThanOrEqual(1023, $data->getServerId());
$this->assertLessThanOrEqual(511, $data->getServerId());
// Check sequenceId
$this->assertGreaterThanOrEqual(0, $data->getSequenceId());
@ -76,7 +73,7 @@ class GeneratorTest extends TestCase {
$generator = new SnowflakeGenerator($timeFactory, $this->config, $this->sequence);
$data = $this->decoder->decode($generator->nextId());
$this->assertEquals($expectedSeconds, ($data->getCreatedAt()->format('U') - ISnowflakeGenerator::TS_OFFSET));
$this->assertEquals($expectedSeconds, $data->getCreatedAt()->format('U') - ISnowflakeGenerator::TS_OFFSET);
$this->assertEquals($expectedMilliseconds, (int)$data->getCreatedAt()->format('v'));
$this->assertEquals(42, $data->getServerId());
}