Skip to content

Commit

Permalink
Improving eventDispatcher findListener call and settings repo
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelfolaron committed Nov 26, 2024
1 parent 177d514 commit ee79913
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 22 deletions.
58 changes: 42 additions & 16 deletions app/Core/Events/EventDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class EventDispatcher implements Dispatcher
use Macroable;
use ReflectsClosures;

/**
* Cache for pattern matching results
*/
private static array $patternMatchCache = [];

/**
* Registry of all events added to a hook
*/
Expand Down Expand Up @@ -115,34 +120,55 @@ public function dispatch(
*/
public static function findEventListeners(string $eventName, array $registry): array
{
// Check cache first
$cacheKey = $eventName . '_' . md5(serialize(array_keys($registry)));
if (isset(self::$patternMatchCache[$cacheKey])) {
return self::$patternMatchCache[$cacheKey];
}

$matches = [];
$patterns = [];

foreach ($registry as $key => $value) {
preg_match_all('/\{RGX:(.*?):RGX\}/', $key, $regexMatches);

$key = strtr($key, [
...collect($regexMatches[0] ?? [])->mapWithKeys(fn ($match, $i) => [$match => "REGEX_MATCH_$i"])->toArray(),
'*' => 'RANDOM_STRING',
'?' => 'RANDOM_CHARACTER',
]);

// escape the non regex characters
$pattern = preg_quote($key, '/');

$pattern = strtr($pattern, [
'RANDOM_STRING' => '.*?', // 0 or more (lazy) - asterisk (*)
'RANDOM_CHARACTER' => '.', // 1 character - question mark (?)
...collect($regexMatches[1] ?? [])->mapWithKeys(fn ($match, $i) => ["REGEX_MATCH_$i" => $match])->toArray(),
]);
// Skip if we've already compiled this pattern
if (!isset($patterns[$key])) {
preg_match_all('/\{RGX:(.*?):RGX\}/', $key, $regexMatches);
$pattern = self::compilePattern($key, $regexMatches);
$patterns[$key] = $pattern;
} else {
$pattern = $patterns[$key];
}

if (preg_match("/^$pattern$/", $eventName)) {
$matches = array_merge($matches, $value);
}
}

// Cache the result
self::$patternMatchCache[$cacheKey] = $matches;
return $matches;
}

/**
* Compiles a pattern for matching
*/
private static function compilePattern(string $key, array $regexMatches): string
{
$key = strtr($key, [
...collect($regexMatches[0] ?? [])->mapWithKeys(fn ($match, $i) => [$match => "REGEX_MATCH_$i"])->toArray(),
'*' => 'RANDOM_STRING',
'?' => 'RANDOM_CHARACTER',
]);

$pattern = preg_quote($key, '/');

return strtr($pattern, [
'RANDOM_STRING' => '.*?',
'RANDOM_CHARACTER' => '.',
...collect($regexMatches[1] ?? [])->mapWithKeys(fn ($match, $i) => ["REGEX_MATCH_$i" => $match])->toArray(),
]);
}

/**
* Dispatches a filter to manipulate a variable somewhere
*
Expand Down
33 changes: 27 additions & 6 deletions app/Domain/Setting/Repositories/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

use Exception;
use Leantime\Core\Db\Db as DbCore;
use Leantime\Domain\Setting\Services\SettingCache;
use PDO;

class Setting
{
private DbCore $db;
private SettingCache $cache;

public array $applications = [
'general' => 'General',
Expand All @@ -17,9 +19,10 @@ class Setting
/**
* __construct - neu db connection
*/
public function __construct(DbCore $db)
public function __construct(DbCore $db, SettingCache $cache)
{
$this->db = $db;
$this->cache = $cache;
}

/**
Expand All @@ -31,10 +34,16 @@ public function getSetting($type): mixed
return false;
}

// Check cache first
$cachedValue = $this->cache->get($type);
if ($cachedValue !== null) {
return $cachedValue;
}

$sql = 'SELECT
value
FROM zp_settings WHERE `key` = :key
LIMIT 1';
value
FROM zp_settings WHERE `key` = :key
LIMIT 1';

$stmn = $this->db->database->prepare($sql);
$stmn->bindvalue(':key', $type, PDO::PARAM_STR);
Expand All @@ -50,9 +59,15 @@ public function getSetting($type): mixed
}

if ($values !== false && isset($values['value'])) {
// Store in cache for future requests
$this->cache->set($type, $values['value']);

return $values['value'];
}

//value is not in the db, which is fine. Let's cache that too
$this->cache->set($type, false);

//TODO: This needs to return null or throw an exception if the setting doesn't exist.
return false;
}
Expand All @@ -65,8 +80,8 @@ public function saveSetting($type, $value): bool
}

$sql = 'INSERT INTO zp_settings (`key`, `value`)
VALUES (:key, :value) ON DUPLICATE KEY UPDATE
`value` = :valueUpdate';
VALUES (:key, :value) ON DUPLICATE KEY UPDATE
`value` = :valueUpdate';

$stmn = $this->db->database->prepare($sql);
$stmn->bindvalue(':key', $type, PDO::PARAM_STR);
Expand All @@ -76,6 +91,9 @@ public function saveSetting($type, $value): bool
$return = $stmn->execute();
$stmn->closeCursor();

// Update cache
$this->cache->set($type, $value);

return $return;
}

Expand All @@ -89,6 +107,9 @@ public function deleteSetting($type): void

$stmn->execute();
$stmn->closeCursor();

// Remove from cache
$this->cache->forget($type);
}

/**
Expand Down
43 changes: 43 additions & 0 deletions app/Domain/Setting/Services/SettingCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Leantime\Domain\Setting\Services;

use Illuminate\Support\Facades\Cache;

class SettingCache
{
private const CACHE_KEY_PREFIX = 'setting:';
private const CACHE_TTL = 3600; // 1 hour

/**
* Get setting from cache
*/
public function get(string $key): mixed
{
return Cache::get(self::CACHE_KEY_PREFIX . $key);
}

/**
* Store setting in cache
*/
public function set(string $key, mixed $value): void
{
Cache::put(self::CACHE_KEY_PREFIX . $key, $value, self::CACHE_TTL);
}

/**
* Remove setting from cache
*/
public function forget(string $key): void
{
Cache::forget(self::CACHE_KEY_PREFIX . $key);
}

/**
* Clear all settings from cache
*/
public function flush(): void
{
Cache::tags(['settings'])->flush();
}
}

0 comments on commit ee79913

Please sign in to comment.