You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 47fa33f
Browse filesBrowse the repository at this point in the historyBrowse files
Load the Conductor client through a ServiceLoader provider (#626)
DBOS finds its Conductor client through `java.util.ServiceLoader`
instead of constructing it directly. This is the hook that lets the
client move out of this SDK into a separate, closed-source artifact,
`dev.dbos:transact-enterprise`, under the DBOS Conductor Software
License. Python and TypeScript already split Conductor out this way
(dbos-transact-py#873, dbos-transact-ts#1394), and Go did the same in
dbos-transact-golang#498.
Nothing changes for users yet. Until the client moves, this artifact
registers its own client as the provider. The move ships in the same
release as this change.
## Changes
**1. A provider interface, in `dev.dbos.transact.conductor`.**
- `ConductorProvider.create(executor, systemDatabase, options)` builds a
`ConductorConnection`, which has `start()` and `stop()`. Giving the
connection its own stop lets shutdown disconnect Conductor at a point
DBOS chooses.
- `ConductorOptions` carries the key, the app name and the domain. A
null app name means the executor's name, and a null domain means DBOS
Conductor's public endpoint.
- `Conductor` implements `ConductorConnection`.
`BundledConductorProvider` wraps it and is registered in
`META-INF/services/dev.dbos.transact.conductor.ConductorProvider`. The
registration and the class go away when the client moves.
**2. The executor requires exactly one provider when Conductor is
configured.**
- When a Conductor key is set in `DBOSConfig` or `DBOS__CLOUD=true`, the
`DBOSExecutor` constructor resolves the provider, so `launch()` fails
before migrations or anything else run. As in Python, DBOS Cloud
requires the provider whether or not the `DBOS__CONDUCTOR_*` variables
are set.
- **No provider:** the error names the artifact to add. For a core
release it gives the exact version
(`dev.dbos:transact-enterprise:1.3.0`). Preview builds are numbered by
commits in each repo, so for a preview it names the minor instead.
- **More than one provider** is an error naming them.
- **A provider whose constructor throws**, e.g. on a version mismatch,
fails launch with ServiceLoader's message plus the cause's.
- Providers are looked up in the thread context class loader and in the
one that loaded DBOS. A provider deployed beside the application is then
found even when DBOS is a shared library, as in a servlet container. A
provider visible through both loaders counts once.
**3. The client is built early and started late.** `start()` creates the
connection right after the system database opens, before queues, the
scheduler or lifecycle listeners start. It starts the connection at the
end of launch, as before. The provider is now another artifact's code,
so if it throws, launch fails with nothing else running. `stop()` is
documented as called even when launch failed before `start()`;
`Conductor.stop()` already handles that.
## Tests
`ConductorProvidersTest`:
- The bundled provider is found, including through a context class
loader that delegates to DBOS's own loader, where it must count once.
- Selection returns the only provider, rejects two, and gives the
release and preview forms of the missing-provider message.
The path where a provider's constructor throws has no test here. A
failing provider registered for tests would be found by every other test
that launches with Conductor. The enterprise artifact's own tests
exercise it.
Run locally: `ConductorProvidersTest`, `ConductorTest`, `ConfigTest`,
`ConfigEnvTest` (151 tests), plus `spotlessCheck`, `compileTestJava` and
`javadoc`. The full suite has not been run locally; this PR's CI run is
that pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
0 commit comments