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

SqlClient pool migration #46015

Merged
merged 6 commits into from
Feb 17, 2025
Merged

SqlClient pool migration #46015

merged 6 commits into from
Feb 17, 2025

Conversation

tsegismont
Copy link
Contributor

@tsegismont tsegismont commented Jan 31, 2025

PgPool and other vendor pool types are deprecated in Vert.x 4. In Vert.x 5, these types are going away.

This PR is an attempt to make the transition incremental. Instead of using PgPool and other vendor pool types as the basis for bean creation, we can use the Pool parent type.

In the recorder, the pool configurator now returns the parent Pool type.
Then, in the processor, new bean configurators are set up to support injection of the different pools:

  • bare pool
  • vendor pool
  • mutiny pool
  • mutiny vendor pool

Each commit can be reviewed individually.

Updated extensions:

  • Reactive Pg Client
  • Reactive MySQL Client
  • Reactive SqlServer Client
  • Reactive Oracle Client
  • Reactive DB2 Client

@tsegismont
Copy link
Contributor Author

tsegismont commented Jan 31, 2025

@cescoffier @gsmet @yrodiere @geoand @jponge would you mind taking a look at this draft PR?

There are a few things I would like to figure out before going on with other extensions.

DRY

This is maybe a dumb question.

In the processor there is now:

    private static final DotName VERTX_POOL = DotName.createSimple(Pool.class);
    private static final Type VERTX_POOL_TYPE = Type.create(VERTX_POOL, Type.Kind.CLASS);

Is it fine to put this somewhere in the reactive-datasource extension to avoid duplication?

Injection of vendor pool types

Should we have a warning message logged to the console when this happens?
In this case, how about adding the log instruction inside the body of the function defined in Recorder#vendorPool and Recorder#mutinyVendorPool?

Implications on Hibernate Reactive

Since both the raw and vendor types can still be injected, I don't believe Hibernate Reactive integration will be impacted.

Migration tooling

Do we share OpenRewrite rules somewhere? How about adding rules so that users can start migrating now?

Datasource Health Check filtering

ReactivePgDataSourcesHealthCheck still looks up for PgPool in Arc. I couldn't think about a solution for selecting pools bound to datasources having the correct db kind. Any ideas?

Mutiny types are not deprecated

Both io.vertx.mutiny.sqlclient.Pool and io.vertx.mutiny.pgclient.PgPool aren't deprecated, even though the corresponding Vert.x type are deprecated.

Shouldn't we fix this in Vert.x Mutiny bindings?

I would expect this to urge users to switch to parent pool types in their codebases.

@geoand
Copy link
Contributor

geoand commented Jan 31, 2025

Since both the raw and vendor types can still be injected, I don't believe Hibernate Reactive integration will be impacted.

cc @DavideD

Do we share OpenRewrite rules somewhere? How about adding rules so that users can start migrating now?

cc @gsmet

Is it fine to put this somewhere in the reactive-datasource extension to avoid duplication?

Sure, you can a ReactiveDataSourceDotNames class

Shouldn't we fix this in Vert.x Mutiny bindings?

cc @jponge

Copy link

github-actions bot commented Jan 31, 2025

🙈 The PR is closed and the preview is expired.

@jponge
Copy link
Member

jponge commented Jan 31, 2025

@tsegismont re Mutiny types are not deprecated yes it's something to be considered

@jponge
Copy link
Member

jponge commented Jan 31, 2025

Note that the Likely new bindings generator does honor deprecation annonations.

Copy link
Member

@yrodiere yrodiere left a comment

Choose a reason for hiding this comment

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

Hey,

Thanks, I added a few comments below.

In the processor there is now:

    private static final DotName VERTX_POOL = DotName.createSimple(Pool.class);
    private static final Type VERTX_POOL_TYPE = Type.create(VERTX_POOL, Type.Kind.CLASS);

Is it fine to put this somewhere in the reactive-datasource extension to avoid duplication?

