CuyZ / Valinor

PHP library that helps to map any input into a strongly-typed value object structure.
https://valinor.cuyz.io
MIT License
1.32k stars 74 forks source link

Dynamic loaders #577

Open mastir opened 5 days ago

mastir commented 5 days ago

Hey @romm, after a while i came back to the same performance issue. My app works in microservice enviroment and simplified workflow is:

Atm i recreate mapper and normalizer after every module loaded. Example intrface:

#[TypedInterface([
    'column.add' => AddColumnDto::class,
    'column.drop' => DropColumnDto::class,
    'column.rename' => RenameColumnDto::class,
    'relation.add' => AddRelationDTO::class,
    'relation.drop' => DropRelationDto::class,
])]
interface AlterOperation {}

and methods to add interfaces like this in MapperBuilder:

    public function onModuleLoaded(string $namespace){
        $updated = false;
        foreach($this->findInterafaces($namespace) as $interfaceName){
            $attr = $this->readAttributes($interfaceName);
            if (!$attr) continue;
            $this->mapperBuilder = $this->mapperBuilder->infer($this->generateInfer($attr->param, $attr->map));
            $updated = true;
        }
        if ($updated){
            $this->mapper = $this->mapperBuilder->mapper();
            $this->normalizer = $this->mapperBuilder->normalizer(Format::array());
        }
    }

    public function generateInfer(string $param_name, array $classmap){
        $tmpfile = tempnam(sys_get_temp_dir(), 'valinor');
        $variants = implode(' | ', $classmap);
        $mapdump = var_export($classmap, true);
        $content = <<<EOT
\$classmap = $mapdump;
/**
 * @return class-string<$variants>
 */
return fn (string \$$param_name) use (\$classmap) => \$classmap[\$$param_name] ?? 'Unknown'.\$$param_name;
EOT;
        file_put_contents($tmpfile, $content);
        $method = include $tmpfile;
        unlink($tmpfile);
        return $method;
    }

I tried to implement some more generic solution in #560 with no success. is there a better way to implement it?

romm commented 4 days ago

Hi @mastir, thanks for the detailed issue. I now see the problem and will be thinking about a solution. Please be patient, I don't have much time these days but I'll definitely find a solution at some point.