Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2b8f6a2
refactor: update logging path and clean up log storage structure
barbosa89 Nov 18, 2025
242235d
feat: caching system
barbosa89 Nov 25, 2025
127200b
feat: add TestNumber class for testing Number column functionality
barbosa89 Nov 25, 2025
016f370
test: enhance file creation and modification time checks
barbosa89 Nov 25, 2025
d7ac7b9
test: increase delay for task completion in ParallelQueueTest
barbosa89 Nov 25, 2025
6e03e87
feat: implement CacheStore abstract class and update store classes to…
barbosa89 Nov 25, 2025
9eeb9fa
chore: add missing function imports in ConnectionFactory and RedisQueue
barbosa89 Nov 25, 2025
fb49431
feat: refactor Redis client integration by introducing ClientWrapper …
barbosa89 Nov 26, 2025
db6aa99
refactor: replace usleep with delay in cache store tests for improved…
barbosa89 Nov 26, 2025
20372ab
feat: add tests for cache expiration and clearing functionality
barbosa89 Nov 26, 2025
b202d2f
refactor: remove duplicate remember and rememberForever methods from …
barbosa89 Nov 26, 2025
b1179f9
refactor: simplify clear method in FileStore by removing unnecessary …
barbosa89 Nov 26, 2025
51a0678
feat: add tests for handling expired cache and corrupted cache files
barbosa89 Nov 26, 2025
fcc5a0a
refactor: update corrupted cache file handling to use a hashed filename
barbosa89 Nov 26, 2025
ffb0cf7
style: php cs
barbosa89 Nov 26, 2025
e2c2e24
feat: implement ConnectionManager and UnknownConnection exception, up…
barbosa89 Nov 26, 2025
23dd983
feat: add test for magic __call method in ClientWrapper to delegate r…
barbosa89 Nov 26, 2025
9e8cbce
feat: streamline command registration in App setup method
barbosa89 Nov 27, 2025
2e7a717
feat: ensure unique command registration in Phenix class
barbosa89 Nov 27, 2025
c388535
test: increase delay in ParallelQueue tests for better processing val…
barbosa89 Nov 27, 2025
406b731
fix: adjust cache clearing logic in tearDown method for file store
barbosa89 Nov 27, 2025
39c89fc
feat: add client method to Redis facade and test for ClientWrapper in…
barbosa89 Nov 27, 2025
183f59e
refactor: replace ClientWrapper instantiation with Redis facade in Ca…
barbosa89 Nov 27, 2025
ec915f9
test: increase delay in ParallelQueue test for improved task completi…
barbosa89 Nov 27, 2025
3bbb05e
refactor: rename class to prevent name collision
barbosa89 Nov 27, 2025
f695ae8
fix: update .gitignore files to exclude data directories in cache and…
barbosa89 Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ Thumbs.db
.phpunit.result.cache
.php-cs-fixer.cache
build
tests/fixtures/application/storage/framework/logs/*.log
tests/fixtures/application/storage/framework/views/*.php
.env
4 changes: 2 additions & 2 deletions src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public function setup(): void

$this->host = $this->getHost();

self::$container->add(Phenix::class)->addMethodCall('registerCommands');

/** @var array $providers */
$providers = Config::get('app.providers', []);

Expand All @@ -71,8 +73,6 @@ public function setup(): void

$this->logger = LoggerFactory::make($channel);

self::$container->add(Phenix::class)->addMethodCall('registerCommands');

$this->register(Log::class, new Log($this->logger));
}

Expand Down
120 changes: 120 additions & 0 deletions src/Cache/CacheManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache;

use Amp\Cache\LocalCache;
use Closure;
use Phenix\Cache\Constants\Store;
use Phenix\Cache\Contracts\CacheStore;
use Phenix\Cache\Stores\FileStore;
use Phenix\Cache\Stores\LocalStore;
use Phenix\Cache\Stores\RedisStore;
use Phenix\Facades\Redis;
use Phenix\Util\Date;

class CacheManager
{
protected array $stores = [];

protected Config $config;

public function __construct(Config|null $config = null)
{
$this->config = $config ?? new Config();
}

public function store(Store|null $storeName = null): CacheStore
{
$storeName ??= $this->resolveStoreName($storeName);

return $this->stores[$storeName->value] ??= $this->resolveStore($storeName);
}

public function get(string $key, Closure|null $callback = null): mixed
{
return $this->store()->get($key, $callback);
}

public function set(string $key, mixed $value, Date|null $ttl = null): void
{
$this->store()->set($key, $value, $ttl);
}

public function forever(string $key, mixed $value): void
{
$this->store()->forever($key, $value);
}

public function remember(string $key, Date $ttl, Closure $callback): mixed
{
return $this->store()->remember($key, $ttl, $callback);
}

public function rememberForever(string $key, Closure $callback): mixed
{
return $this->store()->rememberForever($key, $callback);
}

public function has(string $key): bool
{
return $this->store()->has($key);
}

public function delete(string $key): void
{
$this->store()->delete($key);
}

public function clear(): void
{
$this->store()->clear();
}

protected function resolveStoreName(Store|null $storeName = null): Store
{
return $storeName ?? Store::from($this->config->default());
}

protected function resolveStore(Store $storeName): CacheStore
{
return match ($storeName) {
Store::LOCAL => $this->createLocalStore(),
Store::FILE => $this->createFileStore(),
Store::REDIS => $this->createRedisStore(),
};
}

protected function createLocalStore(): CacheStore
{
$storeConfig = $this->config->getStore(Store::LOCAL->value);

$cache = new LocalCache($storeConfig['size_limit'] ?? null, $storeConfig['gc_interval'] ?? 5);

$defaultTtl = (int) ($storeConfig['ttl'] ?? $this->config->defaultTtlMinutes());

return new LocalStore($cache, $defaultTtl);
}

protected function createFileStore(): CacheStore
{
$storeConfig = $this->config->getStore(Store::FILE->value);

$path = $storeConfig['path'] ?? base_path('storage' . DIRECTORY_SEPARATOR . 'cache');

$defaultTtl = (int) ($storeConfig['ttl'] ?? $this->config->defaultTtlMinutes());

return new FileStore($path, $this->config->prefix(), $defaultTtl);
}

protected function createRedisStore(): CacheStore
{
$storeConfig = $this->config->getStore(Store::REDIS->value);
$defaultTtl = $storeConfig['ttl'] ?? $this->config->defaultTtlMinutes();

$client = Redis::connection($this->config->getConnection())->client();

return new RedisStore($client, $this->config->prefix(), (int) $defaultTtl);
}
}
33 changes: 33 additions & 0 deletions src/Cache/CacheServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache;

use Phenix\Cache\Console\CacheClear;
use Phenix\Providers\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
public function provides(string $id): bool
{
$this->provided = [
CacheManager::class,
];

return $this->isProvided($id);
}

public function register(): void
{
$this->bind(CacheManager::class)
->setShared(true);
}

public function boot(): void
{
$this->commands([
CacheClear::class,
]);
}
}
42 changes: 42 additions & 0 deletions src/Cache/CacheStore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache;

use Closure;
use Phenix\Cache\Contracts\CacheStore as CacheStoreContract;
use Phenix\Util\Date;

abstract class CacheStore implements CacheStoreContract
{
public function remember(string $key, Date $ttl, Closure $callback): mixed
{
$value = $this->get($key);

if ($value !== null) {
return $value;
}

$value = $callback();

$this->set($key, $value, $ttl);

return $value;
}

public function rememberForever(string $key, Closure $callback): mixed
{
$value = $this->get($key);

if ($value !== null) {
return $value;
}

$value = $callback();

$this->forever($key, $value);

return $value;
}
}
45 changes: 45 additions & 0 deletions src/Cache/Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache;

use Phenix\Cache\Constants\Store;
use Phenix\Facades\Config as Configuration;

class Config
{
private array $config;

public function __construct()
{
$this->config = Configuration::get('cache', []);
}

public function default(): string
{
return $this->config['default'] ?? Store::LOCAL->value;
}

public function getStore(string|null $storeName = null): array
{
$storeName ??= $this->default();

return $this->config['stores'][$storeName] ?? [];
}

public function getConnection(): string
{
return $this->getStore()['connection'] ?? 'default';
}

public function prefix(): string
{
return $this->config['prefix'] ?? '';
}

public function defaultTtlMinutes(): int
{
return (int) ($this->config['ttl'] ?? 60);
}
}
41 changes: 41 additions & 0 deletions src/Cache/Console/CacheClear.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache\Console;

use Phenix\Facades\Cache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class CacheClear extends Command
{
/**
* @var string
*
* @phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint
*/
protected static $defaultName = 'cache:clear';

/**
* @var string
*
* @phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint
*/
protected static $defaultDescription = 'Clear cached data in default cache store';

protected function configure(): void
{
$this->setHelp('This command allows you to clear cached data in the default cache store.');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
Cache::clear();

$output->writeln('<info>Cached data cleared successfully!</info>');

return Command::SUCCESS;
}
}
14 changes: 14 additions & 0 deletions src/Cache/Constants/Store.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache\Constants;

enum Store: string
{
case LOCAL = 'local';

case FILE = 'file';

case REDIS = 'redis';
}
27 changes: 27 additions & 0 deletions src/Cache/Contracts/CacheStore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Phenix\Cache\Contracts;

use Closure;
use Phenix\Util\Date;

interface CacheStore
{
public function get(string $key, Closure|null $callback = null): mixed;

public function set(string $key, mixed $value, Date|null $ttl = null): void;

public function forever(string $key, mixed $value): void;

public function remember(string $key, Date $ttl, Closure $callback): mixed;

public function rememberForever(string $key, Closure $callback): mixed;

public function has(string $key): bool;

public function delete(string $key): void;

public function clear(): void;
}
Loading