Not only is it fine, it's great! Every time I touch this code I think "man, so much duplication..."

Injection of vendor pool types

Should we have a warning message logged to the console when this happens? In this case, how about adding the log instruction inside the body of the function defined in Recorder#vendorPool and Recorder#mutinyVendorPool?

I think it's probably enough if the types themselves are deprecated?

But if you want warnings at Quarkus build time or at bootstrap, maybe we should ask @Ladicek / @mkouba / @manovotn. What is the recommended way to mark a bean as "dangerous" and/or have warnings be logged when it's injected/retrieved?

Implications on Hibernate Reactive

Since both the raw and vendor types can still be injected, I don't believe Hibernate Reactive integration will be impacted.

I think Hibernate Reactive uses Pool already:

private void registerVertxAndPool(String persistenceUnitName,
RuntimeSettings runtimeSettings,
PreconfiguredReactiveServiceRegistryBuilder serviceRegistry) {
if (runtimeSettings.isConfigured(AvailableSettings.URL)) {
// the pool has been defined in the persistence unit, we can bail out
return;
}
// for now, we only support one pool but this will change
String datasourceName = DataSourceUtil.DEFAULT_DATASOURCE_NAME;
Pool pool;
try {
InjectableInstance<Pool> poolHandle = Arc.container().select(Pool.class);
if (!poolHandle.isResolvable()) {
throw new IllegalStateException("No pool has been defined for persistence unit " + persistenceUnitName);
}
// ClientProxy.unwrap is necessary to trigger exceptions on inactive datasources
pool = ClientProxy.unwrap(poolHandle.get());
} catch (RuntimeException e) {
throw PersistenceUnitUtil.unableToFindDataSource(persistenceUnitName, datasourceName, e);
}

Migration tooling

Do we share OpenRewrite rules somewhere? How about adding rules so that users can start migrating now?

https://github.com/quarkusio/quarkus-updates/

Datasource Health Check filtering

ReactivePgDataSourcesHealthCheck still looks up for PgPool in Arc. I couldn't think about a solution for selecting pools bound to datasources having the correct db kind. Any ideas?

I'd expect something in the (build-time) processor to take note of which datasources are PostgreSQL datasources, create a List<String> with the names, and have it passed to ReactivePgDataSourcesHealthCheck somehow, so it'll retrieve those datasources and those only.

Mutiny types are not deprecated

Both io.vertx.mutiny.sqlclient.Pool and io.vertx.mutiny.pgclient.PgPool aren't deprecated, even though the corresponding Vert.x type are deprecated.

Shouldn't we fix this in Vert.x Mutiny bindings?

I would expect this to urge users to switch to parent pool types in their codebases.

+1

@Ladicek
Copy link
Contributor

Ladicek commented Feb 3, 2025

 private static final Type VERTX_POOL_TYPE = Type.create(VERTX_POOL, Type.Kind.CLASS);

Just for the record, you can simplify that to ClassType.create(VERTX_POOL).

But if you want warnings at Quarkus build time or at bootstrap, maybe we should ask @Ladicek / @mkouba / @manovotn. What is the recommended way to mark a bean as "dangerous" and/or have warnings be logged when it's injected/retrieved?

I don't think we have anything like that. How would we detect that? Application classes would trigger the warning, but non-application classes wouldn't? Would we detect that on beans or on bean types? (As in, some bean types would be OK to use, while others would be "dangerous".)

@DavideD
Copy link
Contributor

DavideD commented Feb 3, 2025

Since both the raw and vendor types can still be injected, I don't believe Hibernate Reactive integration will be impacted.

cc @DavideD

Hibernate Reactive doesn't and shouldn't use PgPool, because we support other databases.

@manovotn
Copy link
Contributor

manovotn commented Feb 3, 2025

 private static final Type VERTX_POOL_TYPE = Type.create(VERTX_POOL, Type.Kind.CLASS);

Just for the record, you can simplify that to ClassType.create(VERTX_POOL).

But if you want warnings at Quarkus build time or at bootstrap, maybe we should ask @Ladicek / @mkouba / @manovotn. What is the recommended way to mark a bean as "dangerous" and/or have warnings be logged when it's injected/retrieved?

I don't think we have anything like that. How would we detect that? Application classes would trigger the warning, but non-application classes wouldn't? Would we detect that on beans or on bean types? (As in, some bean types would be OK to use, while others would be "dangerous".)

Ladislav is right, there is no facility for that.
But if you are the bean "owner", you can always add some logging to calls such as @PostConstruct which would be invoked any time that bean is created. If it's a synth. bean, you can add it to its create callback with the same result.

Only other thing I can think of is monitoring injection points in user app and then logging; I think we had some build item with all injection points? This of course won't detect/include any dynamic resolution (Instance<T>, Arc.container().select(), CDI.current()).

@jponge
Copy link
Member

jponge commented Feb 4, 2025

FYI I'm doing a patch release soon of the Vert.x Mutiny bindings, and the fix for deprecation will be in (+ using the relocated Jandex plugin that for some reason we hadn't migrated to)

