Skip to content
This repository has been archived by the owner on Sep 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #21 from dew-serverless/refactoring
Browse files Browse the repository at this point in the history
Build throughput reservations and table options on the fly
  • Loading branch information
lizhineng authored Dec 14, 2023
2 parents be2f77f + 8adb96c commit 4cecba5
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 169 deletions.
68 changes: 34 additions & 34 deletions src/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace Dew\Tablestore\Schema;

use Protos\CapacityUnit;
use Protos\DefinedColumnType;
use Protos\PrimaryKeyType;
use Protos\ReservedThroughput;
use Protos\SSEKeyType;
use Protos\SSESpecification;
use Protos\TableOptions;

class Blueprint
{
Expand All @@ -17,38 +20,14 @@ class Blueprint
public array $columns = [];

/**
* The throughput reservations for reading in capacity unit.
*
* @var non-negative-int|null
*/
public ?int $reservedRead = null;

/**
* The throughput reservations for writing in capacity unit.
*
* @var non-negative-int|null
*/
public ?int $reservedWrite = null;

/**
* The number of seconds that data can exist.
*/
public ?int $ttl = null;

/**
* The maximum versions to persist.
*/
public ?int $maxVersions = null;

/**
* The version offset limit.
* The throughput reservations.
*/
public ?int $versionOffset = null;
public ?ReservedThroughput $throughput = null;

/**
* Determine if the existing row can be updated.
* The table options.
*/
public ?bool $allowsUpdate = null;
public ?TableOptions $options = null;

/**
* Determine if the data should be encrypted.
Expand Down Expand Up @@ -123,7 +102,9 @@ public function binary(string $column): Keyable
*/
public function reserveRead(int $capacityUnit): self
{
$this->reservedRead = $capacityUnit;
$this->throughput = (new ReservedThroughput)->setCapacityUnit(
$this->throughputCu()->setRead($capacityUnit)
);

return $this;
}
Expand All @@ -135,7 +116,9 @@ public function reserveRead(int $capacityUnit): self
*/
public function reserveWrite(int $capacityUnit): self
{
$this->reservedWrite = $capacityUnit;
$this->throughput = (new ReservedThroughput)->setCapacityUnit(
$this->throughputCu()->setWrite($capacityUnit)
);

return $this;
}
Expand All @@ -145,7 +128,7 @@ public function reserveWrite(int $capacityUnit): self
*/
public function ttl(int $seconds): self
{
$this->ttl = $seconds;
$this->options = $this->options()->setTimeToLive($seconds);

return $this;
}
Expand All @@ -163,7 +146,7 @@ public function forever(): self
*/
public function maxVersions(int $versions): self
{
$this->maxVersions = $versions;
$this->options = $this->options()->setMaxVersions($versions);

return $this;
}
Expand All @@ -173,7 +156,8 @@ public function maxVersions(int $versions): self
*/
public function versionOffsetIn(int $seconds): self
{
$this->versionOffset = $seconds;
$this->options = $this->options()
->setDeviationCellVersionInSec($seconds);

return $this;
}
Expand All @@ -183,7 +167,7 @@ public function versionOffsetIn(int $seconds): self
*/
public function allowUpdate(bool $allows = true): self
{
$this->allowsUpdate = $allows;
$this->options = $this->options()->setAllowUpdate($allows);

return $this;
}
Expand Down Expand Up @@ -226,4 +210,20 @@ public function withoutEncryption(): self

return $this;
}

/**
* Get the current throughput reservations or create a new one.
*/
protected function throughputCu(): CapacityUnit
{
return $this->throughput?->getCapacityUnit() ?? new CapacityUnit;
}

/**
* Get the current table options or create a new one.
*/
protected function options(): TableOptions
{
return $this->options ?? new TableOptions;
}
}
82 changes: 12 additions & 70 deletions src/Schema/SchemaHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Dew\Tablestore\Concerns\InteractsWithRequest;
use Dew\Tablestore\Tablestore;
use InvalidArgumentException;
use Protos\CapacityUnit;
use Protos\CreateTableRequest;
use Protos\CreateTableResponse;
use Protos\DefinedColumnSchema;
Expand Down Expand Up @@ -67,8 +66,14 @@ public function createTable(string $name, Blueprint $table): CreateTableResponse
{
$request = new CreateTableRequest;
$request->setTableMeta($this->toTableMeta($table)->setTableName($name));
$request->setReservedThroughput($this->toReservedThroughput($table));
$request->setTableOptions($this->toTableOptions($table));

if ($table->throughput instanceof ReservedThroughput) {
$request->setReservedThroughput($table->throughput);
}

if ($table->options instanceof TableOptions) {
$request->setTableOptions($table->options);
}

if ($table->encryption instanceof SSESpecification) {
$request->setSseSpec($table->encryption);
Expand All @@ -87,12 +92,12 @@ public function updateTable(string $name, Blueprint $table): UpdateTableResponse
{
$request = (new UpdateTableRequest)->setTableName($name);

if ($this->hasReservedThroughputUpdate($table)) {
$request->setReservedThroughput($this->toReservedThroughput($table));
if ($table->throughput instanceof ReservedThroughput) {
$request->setReservedThroughput($table->throughput);
}

if ($this->hasTableOptionsUpdate($table)) {
$request->setTableOptions($this->toTableOptions($table));
if ($table->options instanceof TableOptions) {
$request->setTableOptions($table->options);
}

$response = new UpdateTableResponse;
Expand Down Expand Up @@ -137,67 +142,4 @@ public function toTableMeta(Blueprint $table): TableMeta
->setPrimaryKey($pks)
->setDefinedColumn($cols);
}

/**
* Create a throughput reservations Protobuf message.
*/
public function toReservedThroughput(Blueprint $table): ReservedThroughput
{
$cu = new CapacityUnit;

if (is_int($table->reservedRead)) {
$cu->setRead($table->reservedRead);
}

if (is_int($table->reservedWrite)) {
$cu->setWrite($table->reservedWrite);
}

return (new ReservedThroughput)->setCapacityUnit($cu);
}

/**
* Determine if the throughput reservations have been changed.
*/
public function hasReservedThroughputUpdate(Blueprint $table): bool
{
return $table->reservedRead !== null || $table->reservedWrite !== null;
}

/**
* Create a table options Protobuf message.
*/
public function toTableOptions(Blueprint $table): TableOptions
{
$options = new TableOptions;

if (is_int($table->ttl)) {
$options->setTimeToLive($table->ttl);
}

if (is_int($table->maxVersions)) {
$options->setMaxVersions($table->maxVersions);
}

if (is_int($table->versionOffset)) {
$options->setDeviationCellVersionInSec($table->versionOffset);
}

if (is_bool($table->allowsUpdate)) {
$options->setAllowUpdate($table->allowsUpdate);
}

return $options;
}

/**
* Determine if the table options have been modified.
*/
public function hasTableOptionsUpdate(Blueprint $table): bool
{
return $table->ttl !== null
|| $table->maxVersions !== null
|| $table->versionOffset !== null
|| $table->allowsUpdate !== null;
}
}
59 changes: 59 additions & 0 deletions tests/BlueprintTest.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,67 @@
<?php

use Dew\Tablestore\Schema\Blueprint;
use Protos\ReservedThroughput;
use Protos\SSEKeyType;
use Protos\SSESpecification;
use Protos\TableOptions;

test('throughput reserves read', function () {
$table = (new Blueprint)->reserveRead(2);
expect($table->throughput)->toBeInstanceOf(ReservedThroughput::class)
->and($table->throughput->getCapacityUnit()->getRead())->toBe(2)
->and($table->throughput->getCapacityUnit()->hasWrite())->toBeFalse();
});

test('throughput reserves write', function () {
$table = (new Blueprint)->reserveWrite(1);
expect($table->throughput)->toBeInstanceOf(ReservedThroughput::class)
->and($table->throughput->getCapacityUnit()->getWrite())->toBe(1)
->and($table->throughput->getCapacityUnit()->hasRead())->toBeFalse();
});

test('throughput reservations', function () {
$table = (new Blueprint)->reserveRead(2)->reserveWrite(1);
expect($table->throughput)->toBeInstanceOf(ReservedThroughput::class)
->and($table->throughput->getCapacityUnit()->getRead())->toBe(2)
->and($table->throughput->getCapacityUnit()->getWrite())->toBe(1);
});

test('table option configures time-to-live', function () {
$table = (new Blueprint)->ttl(86400);
expect($table->options)->toBeInstanceOf(TableOptions::class)
->and($table->options->getTimeToLive())->toBe(86400);
});

test('table option configures data that is stored permanently', function () {
$table = (new Blueprint)->forever();
expect($table->options)->toBeInstanceOf(TableOptions::class)
->and($table->options->getTimeToLive())->toBe(-1);
});

test('table option defines max versions to persist', function () {
$table = (new Blueprint)->maxVersions(2);
expect($table->options)->toBeInstanceOf(TableOptions::class)
->and($table->options->getMaxVersions())->toBe(2);
});

test('table option limits version offset', function () {
$table = (new Blueprint)->versionOffsetIn(86400 * 2); // 2 days
expect($table->options)->toBeInstanceOf(TableOptions::class)
->and($table->options->getDeviationCellVersionInSec())->toBe(86400 * 2);
});

test('table option allows update', function () {
$table = (new Blueprint)->allowUpdate();
expect($table->options)->toBeInstanceOf(TableOptions::class)
->and($table->options->getAllowUpdate())->toBeTrue();
});

test('table option denies update', function () {
$table = (new Blueprint)->allowUpdate(false);
expect($table->options)->toBeInstanceOf(TableOptions::class)
->and($table->options->getAllowUpdate())->toBeFalse();
});

test('sse encrypts with kms', function () {
$table = (new Blueprint)->encryptWithKms();
Expand Down
65 changes: 0 additions & 65 deletions tests/SchemaHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,68 +55,3 @@
->and($cols[4]->getName())->toBe('blob')
->and($cols[4]->getType())->toBe(DefinedColumnType::DCT_BLOB);
});

test('throughput reserves read', function () {
$table = (new Blueprint)->reserveRead(2);
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toReservedThroughput($table)->getCapacityUnit()->getRead())->toBe(2);
});

test('throughput reserves write', function () {
$table = (new Blueprint)->reserveRead(1);
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toReservedThroughput($table)->getCapacityUnit()->getRead())->toBe(1);
});

test('table option configures time-to-live', function () {
$table = (new Blueprint)->ttl(86400);
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toTableOptions($table)->getTimeToLive())->toBe(86400);
});

