feat: add config redis cache, categories cache (#44)
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
3. **Следуй соглашениям именования проекта**
|
3. **Следуй соглашениям именования проекта**
|
||||||
4. **Тестируй изменения перед коммитом**
|
4. **Тестируй изменения перед коммитом**
|
||||||
5. **Документируй публичные API**
|
5. **Документируй публичные API**
|
||||||
|
6. **Комментарии только на английском языке и только если они действительно оправданы**
|
||||||
|
|
||||||
### Правила коммитов
|
### Правила коммитов
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ services:
|
|||||||
- PHP_IDE_CONFIG=serverName=telecart
|
- PHP_IDE_CONFIG=serverName=telecart
|
||||||
- php.session.gc_maxlifetime=28800
|
- php.session.gc_maxlifetime=28800
|
||||||
- php.session.cookie_lifetime=0
|
- php.session.cookie_lifetime=0
|
||||||
- TELECART_CACHE_DRIVER=database
|
|
||||||
- TELECART_REDIS_HOST=redis
|
- TELECART_REDIS_HOST=redis
|
||||||
- TELECART_REDIS_PORT=6379
|
- TELECART_REDIS_PORT=6379
|
||||||
- TELECART_REDIS_DATABASE=0
|
- TELECART_REDIS_DATABASE=0
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
PULSE_API_HOST=https://pulse.telecart.pro/api/
|
PULSE_API_HOST=https://pulse.telecart.pro/api/
|
||||||
PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb
|
PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb
|
||||||
|
|
||||||
|
TELECART_CACHE_DRIVER=redis
|
||||||
|
#TELECART_REDIS_HOST=redis
|
||||||
|
#TELECART_REDIS_PORT=6379
|
||||||
|
#TELECART_REDIS_DATABASE=0
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
PULSE_API_HOST=http://host.docker.internal:8086/api/
|
PULSE_API_HOST=http://host.docker.internal:8086/api/
|
||||||
PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb
|
PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb
|
||||||
|
TELECART_CACHE_DRIVER=database
|
||||||
|
TELECART_REDIS_HOST=redis
|
||||||
|
TELECART_REDIS_PORT=6379
|
||||||
|
TELECART_REDIS_DATABASE=0
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
PULSE_API_HOST=https://pulse.telecart.pro/api/
|
PULSE_API_HOST=https://pulse.telecart.pro/api/
|
||||||
PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb
|
PULSE_HEARTBEAT_SECRET=c5261f5d-529e-45ad-a69c-9778b755b7cb
|
||||||
|
TELECART_CACHE_DRIVER=mysql
|
||||||
|
TELECART_REDIS_HOST=redis
|
||||||
|
TELECART_REDIS_PORT=6379
|
||||||
|
TELECART_REDIS_DATABASE=0
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Bastion\Tasks;
|
|
||||||
|
|
||||||
use DateInterval;
|
|
||||||
use Openguru\OpenCartFramework\Cache\CacheInterface;
|
|
||||||
use Openguru\OpenCartFramework\MaintenanceTasks\BaseMaintenanceTask;
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
|
|
||||||
class CachePruneTask extends BaseMaintenanceTask
|
|
||||||
{
|
|
||||||
private CacheInterface $cache;
|
|
||||||
|
|
||||||
public function __construct(LoggerInterface $logger, CacheInterface $cache)
|
|
||||||
{
|
|
||||||
parent::__construct($logger);
|
|
||||||
|
|
||||||
$this->cache = $cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(): void
|
|
||||||
{
|
|
||||||
$this->cache->prune();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function interval(): ?DateInterval
|
|
||||||
{
|
|
||||||
return new DateInterval('P1D');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Bastion\Tasks\CachePruneTask;
|
|
||||||
use Bastion\Tasks\CleanUpOldAssetsTask;
|
use Bastion\Tasks\CleanUpOldAssetsTask;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'tasks' => [
|
'tasks' => [
|
||||||
CleanUpOldAssetsTask::class,
|
CleanUpOldAssetsTask::class,
|
||||||
CachePruneTask::class,
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ class Application extends Container implements LoggerAwareInterface
|
|||||||
return new Settings($container->getConfigValue());
|
return new Settings($container->getConfigValue());
|
||||||
});
|
});
|
||||||
|
|
||||||
$dotenv = Dotenv::createImmutable(__DIR__ . '/../');
|
$this->loadEnvironmentVariables();
|
||||||
$dotenv->load();
|
|
||||||
|
|
||||||
$errorHandler = new ErrorHandler(
|
$errorHandler = new ErrorHandler(
|
||||||
$this->get(LoggerInterface::class),
|
$this->get(LoggerInterface::class),
|
||||||
@@ -172,4 +171,30 @@ class Application extends Container implements LoggerAwareInterface
|
|||||||
{
|
{
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads environment variables from .env files.
|
||||||
|
* First loads internal .env (from phar or module directory),
|
||||||
|
* then external .env (if exists next to phar/directory) which overrides values.
|
||||||
|
*/
|
||||||
|
private function loadEnvironmentVariables(): void
|
||||||
|
{
|
||||||
|
if (!defined('BP_PHAR_BASE_PATH') || !defined('BP_REAL_BASE_PATH')) {
|
||||||
|
$dotenv = Dotenv::createMutable(__DIR__ . '/../');
|
||||||
|
$dotenv->load();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$internalEnvPath = BP_PHAR_BASE_PATH;
|
||||||
|
if (is_readable($internalEnvPath . '/.env')) {
|
||||||
|
$dotenv = Dotenv::createImmutable($internalEnvPath);
|
||||||
|
$dotenv->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
$externalEnvPath = BP_REAL_BASE_PATH;
|
||||||
|
if (is_readable($externalEnvPath . '/.env')) {
|
||||||
|
$dotenv = Dotenv::createImmutable($externalEnvPath);
|
||||||
|
$dotenv->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,4 @@ interface CacheInterface
|
|||||||
public function delete(string $key): void;
|
public function delete(string $key): void;
|
||||||
|
|
||||||
public function clear(): void;
|
public function clear(): void;
|
||||||
|
|
||||||
public function prune(): void;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,4 @@ class SymfonyMySqlCache implements CacheInterface
|
|||||||
{
|
{
|
||||||
$this->cache->clear();
|
$this->cache->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function prune(): void
|
|
||||||
{
|
|
||||||
$this->cache->prune();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,4 @@ class SymfonyRedisCache implements CacheInterface
|
|||||||
{
|
{
|
||||||
$this->cache->clear();
|
$this->cache->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function prune(): void
|
|
||||||
{
|
|
||||||
$this->cache->prune();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace App\Handlers;
|
|||||||
|
|
||||||
use App\Services\SettingsService;
|
use App\Services\SettingsService;
|
||||||
use App\Support\Utils;
|
use App\Support\Utils;
|
||||||
|
use Openguru\OpenCartFramework\Cache\CacheInterface;
|
||||||
use Openguru\OpenCartFramework\Http\Request;
|
use Openguru\OpenCartFramework\Http\Request;
|
||||||
use Openguru\OpenCartFramework\ImageTool\ImageFactory;
|
use Openguru\OpenCartFramework\ImageTool\ImageFactory;
|
||||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||||
@@ -21,52 +22,66 @@ class CategoriesHandler
|
|||||||
private Builder $queryBuilder;
|
private Builder $queryBuilder;
|
||||||
private ImageFactory $image;
|
private ImageFactory $image;
|
||||||
private SettingsService $settings;
|
private SettingsService $settings;
|
||||||
|
private CacheInterface $cache;
|
||||||
|
|
||||||
public function __construct(Builder $queryBuilder, ImageFactory $ocImageTool, SettingsService $settings)
|
public function __construct(
|
||||||
{
|
Builder $queryBuilder,
|
||||||
|
ImageFactory $ocImageTool,
|
||||||
|
SettingsService $settings,
|
||||||
|
CacheInterface $cache
|
||||||
|
) {
|
||||||
$this->queryBuilder = $queryBuilder;
|
$this->queryBuilder = $queryBuilder;
|
||||||
$this->image = $ocImageTool;
|
$this->image = $ocImageTool;
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
|
$this->cache = $cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$languageId = $this->settings->config()->getApp()->getLanguageId();
|
$cacheKey = 'categories.index';
|
||||||
$storeId = $this->settings->get('store.oc_store_id', 0);
|
|
||||||
|
|
||||||
$perPage = $request->get('perPage', 100);
|
$categories = $this->cache->get($cacheKey);
|
||||||
|
|
||||||
$categoriesFlat = $this->queryBuilder->newQuery()
|
if ($categories === null) {
|
||||||
->select([
|
$languageId = $this->settings->config()->getApp()->getLanguageId();
|
||||||
'categories.category_id' => 'id',
|
$storeId = $this->settings->get('store.oc_store_id', 0);
|
||||||
'categories.parent_id' => 'parent_id',
|
|
||||||
'categories.image' => 'image',
|
|
||||||
'descriptions.name' => 'name',
|
|
||||||
'descriptions.description' => 'description',
|
|
||||||
])
|
|
||||||
->from(db_table('category'), 'categories')
|
|
||||||
->join(
|
|
||||||
db_table('category_description') . ' AS descriptions',
|
|
||||||
function (JoinClause $join) use ($languageId) {
|
|
||||||
$join->on('categories.category_id', '=', 'descriptions.category_id')
|
|
||||||
->where('descriptions.language_id', '=', $languageId);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
->join(
|
|
||||||
new Table(db_table('category_to_store'), 'category_to_store'),
|
|
||||||
function (JoinClause $join) use ($storeId) {
|
|
||||||
$join->on('category_to_store.category_id', '=', 'categories.category_id')
|
|
||||||
->where('category_to_store.store_id', '=', $storeId);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
->where('categories.status', '=', 1)
|
|
||||||
->orderBy('parent_id')
|
|
||||||
->orderBy('sort_order')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$categories = $this->buildCategoryTree($categoriesFlat);
|
$perPage = $request->get('perPage', 100);
|
||||||
|
|
||||||
$categories = array_slice($categories, 0, $perPage);
|
$categoriesFlat = $this->queryBuilder->newQuery()
|
||||||
|
->select([
|
||||||
|
'categories.category_id' => 'id',
|
||||||
|
'categories.parent_id' => 'parent_id',
|
||||||
|
'categories.image' => 'image',
|
||||||
|
'descriptions.name' => 'name',
|
||||||
|
'descriptions.description' => 'description',
|
||||||
|
])
|
||||||
|
->from(db_table('category'), 'categories')
|
||||||
|
->join(
|
||||||
|
db_table('category_description') . ' AS descriptions',
|
||||||
|
function (JoinClause $join) use ($languageId) {
|
||||||
|
$join->on('categories.category_id', '=', 'descriptions.category_id')
|
||||||
|
->where('descriptions.language_id', '=', $languageId);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->join(
|
||||||
|
new Table(db_table('category_to_store'), 'category_to_store'),
|
||||||
|
function (JoinClause $join) use ($storeId) {
|
||||||
|
$join->on('category_to_store.category_id', '=', 'categories.category_id')
|
||||||
|
->where('category_to_store.store_id', '=', $storeId);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->where('categories.status', '=', 1)
|
||||||
|
->orderBy('parent_id')
|
||||||
|
->orderBy('sort_order')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$categories = $this->buildCategoryTree($categoriesFlat);
|
||||||
|
|
||||||
|
$categories = array_slice($categories, 0, $perPage);
|
||||||
|
|
||||||
|
$this->cache->set($cacheKey, $categories, 60 * 60 * 24);
|
||||||
|
}
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse([
|
||||||
'data' => array_map(static function ($category) {
|
'data' => array_map(static function ($category) {
|
||||||
|
|||||||
Reference in New Issue
Block a user