Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions apps/settings/lib/SetupChecks/ServerIdConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ public function run(): SetupResult {

if ($serverid === PHP_INT_MIN) {
return SetupResult::info(
$this->l10n->t('Server identifier isn’t 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 isn’t 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,
);
}
Expand Down
2 changes: 1 addition & 1 deletion config/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
* 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.
Expand Down
2 changes: 1 addition & 1 deletion lib/private/Snowflake/SnowflakeDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function decode(string $snowflakeId): Snowflake {
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);
Expand Down
11 changes: 5 additions & 6 deletions lib/public/Snowflake/ISnowflakeGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@
*
* 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
Expand Down
4 changes: 2 additions & 2 deletions lib/public/Snowflake/Snowflake.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#[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
Expand All @@ -36,7 +36,7 @@ public function __construct(
}

/**
* @psalm-return int<0,1023>
* @psalm-return int<0,511>
* @since 33.0.0
*/
public function getServerId(): int {
Expand Down
11 changes: 4 additions & 7 deletions tests/lib/Snowflake/GeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -54,7 +51,7 @@ public function testGenerator(): void {

// Check serverId
$this->assertGreaterThanOrEqual(0, $data->getServerId());
$this->assertLessThanOrEqual(1023, $data->getServerId());
$this->assertLessThanOrEqual(511, $data->getServerId());

// Check sequenceId
$this->assertGreaterThanOrEqual(0, $data->getSequenceId());
Expand All @@ -76,7 +73,7 @@ public function testGeneratorWithFixedTime(string $date, int $expectedSeconds, i
$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());
}
Expand Down
Loading