[DPE-10882] feat(database): own the client relation events, drop the endpoint bridge (4/7) - #219
Open
marceloneppel wants to merge 3 commits into
Open
[DPE-10882] feat(database): own the client relation events, drop the endpoint bridge (4/7)#219marceloneppel wants to merge 3 commits into
marceloneppel wants to merge 3 commits into
Conversation
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
marceloneppel
force-pushed
the
feat/02-db-endpoints
branch
from
August 20, 2026 12:33
25e7a83 to
06107b4
Compare
marceloneppel
force-pushed
the
feat/02-db-events
branch
from
August 20, 2026 12:33
1ceb16f to
f9415e6
Compare
marceloneppel
force-pushed
the
feat/02-db-endpoints
branch
from
August 20, 2026 15:02
06107b4 to
8f45680
Compare
marceloneppel
force-pushed
the
feat/02-db-events
branch
from
August 20, 2026 15:02
f9415e6 to
a1dbc16
Compare
marceloneppel
force-pushed
the
feat/02-db-endpoints
branch
from
August 20, 2026 17:10
8f45680 to
e0bba4f
Compare
marceloneppel
force-pushed
the
feat/02-db-events
branch
from
August 20, 2026 17:10
a1dbc16 to
6a439a6
Compare
…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>
K8s 16/edge called update_endpoints() with no event, republishing endpoints to every relation from the request handler; scoping the call to the requesting relation matched VM only and left sibling relations unrefreshed whenever update_config early-exits. Keep the per-substrate call shape, and give each substrate back its own defer log wording. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
The abstract charm claimed set_unit_status is permanent because charm_refresh is not a migration target, contradicting the manager's comment on the same seam. The refresh logic does migrate into the library in its own phase (as the Mongo and OpenSearch kernels already did), so the seam is interim and both comments now say so. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
marceloneppel
force-pushed
the
feat/02-db-endpoints
branch
from
August 20, 2026 19:45
e0bba4f to
64e4163
Compare
marceloneppel
force-pushed
the
feat/02-db-events
branch
from
August 20, 2026 19:45
6a439a6 to
3231c5f
Compare
marceloneppel
marked this pull request as ready for review
August 20, 2026 20:53
marceloneppel
requested review from
carlcsaposs-canonical,
dragomirp,
juju-charm-bot and
taurus-forever
and removed request for
a team
August 20, 2026 20:53
akram09
approved these changes
Aug 21, 2026
| self.relation_name = relation_name | ||
|
|
||
| self.database_provides = DatabaseProvides(charm, relation_name=relation_name) | ||
| self.manager = DatabaseManager( |
Contributor
There was a problem hiding this comment.
Why it is initialized here? shouldn't be in the Charm ?
dragomirp
approved these changes
Aug 21, 2026
taurus-forever
approved these changes
Aug 23, 2026
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 may be redundant (need to validate in https://warthogs.atlassian.net/browse/DPE-10890) — the provider library emitsdatabase_requestedon the leader only, andupdate_endpointspublishes the same values immediately after. Each substrate also keeps its own defer log wording.One smaller divergence is deliberate: the endpoint refresh after a request narrows to the requesting relation on VM, while K8s keeps its whole-relation refresh — each exactly as its charm had it.
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.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 routes status writes through thecharm_refreshpriority gate and stays until the refresh logic itself migrates into the library; the other two are reclaimed by later phases.Follow-up lib PRs:
Wiring up at:
Checklist