Overhaul the Docsify documentation (English + Russian) so it matches the current codebase and follows one consistent pattern. Content accuracy (post-migration): - Rewrite development/autoloader.md to PSR-4 / Composer (the old XC_Autoloader scanner, igbinary tmp/cache/autoload_map and registerDirectories are gone). - PascalCase every source path (src/core -> src/Core, domain/Stream, cli/Commands, public/Controllers, Infrastructure/Redis, ...) across all docs. - Replace the removed autoload.php references with vendor/autoload.php (build_system, bootstrap-contexts, error-handling, modules). - ssl-generation: note that the installer now auto-generates a unique self-signed certificate before Nginx starts. Common pattern (Clean & uniform): - Strip emoji from headings; remove the in-page Navigation blocks (the Docsify sidebar already provides navigation). - One H1 + intro per doc; uniform "Related files" / "Связанные файлы" section, added to the code-centric docs that lacked it. Structure: - Remove the empty stray docs/api/; move updates_checklist.md into builds/; link the previously-orphaned ucs-integration.md. - Regroup the sidebars (split the oversized guides group into Developer Guides / Security & Access / Integrations; fold builds into Build & Release). Augment: - dev-workflow: Local Setup (make dev-tools) + Quality Checks (phpstan, cs, gates). - build_system: Composer Dependencies section (committed prod-only vendor, committed lock, dev tools via composer install, no build-time vendor step). en/ru parity: - Apply the same structure, fixes and pattern to docs/ru/ (translated), including a new Russian ucs-integration.md. The en and ru file sets are now identical.
11 KiB
Кэширование и стратегия Redis
XC_VM использует двухуровневую стратегию кэширования:
- Файловый кэш (igbinary) — основной уровень, используемый как стриминговым, так и административным путём
- Redis/KeyDB — опциональный высокопроизводительный уровень для состояния подключений и продвинутых операций
Стриминговый путь читает исключительно из файлового кэша (без запросов к базе данных). Административный путь читает напрямую из базы данных с опциональным короткоживущим кэшем.
Интерфейс кэша
Файл: src/Core/Cache/CacheInterface.php
get($key, $maxAge = null)
set($key, $data, $ttl = 0)
delete($key)
has($key, $maxAge = null)
flush()
$ttl = 0означает кэш навсегда (до ручного удаления или сброса).$maxAgeпроверяет время изменения файла для свежести (только FileCache).
FileCache
Файл: src/Core/Cache/FileCache.php
Реализация кэша по умолчанию. Хранит igbinary-сериализованные данные в виде плоских файлов.
$cache = new FileCache(CACHE_TMP_PATH);
$cache->set('my_key', $data, 3600);
$data = $cache->get('my_key', 120); // только если меньше 2 минут
Статический упрощённый API (обратная совместимость):
FileCache::setCache($key, $data)
FileCache::getCache($key, $maxAge = null)
Характеристики:
- Сериализация: igbinary (если доступна) или резервный PHP serialize.
- Блокировка:
LOCK_EXпри записи во избежание повреждения. - Расположение файла:
{basePath}/{key}(без подкаталогов для основных ключей). - Восстановление при повреждении: определяет битые данные, автоматически удаляет повреждённые файлы.
RedisCache
Файл: src/Core/Cache/RedisCache.php
Опциональная высокопроизводительная реализация.
$redis = new RedisCache('127.0.0.1', 6379, $password, 'prefix:');
$redis->set($key, $data, 600); // TTL 10 минут через SETEX
$redis->getConnection(); // сырой phpredis для sorted sets, pipelines
- Ленивое подключение: подключается при первой операции.
- Нативная поддержка TTL через
SETEXв Redis. - Используется в первую очередь для
ConnectionTracker(sorted sets для состояния активных подключений).
Управление подключением к Redis
Файл: src/Infrastructure/Redis/RedisManager.php
Жизненный цикл singleton:
RedisManager::instance() // получить активный Redis или null
RedisManager::ensureConnected() // подключиться, если ещё не подключено
RedisManager::isConnected() // проверка состояния
RedisManager::closeInstance() // отключение
Проверка состояния пингует Redis каждые 30 секунд (с дебаунсом). Автоматически переподключается при сбое. Возвращает null при сбое подключения (плавная деградация).
Конфигурация:
| Настройка | Источник | По умолчанию |
|---|---|---|
hostname |
config.ini |
— |
port |
hardcoded | 6379 |
password |
settings.redis_password |
— |
read_timeout |
hardcoded | 2.0 с |
tcp_keepalive |
hardcoded | 60 с |
Наполнение кэша
Файлы кэша генерируются двумя cron-задачами:
Лёгкий кэш (CacheCronJob)
Запускается каждый cron-цикл. Перестраивает быстро меняющиеся данные (~1 секунда):
settings— настройки панелиservers— список серверовbouquets— пакеты каналовcategories— категории потоков- Блок-листы:
blocked_isp,blocked_ua,blocked_ips,blocked_servers allowed_ips,output_formats,hmac_keys,rtmp_ips
Тяжёлый кэш (CacheEngineCronJob)
Перестраивает данные о потоках, линиях и сериях. Ограничен запуском раз в 5 минут через маркер heavy_cache_built:
STREAMS_TMP_PATH/stream_{id}— метаданные отдельного потокаLINES_TMP_PATH/line_i_{user_id}— данные аккаунта пользователяLINES_TMP_PATH/line_c_{username_password}— username → user_id lookupLINES_TMP_PATH/line_t_{access_token}— token → user_id lookupSERIES_TMP_PATH/series_{id}— метаданные сериала
Режим детекции изменений (если включено cache_changes): сравнивает временную метку updated в БД с mtime файла, перестраивает только изменённые элементы.
Режим полной перестройки: пересоздаёт все записи. Управляется настройкой cache_thread_count.
Готовность кэша
Файл cache_complete записывается после каждой полной перестройки кэша. Стриминговый путь проверяет этот файл и завершается с ошибкой, если он отсутствует.
Соглашения о ключах кэша
Системные ключи (CACHE_TMP_PATH)
| Ключ | Содержимое |
|---|---|
settings |
массив настроек панели |
servers |
array[server_id] → конфигурация сервера |
bouquets |
array[bouquet_id] → определение букета |
categories |
array[category_id] → данные категории |
bouquet_map |
array[stream_id] → array[bouquet_id] |
category_map |
array[bouquet_id] → array[category_id] |
permissions_{group_id} |
набор прав группы |
cache_complete |
временная метка time() последней полной перестройки |
Ключи потоков (STREAMS_TMP_PATH)
| Ключ | Содержимое |
|---|---|
stream_{id} |
информация о потоке + букеты + состояние по серверам |
channels_categories |
array[stream_id] → array[category_id] |
Ключи линий (LINES_TMP_PATH)
| Ключ | Содержимое |
|---|---|
line_i_{user_id} |
полная запись пользователя |
line_c_{username_password} |
user_id (lookup по учётным данным) |
line_t_{access_token} |
user_id (lookup по токену) |
Ключи сериалов (SERIES_TMP_PATH)
| Ключ | Содержимое |
|---|---|
series_{id} |
метаданные сериала |
series_map |
array[stream_id] → series_id |
episodes_{series_id} |
array[season_num] → список эпизодов |
Паттерны инвалидации
| Триггер | Затронутые ключи | Механизм |
|---|---|---|
| Админ редактирует поток | stream_{id}, bouquet_map |
сигнал → следующий cron:cache_engine |
| Админ редактирует линию | line_i_*, line_c_*, line_t_* |
следующий cron:cache_engine |
| Изменены настройки | settings, categories, blocklists |
SettingsManager::clearCache() + cron |
| Обновлён список серверов | servers, bouquet_map |
cron |
| Старт потока (FFprobe) | {md5(source)} |
TTL 5 минут через проверку mtime файла |
| Кнопка flush в админке | все файлы в CACHE_TMP_PATH |
rm -rf |
Стриминговый путь vs административный
Стриминговый путь (www/stream/*)
cached: trueпо умолчанию.- Читает только из файлового кэша (без запросов к БД).
- Сырая igbinary-десериализация:
igbinary_unserialize(file_get_contents(...)). - Если
cache_completeотсутствует — выход с ошибкой.
Административный путь (Public/Controllers/Admin/*)
cached: falseпо умолчанию.- Читает напрямую из базы данных через доменные сервисы.
- Опциональный короткоживущий кэш (пример из
BouquetService::getAll()):
$rCache = FileCache::getCache('bouquets', 60); // только если меньше 60 с
if (!empty($rCache)) {
return $rCache;
}
// промах: запрос к базе и запись кэша
FileCache::setCache('bouquets', $rOutput);
Структура файлов кэша
/home/xc_vm/tmp/cache/
├── settings
├── servers
├── bouquets
├── categories
├── bouquet_map
├── category_map
├── cache_complete
├── heavy_cache_built
├── streams/
│ ├── stream_{id}
│ └── channels_categories
├── lines/
│ ├── line_i_{user_id}
│ ├── line_c_{username_password}
│ └── line_t_{access_token}
└── series/
├── series_{id}
├── series_map
└── episodes_{series_id}
Связанные файлы
| Файл | Назначение |
|---|---|
src/Core/Cache/CacheInterface.php |
контракт кэша |
src/Core/Cache/FileCache.php |
реализация файлового кэша |
src/Core/Cache/RedisCache.php |
реализация Redis-кэша |
src/Infrastructure/Redis/RedisManager.php |
singleton подключения к Redis |
src/Infrastructure/Cache/CacheReader.php |
мост для legacy-чтения кэша |
src/Cli/CronJobs/CacheCronJob.php |
генерация лёгкого кэша |
src/Cli/CronJobs/CacheEngineCronJob.php |
генерация тяжёлого кэша (потоки, линии, сериалы) |
src/Domain/Bouquet/BouquetService.php |
пример кэширования на админ-пути |
src/Domain/Stream/ConnectionTracker.php |
Redis sorted sets для состояния подключений |