Skip to content

Commit

Permalink
Merge pull request #69 from ray-di/env_slave
Browse files Browse the repository at this point in the history
Slave can also be specified by environment variable
  • Loading branch information
koriym authored Sep 30, 2022
2 parents 980d567 + 7040a79 commit edf1dec
Show file tree
Hide file tree
Showing 17 changed files with 584 additions and 199 deletions.
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,26 @@ class AppModule extends AbstractModule
'password',
'slave1,slave2,slave3' // optional slave server list
$options, // optional key=>value array of driver-specific connection options
$attributes // optional key=>value attriburtes
$queries // Queries to execute after the connection.
);
}
}
```

Use AuraSqlEnvModule to get the value from the environment variable each time at runtime, instead of specifying the value directly.

```php
$this->install(
new AuraSqlEnvModule(
'PDO_DSN', // getenv('PDO_DSN')
'PDO_USER', // getenv('PDO_USER')
'PDO_PASSWORD', // getenv('PDO_PASSWORD')
'PDO_SLAVE' // getenv('PDO_SLAVE')
$options, // optional key=>value array of driver-specific connection options
$queries // Queries to execute after the connection.
);
```

### DI trait

* [AuraSqlInject](https://github.com/ray-di/Ray.AuraSqlModule/blob/1.x/src/AuraSqlInject.php) for `Aura\Sql\ExtendedPdoInterface` interface
Expand Down Expand Up @@ -80,7 +95,6 @@ public function setLoggerDb(#[Named('log_db') ExtendedPdoInterface $pdo)
}
```


### with no replication

Use `NamedPdoModule ` to inject different named `Pdo` instance for **non** Replication use.
Expand All @@ -96,6 +110,18 @@ class AppModule extends AbstractModule
}
```

Or

```php
class AppModule extends AbstractModule
{
protected function configure()
{
$this->install(new NamedPdoEnvModule('log_db', 'LOG_DSN', 'LOG_USERNAME',
}
}


### with replication

You can set `$qaulifer` in 2nd parameter of AuraSqlReplicationModule.
Expand Down
34 changes: 34 additions & 0 deletions src/AuraSqlBaseModule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Ray\AuraSqlModule;

use Ray\AuraSqlModule\Pagerfanta\AuraSqlPagerModule;
use Ray\Di\AbstractModule;

use function preg_match;

class AuraSqlBaseModule extends AbstractModule
{
private string $dsn;

public function __construct(string $dsnKey, ?AbstractModule $module = null)
{
$this->dsn = $dsnKey;
parent::__construct($module);
}

/**
* {@inheritdoc}
*/
protected function configure(): void
{
// @Transactional
$this->install(new TransactionalModule());
$this->install(new AuraSqlPagerModule());
preg_match(AuraSqlModule::PARSE_PDO_DSN_REGEX, $this->dsn, $parts);
$dbType = $parts[1] ?? '';
$this->install(new AuraSqlQueryModule($dbType));
}
}
51 changes: 26 additions & 25 deletions src/AuraSqlEnvModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,43 @@

namespace Ray\AuraSqlModule;

use Ray\AuraSqlModule\Annotation\EnvAuth;
use Ray\Di\AbstractModule;

class AuraSqlEnvModule extends AbstractModule
{
private string $dsn;
private string $user;
private string $username;
private string $password;
private string $slave;

/** @var array<mixed> */
/** @var array<string> */
private array $options;

/** @var array<string> */
private array $queries;

/**
* @param string $dsn Data Source Name (DSN)
* @param string $user User name for the DSN string
* @param string $password Password for the DSN string
* @param string $slave Comma separated slave host list
* @param array<mixed> $options A key=>value array of driver-specific connection options
* @param string $dsnKey Env key for Data Source Name (DSN)
* @param string $usernameKey Env key for Username for the DSN string
* @param string $passwordKey Env key for Password for the DSN string
* @param string $slaveKey Env key for Comma separated slave host list
* @param array<string> $options A key=>value array of driver-specific connection options
* @param array<string> $queries Queries to execute after the connection.
*/
public function __construct(string $dsn, string $user = '', string $password = '', string $slave = '', array $options = [])
{
$this->dsn = $dsn;
$this->user = $user;
$this->password = $password;
$this->slave = $slave;
public function __construct(
string $dsnKey,
string $usernameKey = '',
string $passwordKey = '',
string $slaveKey = '',
array $options = [],
array $queries = []
) {
$this->dsn = $dsnKey;
$this->username = $usernameKey;
$this->password = $passwordKey;
$this->slave = $slaveKey;
$this->options = $options;
$this->queries = $queries;
parent::__construct();
}

Expand All @@ -39,16 +49,7 @@ public function __construct(string $dsn, string $user = '', string $password = '
*/
protected function configure(): void
{
$this->bind()->annotatedWith(EnvAuth::class)->toInstance(
[
'dsn' => $this->dsn,
'user' => $this->user,
'password' => $this->password,
]
);
$this->bind()->annotatedWith('pdo_dsn')->toProvider(EnvAuthProvider::class, 'dsn');
$this->bind()->annotatedWith('pdo_user')->toProvider(EnvAuthProvider::class, 'user');
$this->bind()->annotatedWith('pdo_pass')->toProvider(EnvAuthProvider::class, 'password');
$this->install(new AuraSqlModule('', '', '', $this->slave, $this->options));
$this->install(new NamedPdoEnvModule('', $this->dsn, $this->username, $this->password, $this->slave, $this->options, $this->queries));
$this->install(new AuraSqlBaseModule($this->dsn));
}
}
19 changes: 14 additions & 5 deletions src/AuraSqlMasterModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ class AuraSqlMasterModule extends AbstractModule
* @phpstan-param array<string> $options
* @phpstan-param array<string> $attributes
*/
public function __construct(string $dsn, string $user = '', string $password = '', array $options = [], array $attributes = [], ?AbstractModule $module = null)
{
$this->dsn = $dsn;
public function __construct(
string $dsnKey,
string $user = '',
string $passwordKey = '',
array $options = [],
array $attributes = [],
?AbstractModule $module = null
) {
$this->dsn = $dsnKey;
$this->user = $user;
$this->password = $password;
$this->password = $passwordKey;
$this->options = $options;
$this->attributes = $attributes;
parent::__construct($module);
Expand All @@ -40,7 +46,10 @@ public function __construct(string $dsn, string $user = '', string $password = '
*/
protected function configure(): void
{
$this->bind(ExtendedPdoInterface::class)->toConstructor(ExtendedPdo::class, 'dsn=pdo_dsn,username=pdo_user,password=pdo_pass,options=pdo_option,attributes=pdo_attributes')->in(Scope::SINGLETON);
$this->bind(ExtendedPdoInterface::class)->toConstructor(
ExtendedPdo::class,
'dsn=pdo_dsn,username=pdo_user,password=pdo_pass,options=pdo_option,attributes=pdo_attributes'
)->in(Scope::SINGLETON);
$this->bind()->annotatedWith('pdo_dsn')->toInstance($this->dsn);
$this->bind()->annotatedWith('pdo_user')->toInstance($this->user);
$this->bind()->annotatedWith('pdo_pass')->toInstance($this->password);
Expand Down
88 changes: 38 additions & 50 deletions src/AuraSqlModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,48 @@

namespace Ray\AuraSqlModule;

use Aura\Sql\ConnectionLocator;
use Aura\Sql\ExtendedPdo;
use Aura\Sql\ExtendedPdoInterface;
use Ray\AuraSqlModule\Pagerfanta\AuraSqlPagerModule;
use Ray\Di\AbstractModule;
use Ray\Di\Scope;

use function explode;
use function preg_match;
use function sprintf;

class AuraSqlModule extends AbstractModule
{
public const PARSE_PDO_DSN_REGEX = '/(.*?)\:(?:(host|server)=.*?;)?(.*)/i';
public const PARSE_PDO_DSN_REGEX = '/(.*?):(?:(host|server)=.*?;)?(.*)/i';

private string $dsn;
private string $user;
private string $password;
private string $slave;

/** @var array<mixed> */
/** @var array<string> */
private array $options;

/** @var array<string> */
private array $queries;

/**
* @param string $dsn Data Source Name (DSN)
* @param string $user User name for the DSN string
* @param string $password Password for the DSN string
* @param string $slave Comma separated slave host list
* @param array<mixed> $options A key=>value array of driver-specific connection options
* @param string $dsnKey Data Source Name (DSN)
* @param string $user User name for the DSN string
* @param string $passwordKey Password for the DSN string
* @param string $slaveKey Comma separated slave host list
* @param array<string> $options A key=>value array of driver-specific connection options
* @param array<string> $queries
*/
public function __construct(string $dsn, string $user = '', string $password = '', string $slave = '', array $options = [])
{
$this->dsn = $dsn;
public function __construct(
string $dsnKey,
string $user = '',
string $passwordKey = '',
string $slaveKey = '',
array $options = [],
array $queries = []
) {
$this->dsn = $dsnKey;
$this->user = $user;
$this->password = $password;
$this->slave = $slave;
$this->password = $passwordKey;
$this->slave = $slaveKey;
$this->options = $options;
$this->queries = $queries;
parent::__construct();
}

Expand All @@ -50,50 +55,33 @@ public function __construct(string $dsn, string $user = '', string $password = '
protected function configure(): void
{
$this->slave ? $this->configureMasterSlaveDsn() : $this->configureSingleDsn();
// @Transactional
$this->install(new TransactionalModule());
$this->install(new AuraSqlPagerModule());
preg_match(self::PARSE_PDO_DSN_REGEX, $this->dsn, $parts);
$dbType = $parts[1] ?? '';
$this->install(new AuraSqlQueryModule($dbType));
$this->install(new AuraSqlBaseModule($this->dsn));
}

private function configureSingleDsn(): void
{
$this->bind(ExtendedPdoInterface::class)->toConstructor(ExtendedPdo::class, 'dsn=pdo_dsn,username=pdo_user,password=pdo_pass,options=pdo_options,attributes=pdo_attributes')->in(Scope::SINGLETON);
$this->bind()->annotatedWith('pdo_dsn')->toInstance($this->dsn);
$this->bind()->annotatedWith('pdo_user')->toInstance($this->user);
$this->bind()->annotatedWith('pdo_pass')->toInstance($this->password);
$this->bind()->annotatedWith('pdo_slave')->toInstance($this->slave);
$this->bind()->annotatedWith('pdo_options')->toInstance($this->options);
$this->bind()->annotatedWith('pdo_attributes')->toInstance($this->options);
$this->bind()->annotatedWith('pdo_queries')->toInstance($this->queries);
$this->bind(ExtendedPdoInterface::class)->toConstructor(
ExtendedPdo::class,
'dsn=pdo_dsn,username=pdo_user,password=pdo_pass,options=pdo_options,queries=pdo_queries'
)->in(Scope::SINGLETON);
}

private function configureMasterSlaveDsn(): void
{
$locator = new ConnectionLocator();
$locator->setWrite('master', new Connection($this->dsn, $this->user, $this->password));
$i = 1;
$slaves = explode(',', $this->slave);
foreach ($slaves as $slave) {
$slaveDsn = $this->changeHost($this->dsn, $slave);
$name = 'slave' . (string) $i++;
$locator->setRead($name, new Connection($slaveDsn, $this->user, $this->password));
}

$locator = ConnectionLocatorFactory::fromInstance(
$this->dsn,
$this->user,
$this->password,
$this->slave,
$this->options,
$this->queries
);
$this->install(new AuraSqlReplicationModule($locator));
}

private function changeHost(string $dsn, string $host): string
{
preg_match(self::PARSE_PDO_DSN_REGEX, $dsn, $parts);
if (! $parts) {
// @codeCoverageIgnoreStart
return $dsn;
// @codeCoverageIgnoreEnd
}

$dsn = sprintf('%s:%s=%s;%s', $parts[1], $parts[2], $host, $parts[3]);

return $dsn;
}
}
13 changes: 8 additions & 5 deletions src/AuraSqlReplicationModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Ray\AuraSqlModule\Annotation\ReadOnlyConnection;
use Ray\AuraSqlModule\Annotation\WriteConnection;
use Ray\Di\AbstractModule;
use Ray\Di\Scope;

class AuraSqlReplicationModule extends AbstractModule
{
Expand All @@ -31,13 +30,17 @@ public function __construct(
*/
protected function configure(): void
{
$this->bind(ConnectionLocatorInterface::class)->annotatedWith($this->qualifer)->toInstance($this->connectionLocator);
$this->bind(ConnectionLocatorInterface::class)
->annotatedWith($this->qualifer)
->toInstance($this->connectionLocator);

// ReadOnlyConnection when GET, otherwise WriteConnection
$this->bind(ExtendedPdoInterface::class)->annotatedWith($this->qualifer)->toProvider(AuraSqlReplicationDbProvider::class, $this->qualifer)->in(Scope::SINGLETON);
$this->bind(ExtendedPdoInterface::class)
->annotatedWith($this->qualifer)
->toProvider(AuraSqlReplicationDbProvider::class, $this->qualifer);

// @ReadOnlyConnection @WriteConnection
$this->installReadWriteConnection();
// @Transactional
$this->install(new TransactionalModule());
}

protected function installReadWriteConnection(): void
Expand Down
Loading

0 comments on commit edf1dec

Please sign in to comment.