@tsegismont
Copy link
Contributor Author

tsegismont commented Feb 4, 2025

Thanks everyone for your comments!

Not only is it fine, it's great! Every time I touch this code I think "man, so much duplication..."

@yrodiere I have the same feeling. Perhaps it's better to address this in a separate PR though.

I'd expect something in the (build-time) processor to take note of which datasources are PostgreSQL datasources, create a List<String> with the names, and have it passed to ReactivePgDataSourcesHealthCheck somehow, so it'll retrieve those datasources and those only.

@yrodiere thanks, I'll try that.

Just for the record, you can simplify that to ClassType.create(VERTX_POOL).

@Ladicek thanks for the tip

Ladislav is right, there is no facility for that.
But if you are the bean "owner", you can always add some logging to calls such as @PostConstruct which would be invoked any time that bean is created. If it's a synth. bean, you can add it to its create callback with the same result.

@manovotn @Ladicek thanks. Since the Mutiny Vert.x bindings generator will soon be able to mark generated types as deprecated when needed, I won't pursue in this direction.

FYI I'm doing a patch release soon of the Vert.x Mutiny bindings, and the fix for deprecation will be in (+ using the relocated Jandex plugin that for some reason we hadn't migrated to)

Thank you @jponge !

@tsegismont tsegismont force-pushed the sql-pool-migration branch 3 times, most recently from 523c029 to a68ae4f Compare February 5, 2025 16:01
@tsegismont
Copy link
Contributor Author

@yrodiere PTAL, in particular to the commit that get rids of vendor pool lookup in ReactivePgDataSourcesHealthCheck.

@mkouba
Copy link
Contributor

mkouba commented Feb 7, 2025

Only other thing I can think of is monitoring injection points in user app and then logging; I think we had some build item with all injection points? This of course won't detect/include any dynamic resolution (Instance<T>, Arc.container().select(), CDI.current()).

Yes, there's the BeanDiscoveryFinishedBuildItem, and the BeanDiscoveryFinishedBuildItem#getInjectionPoints() method returns all injection points declared on class beans. There's also SynthesisFinishedBuildItem which also includes synthetic injection points.

@tsegismont tsegismont force-pushed the sql-pool-migration branch 3 times, most recently from b1c5e53 to 21ab674 Compare February 13, 2025 10:15
@tsegismont tsegismont marked this pull request as ready for review February 13, 2025 16:01
@tsegismont tsegismont force-pushed the sql-pool-migration branch 2 times, most recently from b922f31 to e39cd82 Compare February 13, 2025 16:03
@tsegismont
Copy link
Contributor Author

@gsmet @yrodiere @geoand can you please take a look?

I thought about addressing code duplication in SQL Client extensions in a follow-up PR, is that fine with you?

@tsegismont
Copy link
Contributor Author

@geoand ^^

@geoand
Copy link
Contributor

geoand commented Feb 13, 2025

@tsegismont that's exactly what I had in mind!

This comment has been minimized.

Deprecate PgPoolBuildItem for removal

Refactor PgPoolCreator producer and processor

The PgPoolCreator change will not break existing implementations.
Indeed, the contract now uses the parent Pool type, so returning PgPool is fine.

In the recorder, the pool configurator now returns the parent Pool type.
Then, in the processor, new bean configurators are set up to support injection of the different pools:

- bare pool
- vendor pool
- mutiny pool
- mutiny vendor pool

Also, we can get rid of vendor pool lookup in ReactivePgDataSourcesHealthCheck.
The PgPoolSupport bean indicates which datasource names correspond to a PgPool that has actually been created.
It allows to filter Pool bean instances in ReactivePgDataSourcesHealthCheck.
Apply changes from previous commits to the Reactive MySQL Client extension
Apply changes from previous commits to the Reactive MSSQL Client extension
Apply changes from previous commits to the Reactive Oracle Client extension
Apply changes from previous commits to the Reactive DB2 Client extension

This comment has been minimized.

@tsegismont
Copy link
Contributor Author

@tsegismont that's exactly what I had in mind!

@geoand done, and squashed commits

@geoand
Copy link
Contributor

geoand commented Feb 13, 2025

Thanks! I'll have another look tomorrow

Copy link

quarkus-bot bot commented Feb 13, 2025

Status for workflow Quarkus Documentation CI

This is the status report for running Quarkus Documentation CI on commit a07d65d.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

Warning

There are other workflow runs running, you probably need to wait for their status before merging.

Copy link

quarkus-bot bot commented Feb 13, 2025

Status for workflow Quarkus CI

This is the status report for running Quarkus CI on commit a07d65d.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

You can consult the Develocity build scans.

Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

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

Thanks!

Copy link
Member

@xstefank xstefank left a comment

Choose a reason for hiding this comment

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

LGTM

@tsegismont tsegismont removed the request for review from gsmet February 14, 2025 09:07
@tsegismont
Copy link
Contributor Author

Thank you guys. Can one of you please merge the PR?

@geoand
Copy link
Contributor

geoand commented Feb 14, 2025

I'll want to give @gsmet a chance to review if he wants to

@gsmet
Copy link
Member

gsmet commented Feb 17, 2025

Sorry, late to the party, will have a look this afternoon and hopefully merge it.

@gsmet gsmet merged commit 98942f6 into quarkusio:main Feb 17, 2025
34 checks passed
@quarkus-bot quarkus-bot bot added this to the 3.21 - main milestone Feb 17, 2025
@gsmet
Copy link
Member

gsmet commented Feb 17, 2025

I merged it for 3.21.

A few additional things to do:

@tsegismont
Copy link
Contributor Author

Thank you @gsmet

Here's an update for the migration guide:

== Datasources

=== Generic pool class for reactive datasources

In previous versions of Quarkus, there were vendor-specific pool classes for each reactive datasource type:

* `io.vertx.mutiny.db2client.DB2Pool`, for IBM Db2
* `io.vertx.mutiny.mysqlclient.MySQLPool`, for MariaDB/MySQL
* `io.vertx.mutiny.mssqlclient.MSSQLPool`, for Microsoft SQL Server
* `io.vertx.mutiny.oracleclient.OraclePool`, for Oracle
* `io.vertx.mutiny.pgclient.PgPool`, for PostgreSQL.

Starting with this version of Quarkus, you should use the generic pool class, `io.vertx.mutiny.sqlclient.Pool`, regardless of the database vendor.

Regarding recipes, changing imports should be fine for all "regular" users, i.e. users injecting a managed reactive pool.
Advanced users (e.g. creating pools manually) might see their code broken in some cases. The impact should be limited though, because you usually don't create pools in each and every class.
Is that acceptable?

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.

10 participants