mirror of
https://gitee.com/ctexthuang/hyperf_rbac_framework_server_ctexthuang.git
synced 2025-12-25 20:27:49 +08:00
175 lines
3.9 KiB
PHP
175 lines
3.9 KiB
PHP
<?php
|
||
|
||
namespace App\Cache\Redis;
|
||
|
||
|
||
use App\Lib\Log\Logger;
|
||
use Hyperf\Contract\ConfigInterface;
|
||
use Hyperf\Redis\Redis;
|
||
use Exception;
|
||
use Throwable;
|
||
|
||
abstract class BaseScript
|
||
{
|
||
/**
|
||
* @var string|null
|
||
*/
|
||
protected ?string $sha1 = null;
|
||
|
||
/**
|
||
* @var bool
|
||
*/
|
||
protected bool $debugMode;
|
||
|
||
/**
|
||
* @var Redis
|
||
*/
|
||
protected Redis $redis;
|
||
|
||
/**
|
||
* @var ConfigInterface
|
||
*/
|
||
protected ConfigInterface $config;
|
||
|
||
protected Logger $logger;
|
||
|
||
/**
|
||
* @param Redis $redis
|
||
* @param ConfigInterface $config
|
||
* @param Logger $logger
|
||
*/
|
||
public function __construct(
|
||
Redis $redis,
|
||
ConfigInterface $config,
|
||
Logger $logger
|
||
)
|
||
{
|
||
$this->redis = $redis;
|
||
$this->debugMode = $config->get('app_debug',false);
|
||
$this->logger = $logger;
|
||
}
|
||
|
||
/**
|
||
* 获取脚本名称(对应lua文件名)
|
||
* @return string
|
||
*/
|
||
abstract public function getName(): string;
|
||
|
||
/**
|
||
* @param array $keys
|
||
* @param array $args
|
||
* @param int|null $numKeys
|
||
* @return mixed
|
||
*/
|
||
protected function run(
|
||
array $keys,
|
||
array $args,
|
||
?int $numKeys = null
|
||
): mixed
|
||
{
|
||
$numKeys = $numKeys ?? count($keys);
|
||
|
||
try {
|
||
$script = $this->getScriptContent();
|
||
// $this->logExecution($keys, $args, true);
|
||
return $this->execute($script, $keys, $args, $numKeys);
|
||
} catch (Exception|Throwable $e) {
|
||
$this->logExecution($keys, $args, false, $e);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @return string
|
||
* @throws Exception
|
||
*/
|
||
protected function getScriptContent(): string
|
||
{
|
||
$path = __DIR__.'/Script/'.$this->getName().'.lua';
|
||
// $path = __DIR__.'/Lua/'.$this->getName().'.lua';
|
||
|
||
if (!file_exists($path)) throw new Exception('lua文件不存在');
|
||
|
||
$content = file_get_contents($path);
|
||
if ($content === false) throw new Exception('lua文件读取失败');
|
||
|
||
return $content;
|
||
}
|
||
|
||
/**
|
||
* @param string $script
|
||
* @param array $keys
|
||
* @param array $args
|
||
* @param int $numKeys
|
||
* @return mixed
|
||
*/
|
||
protected function execute(
|
||
string $script,
|
||
array $keys,
|
||
array $args,
|
||
int $numKeys
|
||
): mixed
|
||
{
|
||
if (
|
||
!$this->debugMode &&
|
||
$this->sha1
|
||
)
|
||
{
|
||
try {
|
||
return $this->redis->evalsha(
|
||
$this->sha1,
|
||
array_merge($keys, $args),
|
||
$numKeys
|
||
);
|
||
} catch (Throwable $e)
|
||
{
|
||
// SHA1 不存在时回避
|
||
$this->sha1 = null;
|
||
}
|
||
}
|
||
|
||
$result = $this->redis->eval(
|
||
$script,
|
||
array_merge($keys, $args),
|
||
$numKeys
|
||
);
|
||
$this->sha1 = sha1($script);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* @param array $keys
|
||
* @param array $args
|
||
* @param bool $success
|
||
* @param Throwable|null $e
|
||
* @return void
|
||
*/
|
||
protected function logExecution(
|
||
array $keys,
|
||
array $args,
|
||
bool $success,
|
||
?Throwable $e = null,
|
||
): void
|
||
{
|
||
$context = [
|
||
'script' => $this->getName(),
|
||
'keys' => $keys,
|
||
'args' => $args,
|
||
'success' => $success,
|
||
'error' => $e?->getMessage(),
|
||
'line' => $e?->getLine(),
|
||
'trace' => $e?->getTraceAsString()
|
||
];
|
||
|
||
$logStrategy = match(true) {
|
||
!$success => $this->logger->cache()->error(...),
|
||
$this->debugMode => $this->logger->cache()->debug(...),
|
||
default => fn() => null // 不记录
|
||
};
|
||
|
||
if (!$logStrategy) return;
|
||
|
||
$logStrategy('Redis Lua execution', $context);
|
||
}
|
||
} |