mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 15:34:03 +00:00
Add Predis support (#59)
* wip * Add Predis support * Enable phpredis extension only for some builds * Add note about phpredis * Fix if command * Revert travis changes & add a version check to predis tests
This commit is contained in:
parent
e7b5a77a6b
commit
1b6759084f
9 changed files with 75 additions and 18 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
env:
|
env:
|
||||||
- LARAVEL_VERSION="5.7.*" TESTBENCH_VERSION="~3.7"
|
- LARAVEL_VERSION="5.7.*" TESTBENCH_VERSION="~3.7" REDIS_DRIVER=phpredis
|
||||||
- LARAVEL_VERSION="5.8.*" TESTBENCH_VERSION="~3.8"
|
- LARAVEL_VERSION="5.8.*" TESTBENCH_VERSION="~3.8" REDIS_DRIVER=phpredis
|
||||||
|
|
||||||
language: php
|
language: php
|
||||||
php:
|
php:
|
||||||
|
|
@ -14,7 +14,7 @@ before_install:
|
||||||
- echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
- echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- composer require "laravel/framework:$LARAVEL_VERSION" "orchestra/testbench:$TESTBENCH_VERSION"
|
- travis_retry composer require "laravel/framework:$LARAVEL_VERSION" "orchestra/testbench:$TESTBENCH_VERSION"
|
||||||
- travis_retry composer install --no-interaction
|
- travis_retry composer install --no-interaction
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ You won't have to change a thing in your application's code.\*
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
- Laravel 5.7 or 5.8
|
- Laravel 5.7 or 5.8
|
||||||
- phpredis (predis is not supported)
|
|
||||||
|
|
||||||
### Installing the package
|
### Installing the package
|
||||||
|
|
||||||
|
|
@ -99,6 +98,8 @@ config('tenancy.redis.prefix_base') . $uuid
|
||||||
|
|
||||||
These changes will only apply for connections listed in `prefixed_connections`.
|
These changes will only apply for connections listed in `prefixed_connections`.
|
||||||
|
|
||||||
|
> **Note: *If you want Redis to be multi-tenant, you <u>must</u> use phpredis. Predis does not support prefixes.***
|
||||||
|
|
||||||
#### `cache`
|
#### `cache`
|
||||||
|
|
||||||
Cache keys will be tagged with a tag:
|
Cache keys will be tagged with a tag:
|
||||||
|
|
@ -328,7 +329,7 @@ The entire application will use a new database connection. The connection will b
|
||||||
|
|
||||||
Connections listed in the `tenancy.redis.prefixed_connections` config array use a prefix based on the `tenancy.redis.prefix_base` and the tenant UUID.
|
Connections listed in the `tenancy.redis.prefixed_connections` config array use a prefix based on the `tenancy.redis.prefix_base` and the tenant UUID.
|
||||||
|
|
||||||
**Note: You *must* use phpredis. Predis doesn't support prefixes.**
|
**Note: You *must* use phpredis if you want mutli-tenant Redis. Predis doesn't support prefixes.**
|
||||||
|
|
||||||
## Cache
|
## Cache
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"illuminate/support": "5.7.*||5.8.*",
|
"illuminate/support": "5.7.*||5.8.*",
|
||||||
"webpatser/laravel-uuid": "^3.0"
|
"webpatser/laravel-uuid": "^3.0",
|
||||||
|
"predis/predis": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"vlucas/phpdotenv": "^2.2||^3.3",
|
"vlucas/phpdotenv": "^2.2||^3.3",
|
||||||
|
|
|
||||||
8
src/Exceptions/PhpRedisNotInstalledException.php
Normal file
8
src/Exceptions/PhpRedisNotInstalledException.php
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Exceptions;
|
||||||
|
|
||||||
|
class PhpRedisNotInstalledException extends \Exception
|
||||||
|
{
|
||||||
|
protected $message = 'PhpRedis is not installed. PhpRedis is required for Redis multi-tenancy because Predis does not support prefixes.';
|
||||||
|
}
|
||||||
|
|
@ -71,16 +71,21 @@ class RedisStorageDriver implements StorageDriver
|
||||||
return "tenants:{$hash}";
|
return "tenants:{$hash}";
|
||||||
}, $uuids);
|
}, $uuids);
|
||||||
|
|
||||||
// Apparently, the PREFIX is applied to all functions except scan()
|
if (! $hashes) {
|
||||||
$redis_prefix = $this->redis->getOption($this->redis->client()::OPT_PREFIX);
|
// Apparently, the PREFIX is applied to all functions except scan().
|
||||||
$hashes = $hashes ?: $this->redis->scan(null, $redis_prefix.'tenants:*');
|
// Therefore, if the `tenancy` Redis connection has a prefix set
|
||||||
|
// (and PhpRedis is used), prepend the prefix to the search.
|
||||||
return array_map(function ($tenant) use ($redis_prefix) {
|
$redis_prefix = '';
|
||||||
// Left strip $redis_prefix from $tenant
|
if (config('database.redis.client') === 'phpredis') {
|
||||||
if (substr($tenant, 0, strlen($redis_prefix)) == $redis_prefix) {
|
$redis_prefix = $this->redis->getOption($this->redis->client()::OPT_PREFIX);
|
||||||
$tenant = substr($tenant, strlen($redis_prefix));
|
|
||||||
}
|
}
|
||||||
|
$hashes = array_map(function ($hash) use ($redis_prefix) {
|
||||||
|
// Left strip $redis_prefix from $hash
|
||||||
|
return substr($hash, strlen($redis_prefix));
|
||||||
|
}, $this->redis->scan(null, $redis_prefix.'tenants:*'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_map(function ($tenant) {
|
||||||
return $this->redis->hgetall($tenant);
|
return $this->redis->hgetall($tenant);
|
||||||
}, $hashes);
|
}, $hashes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ namespace Stancl\Tenancy\Traits;
|
||||||
use Stancl\Tenancy\CacheManager;
|
use Stancl\Tenancy\CacheManager;
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||||
|
use Stancl\Tenancy\Exceptions\PhpRedisNotInstalledException;
|
||||||
|
|
||||||
trait BootstrapsTenancy
|
trait BootstrapsTenancy
|
||||||
{
|
{
|
||||||
|
|
@ -13,7 +15,9 @@ trait BootstrapsTenancy
|
||||||
public function bootstrap()
|
public function bootstrap()
|
||||||
{
|
{
|
||||||
$this->switchDatabaseConnection();
|
$this->switchDatabaseConnection();
|
||||||
$this->setPhpRedisPrefix($this->app['config']['tenancy.redis.prefixed_connections']);
|
if ($this->app['config']['tenancy.redis.tenancy']) {
|
||||||
|
$this->setPhpRedisPrefix($this->app['config']['tenancy.redis.prefixed_connections']);
|
||||||
|
}
|
||||||
$this->tagCache();
|
$this->tagCache();
|
||||||
$this->suffixFilesystemRootPaths();
|
$this->suffixFilesystemRootPaths();
|
||||||
}
|
}
|
||||||
|
|
@ -28,7 +32,11 @@ trait BootstrapsTenancy
|
||||||
foreach ($connections as $connection) {
|
foreach ($connections as $connection) {
|
||||||
$prefix = $this->app['config']['tenancy.redis.prefix_base'] . $this->tenant['uuid'];
|
$prefix = $this->app['config']['tenancy.redis.prefix_base'] . $this->tenant['uuid'];
|
||||||
$client = Redis::connection($connection)->client();
|
$client = Redis::connection($connection)->client();
|
||||||
$client->setOption($client::OPT_PREFIX, $prefix);
|
try {
|
||||||
|
$client->setOption($client::OPT_PREFIX, $prefix);
|
||||||
|
} catch (\Throwable $t) {
|
||||||
|
throw new PhpRedisNotInstalledException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ return [
|
||||||
'suffix' => '',
|
'suffix' => '',
|
||||||
],
|
],
|
||||||
'redis' => [
|
'redis' => [
|
||||||
|
'tenancy' => false,
|
||||||
'prefix_base' => 'tenant',
|
'prefix_base' => 'tenant',
|
||||||
'prefixed_connections' => [
|
'prefixed_connections' => [
|
||||||
'default',
|
'default',
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
use Stancl\Tenancy\Exceptions\PhpRedisNotInstalledException;
|
||||||
|
|
||||||
class BootstrapsTenancyTest extends TestCase
|
class BootstrapsTenancyTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
@ -30,6 +32,36 @@ class BootstrapsTenancyTest extends TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function predis_is_supported()
|
||||||
|
{
|
||||||
|
if (app()->version() < 'v5.8.27') {
|
||||||
|
$this->markTestSkipped();
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::set('database.redis.client', 'predis');
|
||||||
|
Redis::setDriver('predis');
|
||||||
|
Config::set('tenancy.redis.tenancy', false);
|
||||||
|
|
||||||
|
// assert no exception is thrown from initializing tenancy
|
||||||
|
$this->assertNotNull($this->initTenancy());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function predis_is_not_supported_without_disabling_redis_multitenancy()
|
||||||
|
{
|
||||||
|
if (app()->version() < 'v5.8.27') {
|
||||||
|
$this->markTestSkipped();
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::set('database.redis.client', 'predis');
|
||||||
|
Redis::setDriver('predis');
|
||||||
|
Config::set('tenancy.redis.tenancy', true);
|
||||||
|
|
||||||
|
$this->expectException(PhpRedisNotInstalledException::class);
|
||||||
|
$this->initTenancy();
|
||||||
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function filesystem_is_suffixed()
|
public function filesystem_is_suffixed()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
|
|
||||||
public function initTenancy($domain = 'localhost')
|
public function initTenancy($domain = 'localhost')
|
||||||
{
|
{
|
||||||
tenancy()->init($domain);
|
return tenancy()->init($domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,6 +72,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
'public',
|
'public',
|
||||||
's3',
|
's3',
|
||||||
],
|
],
|
||||||
|
'tenancy.redis.tenancy' => true,
|
||||||
'tenancy.migrations_directory' => database_path('../migrations'),
|
'tenancy.migrations_directory' => database_path('../migrations'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue