-
-
Notifications
You must be signed in to change notification settings - Fork 396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Driver [redis_tenancy] is not supported. #693
Comments
For now I just use my own Illuminate namespace: composer.json
\app\IlluminateOverwrite\Providers\CacheServiceProvider.php
Seems to work for now. |
Use the 5.2 version cache documentation. |
@JGamboa please elaborate on that, any link or documentation? |
@JGamboa can you clarify what you did that solved your issue? We'd love to improve the docs and implementation for everyone. |
@luceos Im using the hyn 5.3, but the documentation of https://laravel-tenancy.com/docs/hyn/5.3/cache doenst work. Instead i used the 5.2 documentation https://laravel-tenancy.com/docs/hyn/5.2/cache and it works like a charm. If u are using spattie you should add spattie to extra dont discover
|
You are right, in most cases it work, but as soon you have a 3rd party app using cache in boot, it will fail. Therefore my explanation above. |
@Nowi5 I think we should stay with the 5.2 documentation is more realistic considering that we all use 3rd party app. |
What about this, without changing provider just change prefix? <?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class CacheServiceProvider extends ServiceProvider
{
public function boot()
{
if (PHP_SAPI === 'cli') {
$uuid = str_slug(env('APP_NAME', 'laravel'), '_').'_cache';
} else {
$fqdn = request()->getHost();
$uuid = \DB::table('hostnames')
->select('websites.uuid')
->join('websites', 'hostnames.website_id', '=', 'websites.id')
->where('fqdn', $fqdn)
->value('uuid');
}
\Cache::setPrefix(str_slug($uuid, '_').'_cache');
}
} Illuminate\Cache\CacheServiceProvider::class,
App\Providers\CacheServiceProvider::class, is there any downsides of this approach? |
I think the manual way of setting provider priority in the config/app.php is still the best way to get it working without the error. |
Here are my thoughts why the current documentation is not working. At least sometimes. Making it extremely hard to find out the the solution. I use Laravel 5.8 and
When any package calls cache for the first time in the app lifecycle, the E.g. public function __construct(Filesystem $files, $directory)
public function __construct(Redis $redis, $prefix = '', $connection = 'default')
public function __construct(ConnectionInterface $connection, $table, $prefix = '') For all (or at least many) auto-discovered packages Anything calling Here we can try to run our And this may work until you try to run telescope debug tool, which must be run as early as possible to catch all possible activity. But telescope instantiates Fortunately So finally to get cache tetant aware we must:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class CacheServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
if (PHP_SAPI === 'cli') {
$namespace = str_slug(env('APP_NAME', 'laravel'), '_').'_cache';
} else {
$fqdn = request()->getHost();
$namespace = \DB::table('hostnames')
->select('websites.uuid')
->join('websites', 'hostnames.website_id', '=', 'websites.id')
->where('fqdn', $fqdn)
->value('uuid');
}
\Cache::setPrefix($namespace);
}
}
/*
* Application Service Providers...
*/
App\Providers\CacheServiceProvider::class,
App\Providers\AppServiceProvider::class, After that cache should become tenant aware. ===== If you are pretty sure you are not going to use anything like Here the steps are different:
Update "extra": {
"laravel": {
"dont-discover": [
"hyn/multi-tenant"
]
}
}, and run
/*
* Application Service Providers...
*/
App\Providers\CacheServiceProvider::class,
Hyn\Tenancy\Providers\TenancyProvider::class,
Hyn\Tenancy\Providers\WebserverProvider::class,
App\Providers\AppServiceProvider::class,
<?php
namespace App\Providers;
use Illuminate\Cache\FileStore;
use Illuminate\Cache\DatabaseStore;
use Illuminate\Support\ServiceProvider;
class CacheServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
$namespace = function($app) {
if (PHP_SAPI === 'cli') {
return $app['config']['cache.default'];
}
$fqdn = request()->getHost();
$uuid = \DB::table('hostnames')
->select('websites.uuid')
->join('websites', 'hostnames.website_id', '=', 'websites.id')
->where('fqdn', $fqdn)
->value('uuid');
return $uuid;
};
$cacheDriver = config('cache.default');
switch ($cacheDriver) {
case 'file':
\Cache::extend($cacheDriver, function ($app) use ($namespace){
$namespace = $namespace($app);
return \Cache::repository(new FileStore(
$app['files'],
$app['config']['cache.stores.file.path'].$namespace
));
});
break;
case 'database':
\Cache::extend($cacheDriver, function ($app) use ($namespace){
$namespace = $namespace($app);
return \Cache::repository(new DatabaseStore(
$app['db.connection'],
'cache',
$namespace
));
});
break;
case 'redis':
// But if not yet instantiated, then we are able to redifine namespace (prefix). Works for Redis only
if (PHP_SAPI === 'cli') {
$namespace = str_slug(env('APP_NAME', 'laravel'), '_').'_cache';
} else {
$fqdn = request()->getHost();
$namespace = \DB::table('hostnames')
->select('websites.uuid')
->join('websites', 'hostnames.website_id', '=', 'websites.id')
->where('fqdn', $fqdn)
->value('uuid');
}
\Cache::setPrefix($namespace);
break;
default:
}
}
} @luceos Please, have look to this post. Maybe it's worth to update the docs. |
@gruz Thanks for your detailed write-up. Thanks to you I managed to get a custom per-tenant file cache working.
There shouldn't be a meaningful difference between auto-discovering Telescope or manually registering it like this. |
I am getting "Call to undefined method Illuminate\Cache\FileStore::setPrefix()" trying to use \Cache::setPrefix($namespace); I added and removed combinations of the below: use Illuminate\Cache\FileStore; ... but still can't access the method. In the api docs for Laravel 5.8 it says "void setPrefix(string $prefix)" for RedisStore https://laravel.com/api/5.8/Illuminate/Cache/RedisStore.html#method_setPrefix I know it probably an easy fix but I can't get it working. Thanks in advance for any suggestions! |
@kinsaz I described it in my long post above. |
I agree I read it but I can't get it working. What do I need to do? |
@kinsaz |
Yes, and I used the code exactly above and I never reference FileStore but I get the error |
@kinsaz |
Thanks for your quick response! I tried config:clear earlier and it didn't work so I did it again along with artisan cache:clear, artisan clear-compiled and composer update and it worked. Now I don't get the above referenced error -so thanks - I really appreciate it! That said, I now get a predis error "Call to a member function createCommand() on null" in the file /vendor/predis/predis/src/Client.php "Call to a member function createCommand() on null" line 323 Sorry to bug you with this but I appreciate your help. |
@kinsaz I didn't meet such an error. You need to debug it at your own. Sorry, cannot help with issue. |
Thanks for your help. If anyone else has any ideas. On the exception trace when I run cache:clear I get the same error as above "Call to a member function createCommand() on null" but the stack trace give a bit more info here: Predis\Client::createCommand("flushdb", []) The second argument ($arguments = array()) is null. from "Call to a member function createCommand() on null" line 323 What would cause this? |
Is |
Hi, I did a nice trick to solve this issue. The above solution not working for me as i have many packages that instantiate the The problem is with this commit: laravel/framework#19646 Which make any Service Provider with namespace starting with Illuminate load first, then auto-discovered service providers, then any other providers added to config/app.php. My solution is:
It should work with any |
For file Cache to work we need to change Cache storage path:
|
Hi @luceos , The problem was obtaining the uuid for the new prefix and cache file path. Since the CacheServiceProvider is added before the providers for Tenancy, the tenant database is not defined yet (but it is set in the configuration file), so an error is given. This was solved by changing the line obtaining the uuid to use specifically the system connection (\DB::connection('system')->): $uuid = \DB::connection('system')->table('hostnames') A small detail, but maybe it will help others as well. Cheers! PS: Btw, the tenant-aware cache is a huge issue, and if not implemented in Tenancy and left to the user to decide, it should be at least mentioned visibly in the installation documentation. Most tenancy websites will have auth (like in my case), and having user permissions messed up between instances is a nasty security breach (and a pain to debug if not knowing what to look for). |
I'm using another multi-tenant library and your answer was useful to me. Using version 11 of laravel I was able to create a CacheServiceProvider and do what you said. I just summarized the code by removing the switch and leaving what I would use (file), it worked perfectly. Thank you very much! |
Hi,
related to Make cache handling better for tenants #309 I get the issue of getting the error Driver [redis_tenancy] is not supported.
Currently I setup my own CI/CD process with local docker (base on php:7.1.8-apache), gitlab and production server. This seems to be related to some autogenerated loading of composer or so as it seems nearly to be random when it works and when not.
Composer:
config/app
config/cache.php
CacheServiceProvider:
Any idea what is going wrong here? I think the boot of CacheServiceProvider is not loaded early enough, but how to change this?
While writing this, I located this: https://stackoverflow.com/a/53263914/1597218
The order in the config/app is not used as expected. In my case the order is the following:
"According to the Application::registerConfiguredProviders it's hardcoded to have everything that starts with 'Illuminate' to go to the starting chunk, all others to the end, and Composer Packages go in the middle. "
Even so I add all missing 3rd Party provider into the app/config manually, the Application::registerConfiguredProviders list the providers twice.
So one option would be that this package add this provider to the default settings, as vendor files are loaded before app providers or alternativly adding a customIlluminate namespace.
The text was updated successfully, but these errors were encountered: