Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.6k
[Messenger] Add support for PostgreSQL LISTEN/NOTIFY#35485
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
Uh oh!
There was an error while loading.Please reload this page.
Conversation
0171724
to5363561
Comparesrc/Symfony/Component/Messenger/Transport/Doctrine/Connection.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
dunglas commentedJan 27, 2020 • 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.
An alternative implementation is to use a trigger instead of calling For the record, I first used Edit: implementation added in5207f51 |
51fc6ee
to5207f51
Comparesrc/Symfony/Component/Messenger/Transport/Doctrine/Connection.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
@@ -35,6 +35,9 @@ class Connection | |||
'queue_name' => 'default', | |||
'redeliver_timeout' => 3600, | |||
'auto_setup' => true, | |||
'pgsql_get_notify' => false, |
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 should probably be its own transport, not mixing PostgreSQL-specifics with DBAL abstractions
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 had the same feeling in the beginning, but it will require to duplicate most of the code of this transport. So I'm not sure that it is worth it from a maintenance point of view.
Now that the implementation is less intrusive than it was, I'll check if the PostgreSQL related code can be moved to a decorator.
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.
Yeah, but that's not a big deal: more problematic is having generic SQL and PGSQL mixed within the same service, activated conditionally.
If the "enable norify" logic deals to a completely dedicated adapter, fixing specific bugs and maintenance becomes much easier, and so will debugging too.
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 isolated the PostgresSQL-specific code in a dedicated class, it's a bit cleaner, and while far from being perfect I think it will be good enough for now at least.
src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
@@ -227,6 +270,28 @@ public function setup(): void | |||
$this->driverConnection->getConfiguration()->setFilterSchemaAssetsExpression($assetFilter); | |||
} | |||
if ($this->usePgsqlNotify) { | |||
$sql = sprintf(<<<'SQL' |
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.
wrap in begin...commit?
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.
What would be the benefit?
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.
isexec
transactional? you want both statements to fail or both to succeed.
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'm not sure,pg_query
is transnational, but I cannot find the information for exec.
a131f83
to2be2850
CompareThere 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.
with minor comment
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.phpShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
a32d12f
tob976720
CompareThere 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.
LGTM, minor comment.
* file that was distributed with this source code. | ||
*/ | ||
declare(strict_types=1); |
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.
Should be removed
b976720
to01f33c3
CompareThank you@dunglas. |
This PR was merged into the 5.1-dev branch.Discussion----------[Messenger] Made final class really final| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | no| Deprecations? | no| Tickets || License | MIT| Doc PR |introduced in#35485 (so no BC break)Commits-------cd8a386 [Messenger] Made final class really final
This PR was merged into the 5.2 branch.Discussion----------[Messenger] Don't lock tables or start transactions| Q | A| ------------- | ---| Branch? | 5.2| Bug fix? | yes| New feature? | no| Deprecations? | no| Tickets || License | MIT| Doc PR |I was so sure my PR#40336 fixed the doctrine-messenger issue once and for all. But it had a very silent bug..This has been tricky to debug and find because the `PDO` behaves differently in PHP 7.4 compared to PHP 8.| Scenario | Command | Is executed in transaction | Method that calls `PostgreSqlConnection::getTriggerSql()` || --| -- | -- | -- || A | `messenger:setup-transports` | No | `setup()`| B| `doctrine:schema:create` | No | `getExtraSetupSqlForTable()`| C | `doctrine:migration:diff` | Yes by default, but it can be configured | `getExtraSetupSqlForTable()`PR#40055 fixed scenario C on PHP 8, but that also broke scenario B on PHP 7.4 and PHP 8.In PR#40336 I was wrong claiming:> We don't need COMMIT because the transaction will commit itself when we close the connection.The result was the we removed all the errors messages from the 3 scenarios. But scenario B will produce some SQL that is actually never committed. IE it will silently fail.I've been trying to figure out a good solution to how or when to start a transaction. I tried out@fbourigault [suggestion](#40336 (comment)) but that would be the same fix as#40055.---------------We need a transaction because the SQL includes a `LOCK TABLE`, however, I cannot see a strict need for it. This PR removes `LOCK TABLE` and all transaction juggling. It all seams to work.I would be happy to get thorough feedback on this PR so we can end the chapter of constantly adding bugs to this part of the component.@dunglas, you added `LOCK TABLE` in your initial version of this class in#35485, could you share some knowledge if this is a good or bad idea?Commits-------26061a1 Dont lock tables or start transactions
…upport (t-richard)This PR was squashed before being merged into the 5.2 branch.Discussion----------[Messenger] Add options for PostgreSQL LISTEN/NOTIFY support<!--If your pull request fixes a BUG, use the oldest maintained branch that containsthe bug (seehttps://symfony.com/releases for the list of maintained branches).If your pull request documents a NEW FEATURE, use the same Symfony branch wherethe feature was introduced (and `5.x` for features of unreleased versions).-->Documentssymfony/symfony#35485Closes#13039Commits-------55edd48 [Messenger] Add options for PostgreSQL LISTEN/NOTIFY support
Uh oh!
There was an error while loading.Please reload this page.
PostgreSQL comes with a builtin, performant, scalable and transactional pub/sub system called
LISTEN
/NOTIFY
.This PR allows to leverage this mechanism when using the Messenger component with Postgres.
When the Postgres is used, workers are notified in real-time when a message is dispatched.
This reduces the latency, and prevents the worker from executing useless SQL queries. Basically, it allows to switch from a polling-based approach to an event-based one.
This patch can be used with all existing installation of Messenger, as long as the underlying DBMS is Postgres. For many (most ?) projects, it allows to get the benefits of using a queue system such as RabbitMQ or Pulsar without having to introduce new services to monitor, replicate or upgrade.
If PostgreSQL is used,
LISTEN
/NOTIFY
is used automatically!That's all!
It's also possible to configure how long the worker must wait for new messages:
Then you can use start the workers with something like:
php bin/console messenger:consume --sleep=0
A demo app using this new feature is available in this repository:https://github.com/dunglas/demo-postgres-listen-notify
TODO: