Skip to content
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

Allow userland middlewares #1472

Merged
merged 1 commit into from
Feb 22, 2022

Conversation

l-vo
Copy link
Contributor

@l-vo l-vo commented Feb 8, 2022

Related to the needs to replace SQLLogger by Middlewares, this implementations allows to easily inject middleware via a doctrine.middleware tag.

@l-vo l-vo force-pushed the allow_userland_middlewares branch 7 times, most recently from b4a7efa to 13a1ce7 Compare February 8, 2022 21:36
@l-vo l-vo changed the title Allow userland middleware Allow userland middlewares Feb 8, 2022
@l-vo l-vo force-pushed the allow_userland_middlewares branch from 13a1ce7 to 2771b57 Compare February 8, 2022 21:46
@greg0ire
Copy link
Member

You can run vendor/bin/phpcbf to fix most CS issues :)

DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
interface ConnectionNameAwareInterface
{
public function setConnectionName(string $name): void;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the use case for this?

Copy link
Contributor Author

@l-vo l-vo Feb 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote this PR with the replacement of DebugStack by middlewares in mind. In the symfony profiler, queries are grouped by connection. I faced a choice:

  • either I inject in the middleware a different service (kind of debug data holder) by connection
  • either the middleware is aware of the connection and set queries in an unique debug data holder tied with their connection

It's not a big deal to duplicate an abstract middleware for each connection with a tag, but duplicating too the debug data holder seemed to me more complicated; it's why I chose the second possibility.

This is how I plan to create the debug data holder:

class DebugDataHolder
{
    private array $data = [];

    public function addQuery(string $connexionName, Query $query): void
    {
        $this->data[$connexionName][] = [
            'sql' => $query->getSql(),
            'params' => $query->getParams(),
            'types' => $query->getTypes(),
            'executionMS' => static fn() => $query->getDuration(),  // stop() may not be called at this point
        ];
    }

    public function getData(string $connexionName): array
    {
        if (!isset($this->data[$connexionName])) {
            return [];
        }

        foreach ($this->data[$connexionName] as &$data) {
            if (is_callable($data['executionMS'])) {
                $data['executionMS'] = $data['executionMS']();
            }
        }

        return $this->data[$connexionName];
    }
}

@l-vo
Copy link
Contributor Author

l-vo commented Feb 11, 2022

You can run vendor/bin/phpcbf to fix most CS issues :)

Thank you, I missed that cs failed

@greg0ire greg0ire closed this Feb 12, 2022
@greg0ire greg0ire reopened this Feb 12, 2022
@ostrolucky ostrolucky added this to the 2.6.0 milestone Feb 13, 2022
DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
Comment on lines 148 to 153
if (interface_exists(Middleware::class)) {
$container
->getDefinition('doctrine.dbal.logger')
->replaceArgument(0, null);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this moved out of loadMiddlewares?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved nothing out of loadMiddlewares, loadMiddleware has just been added in this PR. What am I missing ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useMiddlewaresIfAvailable was renamed to loadMiddlewares. This condition was there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok sorry, it's a subjective choice, in my mind, loadMiddleware should only register middlewares, not disable what is replaced by a middleware. But I can move it back in loadMiddleware if you think it's better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point is to guarantee logger argument is replaced only when middlewares are registered. After this split, nothing guarantees it anymore and one can call these separately. Perhaps old name was better then, since useMiddlewares doesn't imply it only loads them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests guarantee that 🙂 But I understand the need from a code point of view, I moved it back into useMiddlewaresIfAvailable (I renamed the method too).

if (interface_exists(Middleware::class)) {
$container
->getDefinition('doctrine.dbal.logger')
->replaceArgument(0, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This disables logging even when it's enabled, right? Basically it will block release of 2.6 once we merge this, until you finish follow-up PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It disables logging but the logging is now done by the logging middleware, see Resources/config/middlewares.xml in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's just abstract middleware

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but abstract middlewares are registered for each connection by MiddlewarePass 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. And which part disables middleware when $config['logging'] is false?

Copy link
Contributor Author

@l-vo l-vo Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I missed this case, to allow to handle this case, I did some other changes:

  • Middleware can now be registered only for chosen connections (with a tag attribute)
  • An attribute AsMiddleware has been added

@l-vo l-vo force-pushed the allow_userland_middlewares branch 5 times, most recently from bd84248 to 171f816 Compare February 17, 2022 21:39
Copy link
Member

@ostrolucky ostrolucky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, I think there are only minor comments

DependencyInjection/Compiler/MiddlewaresPass.php Outdated Show resolved Hide resolved
DependencyInjection/DoctrineExtension.php Outdated Show resolved Hide resolved
Tests/DependencyInjection/Compiler/MiddlewarePassTest.php Outdated Show resolved Hide resolved
Tests/DependencyInjection/Compiler/MiddlewarePassTest.php Outdated Show resolved Hide resolved
Tests/DependencyInjection/Compiler/MiddlewarePassTest.php Outdated Show resolved Hide resolved
Tests/DependencyInjection/Compiler/MiddlewarePassTest.php Outdated Show resolved Hide resolved
Tests/DependencyInjection/Compiler/MiddlewarePassTest.php Outdated Show resolved Hide resolved
Tests/DependencyInjection/Compiler/MiddlewarePassTest.php Outdated Show resolved Hide resolved
DependencyInjection/DoctrineExtension.php Outdated Show resolved Hide resolved
@l-vo l-vo force-pushed the allow_userland_middlewares branch 2 times, most recently from 5bd9712 to ed22040 Compare February 20, 2022 14:03
@l-vo
Copy link
Contributor Author

l-vo commented Feb 20, 2022

@ostrolucky thank you, all comments are addressed.

@ostrolucky
Copy link
Member

LGTM, but would be nice if community properly tested this. I didn't try it in a project

@ostrolucky ostrolucky merged commit 89b7ed6 into doctrine:2.6.x Feb 22, 2022
@l-vo l-vo deleted the allow_userland_middlewares branch February 22, 2022 19:09
fabpot added a commit to symfony/symfony that referenced this pull request Mar 25, 2022
…Logger (l-vo)

This PR was merged into the 5.4 branch.

Discussion
----------

[DoctrineBridge] Allow to use a middleware instead of DbalLogger

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       |  Step toward the fix of doctrine/DoctrineBundle#1431  (mentioned too in #44313 and #44495)
| License       | MIT
| Doc PR        |

The SqlLogger that is used in doctrine bridge and doctrine bundle has been deprecated and replaced by a system of Middleware.

A work has started on Doctrine bundle with doctrine/DoctrineBundle#1456 and doctrine/DoctrineBundle#1472

This PR suggest to add a middleware thats covers what was previously done by `DbalLogger` and `DebugStack`.

Another PR will follow in DoctrineBundle for the integration.

Commits
-------

20d0806 Allow to use a middleware instead of DbalLogger
@greg0ire
Copy link
Member

@l-vo sorry to comment about this more than 1 year later, is there documentation on this somewhere?

@l-vo
Copy link
Contributor Author

l-vo commented Apr 19, 2023

@greg0ire yes you're right, I forgot to document the configuration. I'm going to do that soon.

@greg0ire
Copy link
Member

Great! Thanks in advance!

@l-vo
Copy link
Contributor Author

l-vo commented May 3, 2023

@greg0ire done in #1653 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants