Skip to content

Commit

Permalink
[6.0] feat: implement data boost (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
taka-oyama committed Nov 17, 2023
1 parent 9efa8ba commit 4a8aaa7
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# v6.0.0 [Not released Yet]

Added
- Add [Data Boost](https://cloud.google.com/spanner/docs/databoost/databoost-overview) support (#131)
- Deprecation warnings to `Connection`'s methods `cursorWithTimestampBound` `selectWithTimestampBound` `selectOneWithTimestampBound`. Use `cursorWithOptions` `selectWithOptions` instead. (#122)
- `Connection` has new methods `selectWithOptions` `cursorWithOptions` which allows spanner specific options to be set for each query. (#122)

Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,28 @@ $queryBuilder

Stale reads always runs as read-only transaction with `singleUse` option. So you can not run as read-write transaction.

### Data Boost

Data boost creates snapshot and runs the query in parallel without affecting existing workloads.

You can read more about it [here](https://cloud.google.com/spanner/docs/databoost/databoost-overview).

Below are some examples of how to use it.

```php
// Using Connection
$connection->selectWithOptions('SELECT ...', $bindings, ['dataBoostEnabled' => true]);

// Using Query Builder
$queryBuilder
->useDataBoost()
->get();
```

> [!NOTE]
> This creates a new session in the background which is not shared with the current session pool.
> This means, queries running with data boost will not be associated with transactions that may be taking place.
### Data Types
Some data types of Google Cloud Spanner does not have corresponding built-in type of PHP.
You can use following classes by [Google Cloud PHP Client](https://github.com/googleapis/google-cloud-php)
Expand Down
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ parameters:
path: src/Connection.php
- message: '#^Method Colopl\\Spanner\\Connection::selectWithOptions\(\) should return array<int, array> but returns mixed\.$#'
path: src/Connection.php
- message: '#^Generator expects value type array, mixed given.$#'
path: src/Connection.php
count: 1
- message: '#^Cannot cast mixed to int\.$#'
path: src/Eloquent/Model.php
- message: '#^Property Illuminate\\Database\\Schema\\Builder::\$resolver \(Closure\) in isset\(\) is not nullable\.$#'
Expand Down
2 changes: 0 additions & 2 deletions src/Concerns/ManagesSessionPool.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ public function maintainSessionPool(): bool
return false;
}



/**
* @return int Number of warmed up sessions
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Concerns/ManagesStaleReads.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
trait ManagesStaleReads
{
/**
* @deprecated use selectWithOptions() instead. This method will be removed in v7.
* @deprecated use cursorWithOptions() instead. This method will be removed in v7.
* @param string $query
* @param array<array-key, mixed> $bindings
* @param TimestampBoundInterface|null $timestampBound
Expand Down
22 changes: 22 additions & 0 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,33 @@ protected function executeQuery(string $query, array $bindings, array $options):
{
$options += ['parameters' => $this->prepareBindings($bindings)];

if (isset($options['dataBoostEnabled'])) {
return $this->executePartitionedQuery($query, $options);
}

return $this->getDatabaseContext()
->execute($query, $options)
->rows();
}

/**
* @param string $query
* @param array<string, mixed> $options
* @return Generator<int, array<array-key, mixed>>
*/
protected function executePartitionedQuery(string $query, array $options): Generator
{
$snapshot = $this->getSpannerClient()
->batch($this->instanceId, $this->database, $options)
->snapshot();

foreach ($snapshot->partitionQuery($query, $options) as $partition) {
foreach ($snapshot->executePartition($partition) as $row) {
yield $row;
}
}
}

/**
* Check if this is "session not found" error
*
Expand Down
11 changes: 8 additions & 3 deletions src/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@

class Builder extends BaseBuilder
{
use Concerns\UsesMutations,
Concerns\UsesPartitionedDml,
Concerns\UsesStaleReads;
use Concerns\UsesDataBoost;
use Concerns\UsesMutations;
use Concerns\UsesPartitionedDml;
use Concerns\UsesStaleReads;

/**
* @var Connection
Expand Down Expand Up @@ -136,6 +137,10 @@ protected function runSelect()
$bindings = $this->getBindings();
$options = [];

if ($this->dataBoostEnabled()) {
$options += ['dataBoostEnabled' => true];
}

if ($this->timestampBound !== null) {
$options += $this->timestampBound->transactionOptions();
}
Expand Down
44 changes: 44 additions & 0 deletions src/Query/Concerns/UsesDataBoost.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
/**
* Copyright 2019 Colopl Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Colopl\Spanner\Query\Concerns;

trait UsesDataBoost
{
/**
* @var bool
*/
protected bool $useDataBoost = false;

/**
* @param bool $toggle
* @return $this
*/
public function useDataBoost(bool $toggle = true): static
{
$this->useDataBoost = $toggle;
return $this;
}

/**
* @return bool
*/
public function dataBoostEnabled(): bool
{
return $this->useDataBoost;
}
}
21 changes: 21 additions & 0 deletions tests/Query/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -836,4 +836,25 @@ public function test_toRawSql(): void
$sql = $conn->table($table)->where('s', "t\"e\"s\nt")->toRawSql();
$this->assertSame("select * from `RawSqlTest` where `s` = r\"\"\"t\\\"e\\\"s\nt\"\"\"", $sql, 'newline with escaped quote');
}

public function test_dataBoost_enabled(): void
{
$conn = $this->getDefaultConnection();
$tableName = self::TABLE_NAME_USER;

$conn->table($tableName)->insert(['userId' => $this->generateUuid(), 'name' => __FUNCTION__]);

$query = $conn->table($tableName)->useDataBoost();
$result = $query->get();

$this->assertTrue($query->dataBoostEnabled());
$this->assertSame(1, $result->count());
$this->assertSame(__FUNCTION__, $result->first()['name']);
}

public function test_dataBoost_disabled(): void
{
$query = $this->getDefaultConnection()->table('t')->useDataBoost(false);
$this->assertFalse($query->dataBoostEnabled());
}
}

0 comments on commit 4a8aaa7

Please sign in to comment.