quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.64k stars 2.64k forks source link

Datasources and persistence units with multiple "alternatives" listed at build time and selected at runtime #43656

Open yrodiere opened 1 day ago

yrodiere commented 1 day ago

Description

Problem statement

Some applications are built once, then distributed as a single binary (container image) and consumed/deployed by third-parties (users, customers) in various environments.

Such binaries need to work in multiple environments, and that means in particular that datasources and persistence units may need to work with different database kinds (e.g. Oracle and Postgres) depending on the deployment.

Currently, application developers have two solutions to address this:

  1. Declare multiple named persistence units and datasources, one per db-kind, make them active/inactive based on configuration profiles, have a custom PU/datasource CDI bean whose producer would have point to the active PU/datasource at runtime (see previous link).
  2. OR produce a "mutable jar" and have users/customers execute re-augmentation.

This has several downsides, however:

Proposal

We could expose more guided, better integrated ways of developing and deploying of such applications.


Related discussion: https://github.com/quarkusio/quarkus/discussions/42391

Implementation ideas

If we prefer solution 1 above (active/inactive)

We could provide a built-in concept of "alternatives" in the configuration of persistence units or datasources:

# Defining the default datasource with multiple alternatives.
# In practice the extension will generate one set of bytecode/bean per alternative,
# and use only one at runtime.
quarkus.datasource.jdbc.min-size=10
quarkus.datasource.alternatives."db2".db-kind=db2
quarkus.datasource.alternatives."db2".jdbc.max-size=60
quarkus.datasource.alternatives."postgresql".db-kind=postgresql
quarkus.datasource.alternatives."postgresql".jdbc.max-size=40

# Runtime profiles allow selecting an alternative
%db2.quarkus.datasource.selected-alternative=db2
%pg.quarkus.datasource.selected-alternative=postgresql

# Hibernate ORM consumes the default datasource,
# so it will automatically generate one alternative per datasource,
# and automatically select the correct one depending on the selected datasource at runtime
quarkus.hibernate-orm.database.generation=create

Main downsides:

  1. This still implies a distributed container image that contains all the alternatives -- but that's still the bare minimum to address such use case.
  2. This is very ad-hoc and requires per-extension implementation. We may provide some basic scaffoding in Quarkus (e.g. standard build items and helpers around configuration), but most of the heavy lifting will have to be implemented per extension.
  3. \

If we prefer solution 2 above (re-augmentation)

We could provide a simple process and technical solution that could be enabled simply (e.g. configuration flag) by application developers, and could by deployed simply by users/customers, triggering re-augmentation only once:

Main downsides:

  1. This is still quite complex.
  2. This still implies a slow first deployment.
  3. This still requires large distributed applications (they include deployment JARs).
  4. This still wouldn't support native builds.

cc @maxandersen @cescoffier @geoand @gsmet and anyone you think would be interested: your ideas could help here...

quarkus-bot[bot] commented 1 day ago

/cc @geoand (openshift), @iocanel (openshift)

FroMage commented 1 day ago

Solution 1 doesn't work with Panache

See for a possible solution for Panache 1 and repositories https://github.com/quarkusio/quarkus/issues/43341

Panache 2 should have something better, to also make this possible.