Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 7, 2019
Merged

[Messenger] DoctrineTransport: ensure auto setup is only done once #32308

merged 1 commit into from
Oct 7, 2019

Conversation

bendavies
Copy link
Contributor

@bendavies bendavies commented Jul 1, 2019

Q A
Branch? 4.3
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #...
License MIT
Doc PR symfony/symfony-docs#...

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.

@bendavies bendavies changed the title ensure auto setup once only done once [Messenger] DoctrineTransport: ensure auto setup once only done once Jul 1, 2019
@bendavies bendavies changed the title [Messenger] DoctrineTransport: ensure auto setup once only done once [Messenger] DoctrineTransport: ensure auto setup is only done once Jul 1, 2019
@@ -134,7 +136,7 @@ public function send(string $body, array $headers, int $delay = 0): string

public function get(): ?array
{
if ($this->configuration['auto_setup']) {
if ($this->autoSetup) {
Copy link
Member

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 failure

Copy link
Member

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. The truly 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:

  1. Don't do any "setup" here - so, make it like all the other methods
  2. In executeQuery(), tweak the logic a little bit inside the } catch (TableNotFoundException $e) {. Specifically, if we are in a transaction, immediately re-throw the TableNotFoundException. Otherwise, do the current logic of setting up and trying again.
  3. In get(), in the catch(), if the exception is a TableNotFoundException, rollback() (like normal), but then setup and then try the entire get() method again (probably we'll need to extra the majority of get() - the part inside the try to 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.

Copy link
Contributor

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 first get for each worker (if the auto_setup is configured to true)

Copy link
Member

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 :)

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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?

@weaverryan
Copy link
Member

@vincenttouzet I'd like your eyes on this too :)

Copy link
Contributor

@Tobion Tobion left a comment

Choose a reason for hiding this comment

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

@mareksuscak
Copy link

mareksuscak commented Sep 23, 2019

I was wondering if this PR fixes an issue I'm seeing here. If so, is there a workaround? I've disabled auto-setup, yet I'm still seeing tons and tons of queries. They're slamming our database.

EDIT: Yeah, it did work, after all.

@bendavies bendavies requested a review from stof September 25, 2019 11:52
Copy link
Member

@weaverryan weaverryan left a 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 in executeQuery() in all cases. And for the one "transaction" case in get(), 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.

Copy link
Member

@weaverryan weaverryan left a 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 failure does look related

@bendavies
Copy link
Contributor Author

fixed?

@bendavies
Copy link
Contributor Author

failure unrelated.

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

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

Looks good!

@weaverryan
Copy link
Member

This should be ready to go!

@fabpot
Copy link
Member

fabpot commented Oct 7, 2019

Thank you @bendavies.

fabpot added a commit that referenced this pull request Oct 7, 2019
…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     <!-- see https://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
@fabpot fabpot merged commit 0241402 into symfony:4.3 Oct 7, 2019
@fabpot fabpot mentioned this pull request Oct 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.