test('table option configures data that is stored permanently', function () {
$table = (new Blueprint)->forever();
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toTableOptions($table)->getTimeToLive())->toBe(-1);
});

test('table option defines max versions to persist', function () {
$table = (new Blueprint)->maxVersions(2);
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toTableOptions($table)->getMaxVersions())->toBe(2);
});

test('table option limits version offset', function () {
$table = (new Blueprint)->versionOffsetIn(86400 * 2); // 2 days
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toTableOptions($table)->getDeviationCellVersionInSec())->toBe(86400 * 2);
});

test('table option allows update', function () {
$table = (new Blueprint)->allowUpdate();
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toTableOptions($table)->getAllowUpdate())->toBeTrue();
});

test('table option denies update', function () {
$table = (new Blueprint)->allowUpdate(false);
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->toTableOptions($table)->getAllowUpdate())->toBeFalse();
});

test('throughput reservations change determination', function () {
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->hasReservedThroughputUpdate(new Blueprint))->toBeFalse();
expect($handler->hasReservedThroughputUpdate((new Blueprint)->reserveRead(2)))->toBeTrue();
expect($handler->hasReservedThroughputUpdate((new Blueprint)->reserveWrite(1)))->toBeTrue();
});

test('table options modify determination', function () {
$handler = new SchemaHandler(Mockery::mock(Tablestore::class));
expect($handler->hasTableOptionsUpdate(new Blueprint))->toBeFalse();
expect($handler->hasTableOptionsUpdate((new Blueprint)->ttl(86400 * 30)))->toBeTrue();
expect($handler->hasTableOptionsUpdate((new Blueprint)->maxVersions(10)))->toBeTrue();
expect($handler->hasTableOptionsUpdate((new Blueprint)->versionOffsetIn(86400)))->toBeTrue();
expect($handler->hasTableOptionsUpdate((new Blueprint)->allowUpdate(true)))->toBeTrue();
expect($handler->hasTableOptionsUpdate((new Blueprint)->allowUpdate(false)))->toBeTrue();
});

0 comments on commit 4cecba5

Please sign in to comment.