[DPE-10841] feat(database): own the client relation events, drop the endpoint bridge (4/7) - #219
Draft
marceloneppel wants to merge 1 commit into
Draft
[DPE-10841] feat(database): own the client relation events, drop the endpoint bridge (4/7)#219marceloneppel wants to merge 1 commit into
marceloneppel wants to merge 1 commit into
Conversation
…bridge (4/6) Wires the client relation into the library: the handler owns DatabaseProvides, observes database-requested, relation-departed and relation-broken, and constructor-injects the interface into the manager the way the TLS handler already injects its certificate requirers. Each handler keeps its readiness guard and its work in the same observer. defer() is per-observer, so a guard split across observers would let a deferred action retry alone against state its guard never re-checked. With endpoint publishing lib-side, the config manager calls the database manager directly and the refresh_endpoints charm bridge goes away, as does the injected user hash, which is now derived from the same relation data the map is. The charms gain bridges for the refresh-aware status write, the config re-render and the substrate's primary lookup, all of which their own migration phases reclaim. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
marceloneppel
force-pushed
the
feat/02-db-endpoints
branch
from
August 18, 2026 18:23
6f88191 to
25e7a83
Compare
marceloneppel
force-pushed
the
feat/02-db-events
branch
from
August 18, 2026 18:23
12e7928 to
1ceb16f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
The manager from PRs 1–3 has no observers, and
ConfigManagerstill reaches back into the charm to refresh endpoints and is still handed a user hash the charm derives from provider state.Solution
Adds
events/database.py, which ownsDatabaseProvides, observesdatabase-requested,relation-departedandrelation-broken, and constructor-injects the interface intoDatabaseManager— the same shape as the TLS handler and its certificate requirers.Each handler keeps its readiness guard and its work in one observer.
defer()is per-observer, so splitting a guard from the action it protects lets a deferred action retry alone against state its guard never re-checked. That is the same failure mode as the TLS reload race in canonical/postgresql-k8s-operator#1618.The two substrates' guards differ and both are kept. A request waits on the cluster being initialised plus, on VM, a started member and a reachable primary; on K8s,
primary_endpoint_ready. A removal waits on the same predicate on VM, but on K8s settles for a started member. The K8s handler also wrote the primary Service endpoint, URI and TLS fields inline beforeupdate_endpointsran; that write is preserved so databag write ordering is unchanged, though it is redundant — the provider library emitsdatabase_requestedon the leader only, andupdate_endpointspublishes the same values immediately after.Two smaller divergences are deliberate: the endpoint refresh after a request narrows to the requesting relation (both charms refreshed every relation, and the no-argument refresh inside
update_configstill rewrites all of them in the same hook), and a VM leader missing from the peer data yields:5432rather than the charm'sNone:5432for the read-write endpoint — a broken-input corner either way.One parity gap is fixed up-stack rather than here: the
requested_entity_secret_contentread needs theModelErrorguard the charms wrapped their whole_get_credentialsin, because the vendored property raises while a cross-model grant is still pending. Adding the guard to this branch would force a rebase of the three test branches above, so it rides 7/7.Seam changes:
ConfigManagertakes theDatabaseManagerand callsupdate_endpoints()itself. Therefresh_endpointscharm bridge is deleted.update_config'suser_hashparameter is gone; the manager derives it from the same relation data the user-databases map comes from.relations_user_databases_mapstays injected — its computation lives incharm.pyand diverges between substrates, so it belongs to the core event-loop phase.AbstractPostgreSQLCharmgainsset_unit_status,update_configandprimary_endpoint. The first is permanent (it gates status writes oncharm_refreshpriority, andcharm_refreshis not a migration target); the other two are reclaimed by later phases.Handler tests are in PR 7.
tests/unit/test_config_manager.pyis updated here because the constructor andupdate_configsignature change in this PR.Stacked on 3/7. Next: 5/7.
Checklist