From beccd6c1ec6f17f0bb1767329c7971774ab54019 Mon Sep 17 00:00:00 2001 From: Marcel Folaron Date: Mon, 18 Nov 2024 09:26:47 -0500 Subject: [PATCH] Fixing cache pre-fix issues when using redis cluster --- app/Core/Configuration/laravelConfig.php | 51 +++++---- app/Core/Db/Db.php | 3 +- app/Core/Http/HttpKernel.php | 2 +- app/Core/Middleware/LoadPlugins.php | 14 +-- app/Core/Middleware/StartSession.php | 2 + app/Core/Providers/Cache.php | 7 +- app/Core/Providers/Logging.php | 1 + app/Core/Providers/Redis.php | 41 ++++--- app/Domain/Auth/Templates/userInvite.tpl.php | 111 ------------------- app/Domain/Help/Composers/Helpermodal.php | 1 + app/Domain/Ideas/Repositories/Ideas.php | 4 + app/Domain/Plugins/Services/Registration.php | 8 +- app/helpers.php | 73 ++++++++++++ 13 files changed, 153 insertions(+), 165 deletions(-) diff --git a/app/Core/Configuration/laravelConfig.php b/app/Core/Configuration/laravelConfig.php index 3cc9d12974..232642d6e0 100644 --- a/app/Core/Configuration/laravelConfig.php +++ b/app/Core/Configuration/laravelConfig.php @@ -134,7 +134,6 @@ | specified when running a cache operation inside the application. | */ - 'default' => 'installation', /* @@ -179,7 +178,7 @@ | that reason, you may prefix every cache key to avoid collisions. | */ - 'prefix' => 'leantime_cache_', + 'prefix' => '', ], 'session' => [ @@ -395,23 +394,6 @@ 'compiled' => realpath(storage_path('framework/views')), ], - 'redis' => [ - 'client' => 'phpredis', - 'options' => [ - 'cluster' => 'redis', - 'context' => [], - 'compression' => 3, // Redis::COMPRESSION_LZ4 - ], - 'default' => [ - 'url' => env('LEAN_REDIS_URL', ''), - 'scheme' => env('LEAN_REDIS_SCHEME', 'tls'), - 'host' => env('LEAN_REDIS_HOST', '127.0.0.1'), - 'password' => env('LEAN_REDIS_PASSWORD', null), - 'port' => env('LEAN_REDIS_PORT', '127.0.0.1'), - 'database' => '0', - 'prefix' => 'leantime_cache', - ], - ], 'database' => [ 'default' => env('LEAN_DB_DEFAULT_CONNECTION', 'mysql'), /* @@ -460,5 +442,36 @@ ]) : [], ], ], + + + ], + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as Memcached. You may define your connection settings here. + | + */ + 'redis' => [ + 'client' => 'phpredis', + 'options' => [ + 'cluster' => 'redis', + 'context' => [], + 'compression' => 3, // Redis::COMPRESSION_LZ4 + ], + 'default' => [ + 'url' => env('LEAN_REDIS_URL', ''), + 'scheme' => env('LEAN_REDIS_SCHEME', 'tls'), + 'host' => env('LEAN_REDIS_HOST', '127.0.0.1'), + 'password' => env('LEAN_REDIS_PASSWORD', null), + 'port' => env('LEAN_REDIS_PORT', '127.0.0.1'), + 'database' => '0', + ], ], + + ]; diff --git a/app/Core/Db/Db.php b/app/Core/Db/Db.php index 9140112510..91a1196cde 100644 --- a/app/Core/Db/Db.php +++ b/app/Core/Db/Db.php @@ -72,7 +72,8 @@ public function __construct($connection = 'mysql') Log::error("Can't connect to database"); Log::error($e); - exit('Cannot connect to database'); + throw new \Exception($e); + } } diff --git a/app/Core/Http/HttpKernel.php b/app/Core/Http/HttpKernel.php index afe6168a8b..839a536e47 100644 --- a/app/Core/Http/HttpKernel.php +++ b/app/Core/Http/HttpKernel.php @@ -32,7 +32,6 @@ class HttpKernel extends Kernel protected $middleware = [ // \App\Http\Middleware\TrustHosts::class, \Leantime\Core\Middleware\TrustProxies::class, - \Leantime\Core\Middleware\SetCacheHeaders::class, \Leantime\Core\Middleware\InitialHeaders::class, \Leantime\Core\Middleware\StartSession::class, \Leantime\Core\Middleware\Installed::class, @@ -44,6 +43,7 @@ class HttpKernel extends Kernel \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \Leantime\Core\Middleware\Auth::class, \Leantime\Core\Middleware\ApiAuth::class, + \Leantime\Core\Middleware\SetCacheHeaders::class, \Leantime\Core\Middleware\Localization::class, \Leantime\Core\Middleware\CurrentProject::class, \Leantime\Core\Middleware\LoadPlugins::class, diff --git a/app/Core/Middleware/LoadPlugins.php b/app/Core/Middleware/LoadPlugins.php index b42b3531de..2f2568daa8 100644 --- a/app/Core/Middleware/LoadPlugins.php +++ b/app/Core/Middleware/LoadPlugins.php @@ -26,18 +26,10 @@ public function handle($request, Closure $next): Response self::dispatchEvent('pluginsStart', ['request' => $request]); - $this->pluginMiddleware = self::dispatchFilter('pluginMiddlware', $this->pluginMiddleware, ['request' => $request]); + //Good event to use for all kinds of plugin events that should run early on like adding language files + self::dispatchEvent('pluginsEvents', ['request' => $request], 'leantime.core.middleware.loadplugins.handle'); - $response = app()->make(Pipeline::class) - ->send($request) - ->through(app()->shouldSkipMiddleware() ? [] : $this->pluginMiddleware) - ->then(function ($request) use ($next) { - - //Good event to use for all kinds of plugin events that should run early on like adding language files - self::dispatchEvent('pluginsEvents', ['request' => $request], 'leantime.core.middleware.loadplugins.handle'); - - return $next($request); - }); + $response = $next($request); self::dispatchEvent('pluginsTermintate', ['request' => $request, 'response' => $response]); diff --git a/app/Core/Middleware/StartSession.php b/app/Core/Middleware/StartSession.php index 38ee08e142..ddf2186fe8 100644 --- a/app/Core/Middleware/StartSession.php +++ b/app/Core/Middleware/StartSession.php @@ -120,6 +120,8 @@ protected function handleStatefulRequest(IncomingRequest $request, $session, Clo $this->startSession($request, $session) ); + self::dispatchEvent('session_started'); + $this->collectGarbage($session); //Going deeper down the rabbit hole and executing the rest of the middleware and stack. diff --git a/app/Core/Providers/Cache.php b/app/Core/Providers/Cache.php index 31a96f33d8..21dfe3f449 100644 --- a/app/Core/Providers/Cache.php +++ b/app/Core/Providers/Cache.php @@ -31,23 +31,22 @@ public function register() //If redis is set up let's use redis as cache if ($app['config']['useRedis']) { + $app['config']->set('cache.prefix', ''); + //Default driver just in case it is being asked for $app['config']->set('cache.stores.redis.driver', 'redis'); $app['config']->set('cache.stores.redis.connection', 'cache'); - $app['config']->set('cache.stores.redis.prefix', 'leantime_cache'); //Only needed when using sessions with redis $app['config']->set('cache.stores.sessions.driver', 'redis'); $app['config']->set('cache.stores.sessions.connection', 'sessions'); - $app['config']->set('cache.stores.sessions.prefix', 'leantime_sessions'); $app['config']->set('cache.stores.installation.driver', 'redis'); $app['config']->set('cache.stores.installation.connection', 'installation'); - $app['config']->set('cache.stores.installation.prefix', 'leantime_cache:installation'); $app['config']->set('cache.stores.'.$domainCacheName.'.driver', 'redis'); $app['config']->set('cache.stores.'.$domainCacheName.'.connection', 'cache'); - $app['config']->set('cache.stores.'.$domainCacheName.'.prefix', 'leantime_cache:'.$domainCacheName.''); + $app['config']->set('cache.stores.'.$domainCacheName.'.prefix', ''.$domainCacheName.''); } diff --git a/app/Core/Providers/Logging.php b/app/Core/Providers/Logging.php index 073cd589ad..4938483021 100644 --- a/app/Core/Providers/Logging.php +++ b/app/Core/Providers/Logging.php @@ -2,6 +2,7 @@ namespace Leantime\Core\Providers; +use Illuminate\Container\Container; use Illuminate\Log; use Illuminate\Support\ServiceProvider; diff --git a/app/Core/Providers/Redis.php b/app/Core/Providers/Redis.php index 95eff96214..311eaa14fe 100644 --- a/app/Core/Providers/Redis.php +++ b/app/Core/Providers/Redis.php @@ -22,30 +22,44 @@ public function register() */ $this->app->singleton('redis', function ($app) { + //Setting up three different redis stores + //We are using a slightlyt diffewrent config structure and keep redis at the root level of our config + $cacheConfig = $app['config']['redis']['default']; - $cacheConfig['prefix'] = 'leantime_cache'; + $cacheConfig['prefix'] = 'leantime_cache:'; $installationConfig = $app['config']['redis']['default']; - $installationConfig['prefix'] = 'leantime_cache:installation'; + $installationConfig['prefix'] = 'leantime_cache:installation:'; $sessionsConfig = $app['config']['redis']['default']; - $sessionsConfig['prefix'] = 'leantime_sessions'; + $sessionsConfig['prefix'] = 'leantime_sessions:'; + //Prepare available redis connections + //These connections (cache, installation, sessions) can be used for sessions and cache if ($app['config']->useCluster) { - $app['config']['redis']['clusters'] = [ - 'cache' => [$cacheConfig], - 'installation' => [$installationConfig], - 'sessions' => [$sessionsConfig], - ]; + //Cluster configs and prefix management works differently than regular connections + $options = $app['config']['redis']['options']; + + //The default config is not needed anymore and shouldn't be used since the connection is a cluster + //connection and won't work in the standard config setup + $app['config']->set('redis.default', null); + $app['config']->set('redis.cluster', true); + + $app['config']->set('redis.clusters.cache', array_merge(['options' => $options], [$cacheConfig])); + $app['config']->set('redis.clusters.cache.options.prefix', $cacheConfig['prefix']); + + $app['config']->set('redis.clusters.installation', array_merge(['options' => $options], [$installationConfig])); + $app['config']->set('redis.clusters.installation.options.prefix', $installationConfig['prefix']); + + $app['config']->set('redis.clusters.sessions', array_merge(['options' => $options], [$sessionsConfig])); + $app['config']->set('redis.clusters.sessions.options.prefix', $sessionsConfig['prefix']); } else { - $app['config']['redis'] = [ - 'cache' => $cacheConfig, - 'installation' => $installationConfig, - 'sessions' => $sessionsConfig, - ]; + $app['config']->set('redis.cache', $cacheConfig); + $app['config']->set('redis.installation', $installationConfig); + $app['config']->set('redis.sessions', $sessionsConfig); } @@ -58,7 +72,6 @@ public function register() $this->app->bind('redis.connection', function ($app) { return $app['redis']->connection(); }); - } public function provides() diff --git a/app/Domain/Auth/Templates/userInvite.tpl.php b/app/Domain/Auth/Templates/userInvite.tpl.php index 242bd987a1..e69de29bb2 100644 --- a/app/Domain/Auth/Templates/userInvite.tpl.php +++ b/app/Domain/Auth/Templates/userInvite.tpl.php @@ -1,111 +0,0 @@ - $val) { - $$var = $val; // necessary for blade refactor -} -$user = $tpl->get('user'); -?> -
- -
-


- - -

language->__('headlines.set_up_your_account'); ?>

- -dispatchTplEvent('afterPageHeaderClose'); ?> -
- dispatchTplEvent('afterRegcontentOpen'); ?> - -
- dispatchTplEvent('afterFormOpen'); ?> - - displayInlineNotification(); ?> - - - -
- - -
-
- -
-
- -
-
- - -
-
- -
- __('label.passwordRequirements') ?>

-
- - dispatchTplEvent('beforeSubmitButton'); ?> - - -
- dispatchTplEvent('beforeFormClose'); ?> -
- dispatchTplEvent('beforeRegcontentClose'); ?> -
- - diff --git a/app/Domain/Help/Composers/Helpermodal.php b/app/Domain/Help/Composers/Helpermodal.php index 0a5a1c9b5e..c21273463f 100644 --- a/app/Domain/Help/Composers/Helpermodal.php +++ b/app/Domain/Help/Composers/Helpermodal.php @@ -38,6 +38,7 @@ public function with(): array $currentModal = $this->helperService->getHelperModalByRoute($action); + if ( $completedOnboarding == '1' && $currentModal !== 'notfound' diff --git a/app/Domain/Ideas/Repositories/Ideas.php b/app/Domain/Ideas/Repositories/Ideas.php index e0edf0c8b8..839b3711b0 100644 --- a/app/Domain/Ideas/Repositories/Ideas.php +++ b/app/Domain/Ideas/Repositories/Ideas.php @@ -239,6 +239,10 @@ public function editCanvasItem($values): void public function patchCanvasItem($id, $params): bool { + if (isset($params['act'])) { + unset($params['act']); + } + $sql = 'UPDATE zp_canvas_items SET '; foreach ($params as $key => $value) { diff --git a/app/Domain/Plugins/Services/Registration.php b/app/Domain/Plugins/Services/Registration.php index 138e575109..aaaf4d8ddd 100644 --- a/app/Domain/Plugins/Services/Registration.php +++ b/app/Domain/Plugins/Services/Registration.php @@ -58,12 +58,12 @@ public function registerLanguageFiles(array $languages) $languageArray += parse_ini_file(app_path().'/Plugins/'.$pluginId.'/Language/en-US.ini', true); } - if ((($language = session('usersettings.language') ?? $config->language) !== 'en-US') && in_array($language, $languages)) { + if ((($userLanguage = session('usersettings.language') ?? $config->language) !== 'en-US') && in_array($userLanguage, $languages)) { - if (! Cache::store('installation')->has($pluginId.'.language.'.$language)) { + if (! Cache::store('installation')->has($pluginId.'.language.'.$userLanguage)) { Cache::store('installation')->put( - $pluginId.'.language.'.$language, - parse_ini_file(app_path().'/Plugins/'.$pluginId.'/Language/'.$language.'.ini', true), + $pluginId.'.language.'.$userLanguage, + parse_ini_file(app_path().'/Plugins/'.$pluginId.'/Language/'.$userLanguage.'.ini', true), Carbon::now()->addDays(30) ); } diff --git a/app/helpers.php b/app/helpers.php index 2ccfc71a55..d8180be081 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -230,3 +230,76 @@ function mix(string $path = '', string $manifestDirectory = ''): \Leantime\Core\ return $mix($path, $manifestDirectory); } } + +if (! function_exists('base_path')) { + /** + * Get the path to the base of the install. + * + * @param string $path + * @return string + */ + function base_path($path = '') + { + return app()->basePath($path); + } +} + +if (! function_exists('redirect')) { + /** + * Get an instance of the redirector. + * + * @param string|null $url + * @param int $status + * @param array $headers + * @param bool|null $secure + * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse + */ + function redirect($url = null, $http_response_code = 302, $headers = [], $secure = null) + { + return new RedirectResponse( + trim(preg_replace('/\s\s+/', '', strip_tags($url))), + $http_response_code + ); + } +} + +if (! function_exists('currentRoute')) { + /** + * Get an instance of the redirector. + * + * @param string|null $to + * @param int $status + * @param array $headers + * @param bool|null $secure + */ + + function currentRoute() + { + + return app('request')->getCurrentRoute(); + + } +} + +if (! function_exists('get_domain_key')) { + + /** + * Gets a unique instance key determined by domain + * + */ + function get_domain_key() + { + + //Now that we know where the instance is bing called from + //Let's add a domain level cache. + $domainCacheName = 'localhost'; + if (! app()->runningInConsole()) { + $domainCacheName = md5(\Illuminate\Support\Str::slug(app('request')->host().app('request')['key'])); + } + + return $domainCacheName; + + } + +} +