Skip to content

Commit

Permalink
Add way to create IDs that are meant for querying a specific timestamp (
Browse files Browse the repository at this point in the history
#9)

* Add way to create IDs that are meant for querying a specific timestamp

* Code style

* Update to match new signature
  • Loading branch information
inxilpro authored Jul 10, 2024
1 parent ba83eec commit dbe3b4a
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/Contracts/MakesBits.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public function make(): Bits;

public function makeFromTimestamp(CarbonInterface $timestamp): Bits;

public function firstForTimestamp(CarbonInterface $timestamp): Bits;

public function fromId(int|string $id): Bits;

public function coerce(int|string|Bits $value): Bits;
Expand Down
13 changes: 13 additions & 0 deletions src/Factories/GenericFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ public function makeFromTimestamp(CarbonInterface $timestamp): Bits
return new Bits($values, $this->config, $this->epoch);
}

public function firstForTimestamp(CarbonInterface $timestamp): Bits
{
$timestamp = $this->diffFromEpoch($timestamp);

$values = $this->config->organize(
ids: new WorkerIds(...array_map(fn() => 0, $this->ids->ids)),
timestamp: $timestamp,
sequence: 0
);

return new Bits($values, $this->config, $this->epoch);
}

public function fromId(int|string $id): Bits
{
$values = $this->config->parse((int) $id);
Expand Down
7 changes: 7 additions & 0 deletions src/Factories/SnowflakeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ public function makeFromTimestamp(CarbonInterface $timestamp): Snowflake
return new Snowflake($timestamp, $this->datacenter_id, $this->worker_id, $sequence, $this->epoch, $this->config);
}

public function firstForTimestamp(CarbonInterface $timestamp): Snowflake
{
$timestamp = $this->diffFromEpoch($timestamp);

return new Snowflake($timestamp, 0, 0, 0, $this->epoch, $this->config);
}

public function fromId(int|string $id): Snowflake
{
[$_, $timestamp, $datacenter_id, $worker_id, $sequence] = $this->config->parse((int) $id);
Expand Down
7 changes: 7 additions & 0 deletions src/Factories/SonyflakeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ public function makeFromTimestamp(CarbonInterface $timestamp): Sonyflake
return new Sonyflake($timestamp, $sequence, $this->machine_id, $this->epoch, $this->config);
}

public function firstForTimestamp(CarbonInterface $timestamp): Sonyflake
{
$timestamp = $this->diffFromEpoch($timestamp);

return new Sonyflake($timestamp, 0, 0, $this->epoch, $this->config);
}

public function fromId(int|string $id): Sonyflake
{
[$timestamp, $sequence, $machine_id] = $this->config->parse((int) $id);
Expand Down
20 changes: 18 additions & 2 deletions tests/Unit/CustomTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,28 @@ public function test_a_bit_can_be_created_for_a_specific_timestamp(): void
$factory = $this->getBitsFactory(14);

$bits = $factory->makeFromTimestamp(now()->addMicrosecond());
$this->assertEquals([1, 14, 0], $bits->values->all());

$this->assertEquals(1, $bits->values[0]);
$bits = $factory->makeFromTimestamp(now()->addMicrosecond());
$this->assertEquals([1, 14, 1], $bits->values->all());

$bits = $factory->makeFromTimestamp(now()->addMicroseconds(42));
$this->assertEquals([42, 14, 0], $bits->values->all());
}

public function test_a_bit_can_be_created_for_querying_by_a_specific_timestamp(): void
{
Date::setTestNow(now());

$factory = $this->getBitsFactory(14);

$bits = $factory->firstForTimestamp(now()->addMicrosecond());

$this->assertEquals([1, 0, 0], $bits->values->all());

$bits = $factory->firstForTimestamp(now()->addMicroseconds(42));

$this->assertEquals(42, $bits->values[0]);
$this->assertEquals([42, 0, 0], $bits->values->all());
}

protected function getBitsFactory(int $id, ResolvesSequences $sequence = null): GenericFactory
Expand Down
40 changes: 39 additions & 1 deletion tests/Unit/SnowflakeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,53 @@ public function test_it_sleeps_1ms_when_sequence_limit_is_reached(): void

public function test_a_snowflake_can_be_created_for_a_specific_timestamp(): void
{
$factory = $this->app->make(MakesSnowflakes::class);
$factory = new SnowflakeFactory(
epoch: now(),
datacenter_id: 1,
worker_id: 15,
config: app(SnowflakesConfig::class),
sequence: new InMemorySequenceResolver(),
);

$snowflake = $factory->makeFromTimestamp($factory->epoch->toImmutable()->addMillisecond());

$this->assertEquals(1, $snowflake->timestamp);
$this->assertEquals(1, $snowflake->datacenter_id);
$this->assertEquals(15, $snowflake->worker_id);
$this->assertEquals(0, $snowflake->sequence);

$snowflake = $factory->makeFromTimestamp($factory->epoch->toImmutable()->addMillisecond());

$this->assertEquals(1, $snowflake->timestamp);
$this->assertEquals(1, $snowflake->datacenter_id);
$this->assertEquals(15, $snowflake->worker_id);
$this->assertEquals(1, $snowflake->sequence);

$snowflake = $factory->makeFromTimestamp($factory->epoch->toImmutable()->addMilliseconds(42));

$this->assertEquals(42, $snowflake->timestamp);
$this->assertEquals(1, $snowflake->datacenter_id);
$this->assertEquals(15, $snowflake->worker_id);
$this->assertEquals(0, $snowflake->sequence);
}

public function test_a_snowflake_can_be_created_for_querying_by_a_specific_timestamp(): void
{
$factory = $this->app->make(MakesSnowflakes::class);

$snowflake = $factory->firstForTimestamp($factory->epoch->toImmutable()->addMillisecond());

$this->assertEquals(1, $snowflake->timestamp);
$this->assertEquals(0, $snowflake->datacenter_id);
$this->assertEquals(0, $snowflake->worker_id);
$this->assertEquals(0, $snowflake->sequence);

$snowflake = $factory->firstForTimestamp($factory->epoch->toImmutable()->addMilliseconds(42));

$this->assertEquals(42, $snowflake->timestamp);
$this->assertEquals(0, $snowflake->datacenter_id);
$this->assertEquals(0, $snowflake->worker_id);
$this->assertEquals(0, $snowflake->sequence);
}

public function test_a_snowflake_can_be_serialized_to_json(): void
Expand Down
19 changes: 18 additions & 1 deletion tests/Unit/SonyflakeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public function test_it_sleeps_10ms_when_sequence_limit_is_reached(): void
Sleep::assertSlept(fn(CarbonInterval $interval) => (int) $interval->totalMicroseconds === 10000);
}

public function test_a_snowflake_can_be_created_for_a_specific_timestamp(): void
public function test_a_sonyflake_can_be_created_for_a_specific_timestamp(): void
{
$factory = $this->app->make(MakesSonyflakes::class);

Expand All @@ -164,4 +164,21 @@ public function test_a_snowflake_can_be_created_for_a_specific_timestamp(): void

$this->assertEquals(42, $sonyflake->timestamp);
}

public function test_a_sonyflake_can_be_created_for_querying_by_a_specific_timestamp(): void
{
$factory = $this->app->make(MakesSonyflakes::class);

$sonyflake = $factory->firstForTimestamp($factory->epoch->toImmutable()->addMilliseconds(10));

$this->assertEquals(1, $sonyflake->timestamp);
$this->assertEquals(0, $sonyflake->sequence);
$this->assertEquals(0, $sonyflake->machine_id);

$sonyflake = $factory->firstForTimestamp($factory->epoch->toImmutable()->addMilliseconds(420));

$this->assertEquals(42, $sonyflake->timestamp);
$this->assertEquals(0, $sonyflake->sequence);
$this->assertEquals(0, $sonyflake->machine_id);
}
}

0 comments on commit dbe3b4a

Please sign in to comment.