Skip to content

Commit

Permalink
feat: Transaction and request tagging support (#206)
Browse files Browse the repository at this point in the history
  • Loading branch information
taka-oyama authored Apr 17, 2024
1 parent 4caec32 commit 3f91d3b
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# v8.1.0 (2024-04-16)

Added
- Request and Transaction tagging support (#206)

# v8.0.0 (2024-04-11)

Added
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,19 @@ $queryBuilder
> 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.
### Request Tags and Transaction Tags

Spanner allows you to attach tags to your queries and transactions that can be [used for troubleshooting](https://cloud.google.com/spanner/docs/introspection/troubleshooting-with-tags).

You can set request tags and transaction tags as below.

```php
$requestPath = request()->path();
$tag = 'url=' . $requestPath;
$connection->setRequestTag($tag);
$connection->setTransactionTag($tag);
```

### Data Types

Some data types of Google Cloud Spanner does not have corresponding built-in type of PHP.
Expand Down
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ parameters:
- message: "#^Expression on left side of \\?\\? is not nullable\\.$#"
count: 1
path: src/Connection.php
- message: "#^Cannot access offset 'requestTag' on mixed\\.$#"
count: 1
path: src/Connection.php
67 changes: 67 additions & 0 deletions src/Concerns/ManagesTagging.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?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\Concerns;

trait ManagesTagging
{
/**
* @var string|null
*/
protected ?string $requestTag = null;

/**
* @var string|null
*/
protected ?string $transactionTag = null;

/**
* @param string|null $tag
* @return $this
*/
public function setRequestTag(?string $tag): static
{
$this->requestTag = $tag;
return $this;
}

/**
* @return string|null
*/
public function getRequestTag(): ?string
{
return $this->requestTag;
}

/**
* @param string|null $tag
* @return $this
*/
public function setTransactionTag(?string $tag): static
{
$this->transactionTag = $tag;
return $this;
}

/**
* @return string|null
*/
public function getTransactionTag(): ?string
{
return $this->transactionTag;
}
}
11 changes: 9 additions & 2 deletions src/Concerns/ManagesTransactions.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@ public function transaction(Closure $callback, $attempts = -1)
return parent::transaction($callback, $attempts);
}

return $this->withSessionNotFoundHandling(function () use ($callback, $attempts) {
$options = ['maxRetries' => $attempts - 1];

$tag = $this->getTransactionTag();
if ($tag !== null) {
$options['tag'] = $tag;
}

return $this->withSessionNotFoundHandling(function () use ($callback, $options) {
$return = $this->getSpannerDatabase()->runTransaction(function (Transaction $tx) use ($callback) {
try {
$this->currentTransaction = $tx;
Expand All @@ -81,7 +88,7 @@ public function transaction(Closure $callback, $attempts = -1)
$this->rollBack();
throw $e;
}
}, ['maxRetries' => $attempts - 1]);
}, $options);

$this->fireConnectionEvent('committed');

Expand Down
14 changes: 11 additions & 3 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Connection extends BaseConnection
Concerns\ManagesMutations,
Concerns\ManagesPartitionedDml,
Concerns\ManagesSessionPool,
Concerns\ManagesTagging,
Concerns\ManagesTransactions,
Concerns\MarksAsNotSupported;

Expand Down Expand Up @@ -571,9 +572,16 @@ protected function executeQuery(string $query, array $bindings, array $options):
return $this->executePartitionedQuery($query, $options);
}

return $this->getDatabaseContext()
->execute($query, $options)
->rows();
$tag = $this->getRequestTag();
if ($tag !== null) {
$options['requestOptions'] ??= [];
$options['requestOptions']['requestTag'] = $tag;
}

if ($transaction = $this->getCurrentTransaction()) {
return $transaction->execute($query, $options)->rows();
}
return $this->getSpannerDatabase()->execute($query, $options)->rows();
}

/**
Expand Down
44 changes: 44 additions & 0 deletions tests/Concerns/ManagesTagsTest.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\Tests\Concerns;

use Colopl\Spanner\Connection;
use Colopl\Spanner\Tests\TestCase;

class ManagesTagsTest extends TestCase
{
public function test_set_and_get_requestTag(): void
{
$conn = $this->getConnection();
assert($conn instanceof Connection);
$conn->setRequestTag('url=/api/users');
$this->assertSame('url=/api/users', $conn->getRequestTag());
$conn->setRequestTag(null);
$this->assertNull($conn->getRequestTag());
}

public function test_set_and_get_transactionTag(): void
{
$conn = $this->getDefaultConnection();
assert($conn instanceof Connection);
$conn->setTransactionTag('url=/api/users/update');
$this->assertSame('url=/api/users/update', $conn->getTransactionTag());
$conn->setTransactionTag(null);
$this->assertNull($conn->getTransactionTag());
}
}

0 comments on commit 3f91d3b

Please sign in to comment.