Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Messenger] DoctrineTransport: ensure auto setup is only done once#32308
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
[Messenger] DoctrineTransport: ensure auto setup is only done once#32308
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
| publicfunctionget(): ?array | ||
| { | ||
| if ($this->configuration['auto_setup']) { | ||
| if ($this->autoSetup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
maybe we should add a comment here:
// manually try to setup because the transaction below prevents setup on failureThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Hmm, or I have a different idea. Thetruly desired behavior is to only setup once we know that the table is actually missing. That's how it's done on every other method... we just can't do it here because of the transaction.
Could we instead do this:
- Don't do any "setup" here - so, make it like all the other methods
- In
executeQuery(), tweak the logic a little bit inside the} catch (TableNotFoundException $e) {. Specifically, if we are in a transaction, immediately re-throw theTableNotFoundException. Otherwise, do the current logic of setting up and trying again. - In
get(), in thecatch(), if the exception is aTableNotFoundException, rollback() (like normal), but then setup andthen try the entireget()method again (probably we'll need to extra the majority ofget()- the part inside thetryto a private function so it can be called both in the try and again in the catch).
@vincenttouzet WDYT? By the way, see#32712 where a related conversation (for different reasons) is happening around AMQP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@weaverryan I like the idea. This way the setup would only be run once for ALL workers. For now it runs at the firstget for each worker (if theauto_setup is configured to true)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@bendavies we have some consensus - could you try to put this into your PR? thx :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@weaverryan sounds good. bit busy this week but can take a look after that. if you want to go ahead without me, feel free.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I agree that we should be able to implement this like ryan suggested.@bendavies do you have time to finish this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Forgot about this. I'll look to do it next week.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@weaverryan better late than never. take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
be careful about doing a setup inside a transaction. In some platforms (MySQL being one of them), doing a DDL statement in a transaction will commit the existing transaction and start a new one after, so a rollback later will rollback only until your DDL statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@stof it seems that is explicitly checked for now and handled, isn't it?
Uh oh!
There was an error while loading.Please reload this page.
weaverryan commentedJul 1, 2019
@vincenttouzet I'd like your eyes on this too :) |
Tobion left a comment• edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
mareksuscak commentedSep 23, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
weaverryan left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This looks great - we setup lazily inexecuteQuery() in all cases. And for the one "transaction" case inget(), we handle it manually.
The Connection was only ever written the "incorrect" way because we were imitating the logic from Amqp, where the connection setup is cheap.
weaverryan left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Hmm, but AppVeyor test failuredoes look related
bendavies commentedSep 27, 2019
fixed? |
bendavies commentedSep 27, 2019
failure unrelated. |
weaverryan left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Looks good!
src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.phpShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
weaverryan commentedOct 7, 2019
This should be ready to go! |
fabpot commentedOct 7, 2019
Thank you@bendavies. |
…one once (bendavies)This PR was squashed before being merged into the 4.3 branch (closes#32308).Discussion----------[Messenger] DoctrineTransport: ensure auto setup is only done once| Q | A| ------------- | ---| Branch? | 4.3| Bug fix? | yes| New feature? | no <!-- please update src/**/CHANGELOG.md files -->| BC breaks? | no <!-- seehttps://symfony.com/bc -->| Deprecations? |no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->| Tests pass? | yes <!-- please add some, will be required by reviewers -->| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->| License | MIT| Doc PR | symfony/symfony-docs#... <!-- required for new features -->Setup is done for every invocation of `get`, `find`, and `findAll`.For `get`, this causes message consumption to be very slow, as slow as 1 message per second on my moderately sized schema, because a schema diff is done in `setup` every `get`.I'm not sure what the desired behaviour is here, but it seems like we should try performing a query, fail once, `setup`, and retry. This will the same approach taken by the PDO Cache.However, we still need auto setup in `get`, as `get` starts a transaction, so the auto setup in `executeQuery` won't be called.Further more, the same problem seems to exist for the AMPQ Transport, but the performance impact should be less there, but i have not tried.Commits-------0241402 [Messenger] DoctrineTransport: ensure auto setup is only done once
Uh oh!
There was an error while loading.Please reload this page.
Setup is done for every invocation of
get,find, andfindAll.For
get, this causes message consumption to be very slow, as slow as 1 message per second on my moderately sized schema, because a schema diff is done insetupeveryget.I'm not sure what the desired behaviour is here, but it seems like we should try performing a query, fail once,
setup, and retry. This will the same approach taken by the PDO Cache.However, we still need auto setup in
get, asgetstarts a transaction, so the auto setup inexecuteQuerywon't be called.Further more, the same problem seems to exist for the AMPQ Transport, but the performance impact should be less there, but i have not tried.