-
Notifications
You must be signed in to change notification settings - Fork 327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[3.x] Build custom Redis client based on the installed extension #511
Conversation
5ddc80b
to
e1da2fd
Compare
@B-Galati, how do you propose to load the cache generated class? Currently, I'm generating the file as
|
Good question. |
@curry684 Any advice about the implementation? It looks like you thought about it a lot in the past. |
To detect the phpredis usage, it could be a parameter set by the extension as soon as a phpredis client is declared like here SncRedisBundle/DependencyInjection/SncRedisExtension.php Lines 247 to 295 in 521d237
|
The suggested changes were addressed, I think. Now I'm facing 2 new issues:
|
0c1c7f8
to
6cb87d3
Compare
@phansys Looks like you fix them! Nice! What were the issues? |
These are the changes I've done to solve the described issues:
|
b5f21d5
to
fe0c251
Compare
I think everything is working now @B-Galati. Thank you for your support! |
@phansys What about using |
4971b31
to
e9165aa
Compare
Since we need to intercept each call to Redis' methods, I think we should use Thank you. |
@phansys Sorry i never used it either :/ But I see 2 benefits, the underlying lib ( (I could be missing some points that would make the usage of this lib impossible or hard) |
Hi, it's been a while since last comment ... Is there any news of acceptance for this PR ? Cheers |
Hey, I am not sure about the maintenance cost of this solution. I am currently not having time to look at such a big feature and maintain it after the release. What's your opinion @curry684? |
Same issue here... I think the intended direction is the right way (as discussed long ago) but indeed it's far from trivial to both develop and maintain, and depending on phpredis itself it may either be fragile or more resilient than what we have now. If we go forward on this I would most certainly prefer using the proxy manager as that's indeed battle tested and well maintained. |
109d45d
to
a2e9f88
Compare
@phansys for example what to use here, please check https://github.com/Ocramius/ProxyManager/blob/2.14.x/examples/access-interceptor-scope-localizer.php That's pretty generic example. I've been playing with this some weeks ago in context of sncredis and this example I came up with could help too: (static function () : void {
$config = new Configuration();
$config->setGeneratorStrategy(new FileWriterGeneratorStrategy(new FileLocator(__DIR__.'/generated')));
$config->setProxiesTargetDir(__DIR__.'/generated');
// then register the autoloader
spl_autoload_register($config->getProxyAutoloader());
$factory = new AccessInterceptorScopeLocalizerFactory($config);
$foo = new FluentCounter();
$proxy = $factory->createProxy(
$foo,
[
'fluentMethod' => static function (AccessInterceptorInterface $proxy, FluentCounter $realInstance) use (&$time) : void {
$time = microtime(true);
},
],
[
'fluentMethod' => static function (AccessInterceptorInterface $proxy, FluentCounter $realInstance) use (&$time) : void {
echo "fluentMethod #{$realInstance->counter} took ".(microtime(true) - $time)."!\n";
},
]
);
var_dump(\Safe\class_parents($proxy));
$proxy->fluentMethod()->fluentMethod()->fluentMethod()->fluentMethod();
echo 'The proxy counter is now at ' . $proxy->counter . "\n";
echo 'The real instance counter is now at ' . $foo->counter . "\n";
})(); Current solution with custom generator indeed is not something we will merge. If you think it's better, perhaps you could also use laminas code generator, that's a library behind ocramius proxy manager. I was playing with that idea, because it seems we can't avoid having to create reflection classes and iterate over Redis classes anyways - ProxyManager requires listing all the methods we want to proxify. With that one, it would be something like this: <?php
declare(strict_types=1);
namespace ProxyManager\Example\AccessInterceptorScopeLocalizer;
use Laminas\Code\Generator\ClassGenerator;
use Laminas\Code\Generator\MethodGenerator;
use Laminas\Code\Generator\ParameterGenerator;
use Laminas\Code\Reflection\MethodReflection;
use ProxyManager\Generator\Util\ClassGeneratorUtils;
use Psr\Log\LoggerInterface;
require_once __DIR__ . '/../vendor/autoload.php';
$reflClass = new \ReflectionClass(\RedisCluster::class);
$classGenerator = new ClassGenerator('SncLoggingAwareRedisClient');
$classGenerator->setExtendedClass($reflClass->getName());
foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
$forwardedParams = [];
if ($method->getName()[0] === '_') {
continue;
}
foreach ($method->getParameters() as $parameter) {
$forwardedParams[] = ($parameter->isVariadic() ? '...' : '') . '$' . $parameter->getName();
}
$methodGenerator = MethodGenerator::copyMethodSignature(new MethodReflection($reflClass->getName(), $method->getName()));
if ($method->isConstructor()) {
$logger = new ParameterGenerator('logger', LoggerInterface::class, null, $method->getNumberOfParameters());
$logger->setDefaultValue(null);
$methodGenerator->setParameter($logger);
$methodGenerator->setBody("
parent::__construct(" . implode(', ', $forwardedParams) . '");
$this->logger = $logger;
');
} else {
$methodGenerator->setBody("
\$startTime = microtime(true);
\$return = parent::{$method->getName()}(" . implode(', ', $forwardedParams) . ");
\$duration = (microtime(true) - \$startTime) * 1000;
if (null !== \$this->logger) {
\$this->logger->logCommand(\$this->getCommandString({$method->getName()}, func_get_args(), \$duration, \$this->alias, false);
}
return \$return;
");
}
ClassGeneratorUtils::addMethodIfNotFinal($reflClass, $classGenerator, $methodGenerator);
}
echo $classGenerator->generate(); |
Superseded by #636 |
Fixes #399.
This PR reverts the changes made at #405 and #487.