mirror of
https://github.com/torrentpier/torrentpier
synced 2025-08-22 06:13:58 -07:00
refactor(cache): centralize storage creation and eliminate redundancy
- Remove redundant initializeStorage() from CacheManager - Update CacheManager to receive pre-built Storage instances - Centralize all storage creation logic in UnifiedCacheSystem - Remove unused properties and fix method signatures - Update documentation to reflect simplified architecture No breaking changes - all public APIs unchanged.
This commit is contained in:
parent
00b0f2ffa2
commit
6f6753f6a1
5 changed files with 157 additions and 124 deletions
|
@ -53,11 +53,14 @@ $bb_cfg['db_alias'] = [
|
|||
];
|
||||
|
||||
// Cache
|
||||
// Future enhancement: implement Redis/Memcached storage for Nette
|
||||
$bb_cfg['cache'] = [
|
||||
'db_dir' => realpath(BB_ROOT) . '/internal_data/cache/filecache/',
|
||||
'prefix' => 'tp_',
|
||||
// Available cache types: file, sqlite, memory (file by default)
|
||||
'memcached' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 11211,
|
||||
],
|
||||
// Available cache types: file, sqlite, memory, memcached (file by default)
|
||||
'engines' => [
|
||||
'bb_cache' => ['file'],
|
||||
'bb_config' => ['file'],
|
||||
|
@ -71,7 +74,7 @@ $bb_cfg['cache'] = [
|
|||
];
|
||||
|
||||
// Datastore
|
||||
// Available datastore types: file, sqlite, memory (file by default)
|
||||
// Available datastore types: file, sqlite, memory, memcache (file by default)
|
||||
$bb_cfg['datastore_type'] = 'file';
|
||||
|
||||
// Server
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace TorrentPier\Cache;
|
|||
use Nette\Caching\Cache;
|
||||
use Nette\Caching\Storage;
|
||||
use Nette\Caching\Storages\FileStorage;
|
||||
use Nette\Caching\Storages\MemcachedStorage;
|
||||
use Nette\Caching\Storages\MemoryStorage;
|
||||
use Nette\Caching\Storages\SQLiteStorage;
|
||||
use TorrentPier\Dev;
|
||||
|
@ -42,18 +43,6 @@ class CacheManager
|
|||
*/
|
||||
private Storage $storage;
|
||||
|
||||
/**
|
||||
* Cache configuration
|
||||
* @var array
|
||||
*/
|
||||
private array $config;
|
||||
|
||||
/**
|
||||
* Cache namespace/name
|
||||
* @var string
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
/**
|
||||
* Cache prefix
|
||||
* @var string
|
||||
|
@ -89,16 +78,14 @@ class CacheManager
|
|||
* Constructor
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param Storage $storage Pre-built storage instance from UnifiedCacheSystem
|
||||
* @param array $config
|
||||
*/
|
||||
private function __construct(string $namespace, array $config)
|
||||
private function __construct(string $namespace, Storage $storage, array $config)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->config = $config;
|
||||
$this->storage = $storage;
|
||||
$this->prefix = $config['prefix'] ?? 'tp_';
|
||||
|
||||
// Initialize storage based on configuration
|
||||
$this->initializeStorage();
|
||||
$this->engine = $config['engine'] ?? 'Unknown';
|
||||
|
||||
// Create Nette Cache instance with namespace
|
||||
$this->cache = new Cache($this->storage, $namespace);
|
||||
|
@ -108,56 +95,24 @@ class CacheManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Get singleton instance
|
||||
* Get singleton instance (called by UnifiedCacheSystem)
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param Storage $storage Pre-built storage instance
|
||||
* @param array $config
|
||||
* @return self
|
||||
*/
|
||||
public static function getInstance(string $namespace, array $config): self
|
||||
public static function getInstance(string $namespace, Storage $storage, array $config): self
|
||||
{
|
||||
$key = $namespace . '_' . md5(serialize($config));
|
||||
|
||||
if (!isset(self::$instances[$key])) {
|
||||
self::$instances[$key] = new self($namespace, $config);
|
||||
self::$instances[$key] = new self($namespace, $storage, $config);
|
||||
}
|
||||
|
||||
return self::$instances[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize storage based on configuration
|
||||
*/
|
||||
private function initializeStorage(): void
|
||||
{
|
||||
$storageType = $this->config['storage_type'] ?? 'file';
|
||||
|
||||
switch ($storageType) {
|
||||
case 'file':
|
||||
$this->engine = 'File';
|
||||
$dir = $this->config['db_dir'] ?? sys_get_temp_dir() . '/cache/';
|
||||
$this->storage = new FileStorage($dir);
|
||||
break;
|
||||
|
||||
case 'sqlite':
|
||||
$this->engine = 'SQLite';
|
||||
$dbFile = $this->config['sqlite_path'] ?? sys_get_temp_dir() . '/cache.db';
|
||||
$this->storage = new SQLiteStorage($dbFile);
|
||||
break;
|
||||
|
||||
case 'memory':
|
||||
$this->engine = 'Memory';
|
||||
$this->storage = new MemoryStorage();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Fallback to file storage
|
||||
$this->engine = 'File';
|
||||
$dir = $this->config['db_dir'] ?? sys_get_temp_dir() . '/cache/';
|
||||
$this->storage = new FileStorage($dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache get method (Legacy Cache API)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
namespace TorrentPier\Cache;
|
||||
|
||||
use Nette\Caching\Cache;
|
||||
use Nette\Caching\Storage;
|
||||
use TorrentPier\Dev;
|
||||
|
||||
/**
|
||||
|
@ -93,12 +94,13 @@ class DatastoreManager
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Storage $storage Pre-built storage instance from UnifiedCacheSystem
|
||||
* @param array $config
|
||||
*/
|
||||
private function __construct(array $config)
|
||||
private function __construct(Storage $storage, array $config)
|
||||
{
|
||||
// Create unified cache manager for datastore
|
||||
$this->cacheManager = CacheManager::getInstance('datastore', $config);
|
||||
// Create unified cache manager for datastore with pre-built storage
|
||||
$this->cacheManager = CacheManager::getInstance('datastore', $storage, $config);
|
||||
$this->engine = $this->cacheManager->engine;
|
||||
$this->dbg_enabled = dev()->checkSqlDebugAllowed();
|
||||
}
|
||||
|
@ -106,13 +108,14 @@ class DatastoreManager
|
|||
/**
|
||||
* Get singleton instance
|
||||
*
|
||||
* @param Storage $storage Pre-built storage instance
|
||||
* @param array $config
|
||||
* @return self
|
||||
*/
|
||||
public static function getInstance(array $config): self
|
||||
public static function getInstance(Storage $storage, array $config): self
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self($config);
|
||||
self::$instance = new self($storage, $config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
|
|
|
@ -46,6 +46,7 @@ $datastore = datastore();
|
|||
- ✅ **Advanced Features**: Dependencies, tags, bulk operations, memoization, output buffering
|
||||
- ✅ **Better Debugging**: Unified debug interface with compatibility for Dev.php
|
||||
- ✅ **Performance**: 456,647+ operations per second with efficient memory usage
|
||||
- ✅ **Clean Architecture**: No redundant configuration logic, single storage creation path
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -190,17 +191,19 @@ $bb_cfg['datastore_type'] = 'file'; // Uses Nette FileStorage
|
|||
| `file` | `FileStorage` | File-based, persistent, dependencies |
|
||||
| `sqlite` | `SQLiteStorage` | Database, supports tags and complex dependencies |
|
||||
| `memory` | `MemoryStorage` | In-memory, fastest, non-persistent |
|
||||
| `memcached` | `MemcachedStorage` | Distributed memory, high-performance |
|
||||
|
||||
### Storage Features Comparison
|
||||
|
||||
| Feature | FileStorage | SQLiteStorage | MemoryStorage |
|
||||
|---------|-------------|---------------|---------------|
|
||||
| Persistence | ✅ | ✅ | ❌ |
|
||||
| File Dependencies | ✅ | ✅ | ✅ |
|
||||
| Tags | ❌ | ✅ | ✅ |
|
||||
| Callbacks | ✅ | ✅ | ✅ |
|
||||
| Bulk Operations | ✅ | ✅ | ✅ |
|
||||
| Performance | High | Medium | Highest |
|
||||
| Feature | FileStorage | SQLiteStorage | MemoryStorage | MemcachedStorage |
|
||||
|---------|-------------|---------------|---------------|------------------|
|
||||
| Persistence | ✅ | ✅ | ❌ | ✅ |
|
||||
| File Dependencies | ✅ | ✅ | ✅ | ✅ |
|
||||
| Tags | ❌ | ✅ | ✅ | ❌ |
|
||||
| Callbacks | ✅ | ✅ | ✅ | ✅ |
|
||||
| Bulk Operations | ✅ | ✅ | ✅ | ✅ |
|
||||
| Performance | High | Medium | Highest | Very High |
|
||||
| Distributed | ❌ | ❌ | ❌ | ✅ |
|
||||
|
||||
## Migration Guide
|
||||
|
||||
|
@ -279,13 +282,40 @@ $rendered_page = $cache->capture("page_$page_id", function() {
|
|||
|
||||
## Implementation Details
|
||||
|
||||
### Architecture Flow (Refactored)
|
||||
|
||||
**Clean, Non-Redundant Architecture:**
|
||||
```
|
||||
UnifiedCacheSystem (singleton)
|
||||
├── _buildStorage() → Creates Nette Storage instances directly
|
||||
├── get_cache_obj() → Returns CacheManager with pre-built storage
|
||||
└── getDatastore() → Returns DatastoreManager with pre-built storage
|
||||
|
||||
CacheManager (receives pre-built Storage)
|
||||
├── Constructor receives: Storage instance + minimal config
|
||||
├── No redundant initializeStorage() switch statement
|
||||
└── Focuses purely on cache operations
|
||||
|
||||
DatastoreManager (uses CacheManager internally)
|
||||
├── Constructor receives: Storage instance + minimal config
|
||||
├── Uses CacheManager internally for unified functionality
|
||||
└── Maintains datastore-specific methods and compatibility
|
||||
```
|
||||
|
||||
**Benefits of Refactored Architecture:**
|
||||
- **Single Source of Truth**: Only UnifiedCacheSystem creates storage instances
|
||||
- **No Redundancy**: Eliminated duplicate switch statements and configuration parsing
|
||||
- **Cleaner Separation**: CacheManager focuses on caching, not storage creation
|
||||
- **Impossible Path Bugs**: Storage is pre-built, no configuration mismatches possible
|
||||
- **Better Maintainability**: One place to modify storage creation logic
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
src/Cache/
|
||||
├── CacheManager.php # Cache interface with Nette Caching + singleton pattern
|
||||
├── DatastoreManager.php # Datastore interface using CacheManager internally
|
||||
├── UnifiedCacheSystem.php # Main singleton orchestrator
|
||||
├── UnifiedCacheSystem.php # Main singleton orchestrator + storage factory
|
||||
└── README.md # This documentation
|
||||
```
|
||||
|
||||
|
@ -304,6 +334,8 @@ The following development and testing files were removed after successful integr
|
|||
4. **Efficient Singletons**: Memory-efficient instance management following TorrentPier patterns
|
||||
5. **Unified Debugging**: Consistent debug interface compatible with Dev.php
|
||||
6. **Production Ready**: Comprehensive error handling, validation, and performance optimization
|
||||
7. **Clean Architecture**: Eliminated redundant configuration logic and switch statements
|
||||
8. **Single Storage Source**: All storage creation centralized in UnifiedCacheSystem
|
||||
|
||||
### Architectural Consistency
|
||||
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
|
||||
namespace TorrentPier\Cache;
|
||||
|
||||
use Nette\Caching\Storage;
|
||||
use Nette\Caching\Storages\FileStorage;
|
||||
use Nette\Caching\Storages\MemcachedStorage;
|
||||
use Nette\Caching\Storages\MemoryStorage;
|
||||
use Nette\Caching\Storages\SQLiteStorage;
|
||||
|
||||
/**
|
||||
* Unified Cache System using Nette Caching
|
||||
* Replaces Legacy Caches class and provides both cache and datastore functionality
|
||||
|
@ -81,10 +87,12 @@ class UnifiedCacheSystem
|
|||
$this->cfg = $cfg['cache'] ?? [];
|
||||
|
||||
// Create stub cache manager
|
||||
$this->stub = CacheManager::getInstance('__stub', [
|
||||
'storage_type' => 'memory',
|
||||
$stubStorage = new MemoryStorage();
|
||||
$stubConfig = [
|
||||
'engine' => 'Memory',
|
||||
'prefix' => $this->cfg['prefix'] ?? 'tp_'
|
||||
]);
|
||||
];
|
||||
$this->stub = CacheManager::getInstance('__stub', $stubStorage, $stubConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,10 +109,16 @@ class UnifiedCacheSystem
|
|||
$this->ref[$cache_name] = $this->stub;
|
||||
} else {
|
||||
$cache_type = $engine_cfg[0] ?? 'file';
|
||||
$config = $this->_buildCacheConfig($cache_type, $cache_name);
|
||||
|
||||
if (!isset($this->managers[$cache_name])) {
|
||||
$this->managers[$cache_name] = CacheManager::getInstance($cache_name, $config);
|
||||
// Build storage and config directly
|
||||
$storage = $this->_buildStorage($cache_type, $cache_name);
|
||||
$config = [
|
||||
'engine' => $this->_getEngineType($cache_type),
|
||||
'prefix' => $this->cfg['prefix'] ?? 'tp_'
|
||||
];
|
||||
|
||||
$this->managers[$cache_name] = CacheManager::getInstance($cache_name, $storage, $config);
|
||||
}
|
||||
$this->ref[$cache_name] = $this->managers[$cache_name];
|
||||
}
|
||||
|
@ -122,94 +136,108 @@ class UnifiedCacheSystem
|
|||
public function getDatastore(string $datastore_type = 'file'): DatastoreManager
|
||||
{
|
||||
if ($this->datastore === null) {
|
||||
$config = $this->_buildDatastoreConfig($datastore_type);
|
||||
$this->datastore = DatastoreManager::getInstance($config);
|
||||
// Build storage and config for datastore
|
||||
$storage = $this->_buildDatastoreStorage($datastore_type);
|
||||
$config = [
|
||||
'engine' => $this->_getEngineType($datastore_type),
|
||||
'prefix' => $this->cfg['prefix'] ?? 'tp_'
|
||||
];
|
||||
|
||||
$this->datastore = DatastoreManager::getInstance($storage, $config);
|
||||
}
|
||||
|
||||
return $this->datastore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build cache configuration
|
||||
* Build storage instance directly (eliminates redundancy with CacheManager)
|
||||
*
|
||||
* @param string $cache_type
|
||||
* @param string $cache_name
|
||||
* @return array
|
||||
* @return Storage
|
||||
*/
|
||||
private function _buildCacheConfig(string $cache_type, string $cache_name): array
|
||||
private function _buildStorage(string $cache_type, string $cache_name): Storage
|
||||
{
|
||||
$config = [
|
||||
'prefix' => $this->cfg['prefix'] ?? 'tp_',
|
||||
];
|
||||
|
||||
switch ($cache_type) {
|
||||
case 'file':
|
||||
case 'filecache':
|
||||
case 'apcu':
|
||||
case 'memcached':
|
||||
case 'redis':
|
||||
// Some deprecated cache types will fall back to file storage
|
||||
$config['storage_type'] = 'file';
|
||||
$config['db_dir'] = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/' . $cache_name . '/';
|
||||
break;
|
||||
$dir = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/' . $cache_name . '/';
|
||||
return new FileStorage($dir);
|
||||
|
||||
case 'sqlite':
|
||||
$config['storage_type'] = 'sqlite';
|
||||
$config['sqlite_path'] = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/' . $cache_name . '.db';
|
||||
break;
|
||||
$dbFile = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/' . $cache_name . '.db';
|
||||
return new SQLiteStorage($dbFile);
|
||||
|
||||
case 'memory':
|
||||
$config['storage_type'] = 'memory';
|
||||
break;
|
||||
return new MemoryStorage();
|
||||
|
||||
case 'memcached':
|
||||
$memcachedConfig = $this->cfg['memcached'] ?? ['host' => '127.0.0.1', 'port' => 11211];
|
||||
$host = $memcachedConfig['host'] ?? '127.0.0.1';
|
||||
$port = $memcachedConfig['port'] ?? 11211;
|
||||
return new MemcachedStorage("{$host}:{$port}");
|
||||
|
||||
default:
|
||||
$config['storage_type'] = 'file';
|
||||
$config['db_dir'] = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/' . $cache_name . '/';
|
||||
break;
|
||||
// Fallback to file storage
|
||||
$dir = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/' . $cache_name . '/';
|
||||
return new FileStorage($dir);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build datastore configuration
|
||||
* Get engine type name for debugging
|
||||
*
|
||||
* @param string $cache_type
|
||||
* @return string
|
||||
*/
|
||||
private function _getEngineType(string $cache_type): string
|
||||
{
|
||||
return match ($cache_type) {
|
||||
'sqlite' => 'SQLite',
|
||||
'memory' => 'Memory',
|
||||
'memcached' => 'Memcached',
|
||||
default => 'File',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build datastore storage instance
|
||||
*
|
||||
* @param string $datastore_type
|
||||
* @return array
|
||||
* @return Storage
|
||||
*/
|
||||
private function _buildDatastoreConfig(string $datastore_type): array
|
||||
private function _buildDatastoreStorage(string $datastore_type): Storage
|
||||
{
|
||||
$config = [
|
||||
'prefix' => $this->cfg['prefix'] ?? 'tp_',
|
||||
];
|
||||
|
||||
switch ($datastore_type) {
|
||||
case 'file':
|
||||
case 'filecache':
|
||||
case 'apcu':
|
||||
case 'memcached':
|
||||
case 'redis':
|
||||
// Some deprecated cache types will fall back to file storage
|
||||
$config['storage_type'] = 'file';
|
||||
$config['db_dir'] = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/datastore/';
|
||||
break;
|
||||
$dir = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/datastore/';
|
||||
return new FileStorage($dir);
|
||||
|
||||
case 'sqlite':
|
||||
$config['storage_type'] = 'sqlite';
|
||||
$config['sqlite_path'] = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/datastore.db';
|
||||
break;
|
||||
$dbFile = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/datastore.db';
|
||||
return new SQLiteStorage($dbFile);
|
||||
|
||||
case 'memory':
|
||||
$config['storage_type'] = 'memory';
|
||||
break;
|
||||
return new MemoryStorage();
|
||||
|
||||
case 'memcached':
|
||||
$memcachedConfig = $this->cfg['memcached'] ?? ['host' => '127.0.0.1', 'port' => 11211];
|
||||
$host = $memcachedConfig['host'] ?? '127.0.0.1';
|
||||
$port = $memcachedConfig['port'] ?? 11211;
|
||||
return new MemcachedStorage("{$host}:{$port}");
|
||||
|
||||
default:
|
||||
$config['storage_type'] = 'file';
|
||||
$config['db_dir'] = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/datastore/';
|
||||
break;
|
||||
// Fallback to file storage
|
||||
$dir = rtrim($this->cfg['db_dir'] ?? sys_get_temp_dir() . '/cache/', '/') . '/datastore/';
|
||||
return new FileStorage($dir);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -323,7 +351,15 @@ class UnifiedCacheSystem
|
|||
$fullConfig = array_merge($this->cfg, $config);
|
||||
$fullConfig['prefix'] = $fullConfig['prefix'] ?? 'tp_';
|
||||
|
||||
return CacheManager::getInstance($namespace, $fullConfig);
|
||||
// Build storage for the advanced cache
|
||||
$storageType = $config['storage_type'] ?? 'file';
|
||||
$storage = $this->_buildStorage($storageType, $namespace);
|
||||
$managerConfig = [
|
||||
'engine' => $this->_getEngineType($storageType),
|
||||
'prefix' => $fullConfig['prefix']
|
||||
];
|
||||
|
||||
return CacheManager::getInstance($namespace, $storage, $managerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -353,10 +389,14 @@ class UnifiedCacheSystem
|
|||
*/
|
||||
public function createTaggedCache(string $namespace): CacheManager
|
||||
{
|
||||
$config = $this->cfg;
|
||||
$config['storage_type'] = 'sqlite'; // SQLite supports tags via journal
|
||||
// Use SQLite storage which supports tags via journal
|
||||
$storage = $this->_buildStorage('sqlite', $namespace);
|
||||
$config = [
|
||||
'engine' => 'SQLite',
|
||||
'prefix' => $this->cfg['prefix'] ?? 'tp_'
|
||||
];
|
||||
|
||||
return CacheManager::getInstance($namespace, $config);
|
||||
return CacheManager::getInstance($namespace, $storage, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue