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->error()->error(...), $this->debugMode => $this->logger->cache()->debug(...), default => fn() => null // 不记录 }; if (!$logStrategy) return; $logStrategy('Redis Lua execution', $context); } }