diff --git a/CHANGELOG.md b/CHANGELOG.md index 815e2caa..975e2528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -# v6.1.0 (Not Released Yet) +# v6.1.1 (Not Released Yet) + +Fixed +- Bug where auth and session pool writing to the same file may cause race condition (#152) + +# v6.1.0 (2023-11-29) Added - Add support for [NUMERIC](https://cloud.google.com/spanner/docs/reference/standard-sql/data-types#numeric_type) column type. (#145) diff --git a/phpstan.neon b/phpstan.neon index 30c8458f..bbf99887 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -35,3 +35,6 @@ parameters: - message: '#^Property Colopl\\Spanner\\Session\\SessionInfo\:\:\$labels \(array\\) does not accept array\.$#' path: src/Session/SessionInfo.php count: 1 + - message: "#^Method Colopl\\\\Spanner\\\\SpannerServiceProvider\\:\\:parseConfig\\(\\) should return array\\{name\\: string, instance\\: string, database\\: string, prefix\\: string, cache_path\\: string|null, session_pool\\: array\\\\} but returns non\\-empty\\-array\\\\.$#" + count: 1 + path: src/SpannerServiceProvider.php diff --git a/src/SpannerServiceProvider.php b/src/SpannerServiceProvider.php index 590da686..41c1ff9f 100644 --- a/src/SpannerServiceProvider.php +++ b/src/SpannerServiceProvider.php @@ -21,10 +21,12 @@ use Colopl\Spanner\Console\SessionsCommand; use Colopl\Spanner\Console\WarmupCommand; use Google\Cloud\Spanner\Session\CacheSessionPool; +use Google\Cloud\Spanner\Session\SessionPoolInterface; use Illuminate\Database\DatabaseManager; use Illuminate\Queue\QueueManager; use Illuminate\Support\Facades\DB; use Illuminate\Support\ServiceProvider; +use LogicException; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\FilesystemAdapter; @@ -56,40 +58,76 @@ public function boot(): void } /** - * @param array $config + * @param array{ + * name: string, + * instance: string, + * database: string, + * prefix: string, + * cache_path: string|null, + * session_pool: array, + * } $config * @return Connection */ protected function createSpannerConnection(array $config): Connection { - $cache = $this->getCacheAdapter( - $config['name'], - $config['cache_path'] ?? null, - ); - return new Connection( $config['instance'], $config['database'], $config['prefix'], $config, - $cache, - new CacheSessionPool($cache, $config['session_pool'] ?? []) + $this->createAuthCache($config), + $this->createSessionPool($config), ); } /** * @param array $config * @param string $name - * @return array + * @return array{ + * name: string, + * instance: string, + * database: string, + * prefix: string, + * cache_path: string|null, + * session_pool: array, + * } $config */ protected function parseConfig(array $config, string $name): array { + if ($name === '_auth') { + throw new LogicException('Connection name "_auth" is reserved.'); + } + return $config + [ 'prefix' => '', 'name' => $name, + 'cache_path' => null, + 'session_pool' => [], 'useGapicBackoffs' => true, ]; } + /** + * @param array{ cache_path: string|null } $config + * @return AdapterInterface + */ + protected function createAuthCache(array $config): AdapterInterface + { + return $this->getCacheAdapter('_auth', $config['cache_path']); + } + + /** + * @param array{ name: string, cache_path: string|null, session_pool: array } $config + * @return SessionPoolInterface + */ + protected function createSessionPool(array $config): SessionPoolInterface + { + return new CacheSessionPool( + $this->getCacheAdapter($config['name'], $config['cache_path']), + $config['session_pool'], + ); + } + /** * @param string $namespace * @param string|null $path @@ -101,6 +139,9 @@ protected function getCacheAdapter(string $namespace, ?string $path): AdapterInt return new FilesystemAdapter($namespace, 0, $path); } + /** + * @return void + */ protected function closeSessionAfterEachQueueJob(): void { $this->app->resolving('queue', function (QueueManager $queue): void {