It is a good question to ask. Certainly Charms can currently already define
limit:1 in their metadata.yaml for a given interface if they only support 0 or 1 relations on a given endpoint. (eg, It generally doesn’t make a lot of sense to have multiple databases for an app, as it only has one central authority.)
It isn’t something that we have designed the Operator Framework around, as you don’t register for events for just one relation-id, but for all events on that relation. (eg if you do
observe(charm.on[db].relation_changed) you will get events for any relation-id). So while you can give it the context of a single relation, you would need to do the delegation in other code (or have the event handler do
if event.relation.id != self.relation.id: return.)
I can see an advantage of it, as it does make writing the component easier. (In fact, a lot of components that are actually written will only support a single relation, and will just go into some sort of Blocked condition if they have >1 relation on a given endpoint.)
If we do want to drive further, we would certainly want to model that in the framework. Being able to receive events on a relation-id rather than on a relation endpoint.
The main problem is things like ‘joined’ signify that there is a new relation being established. And unless you have something that does listen to db_relation_joined, it never has a chance to instantiate the new relation handler. Obviously you can do that in the charm code. Certainly a pattern could be that only your Charm ever receives events, but your components just take dicts/etc. The pattern that we’re currently driving is that a component handles all aspects of a given Relation, and registers and receives events on that relation, and then drives new events for the Charm. (eg a postgresql or mysql component has a
database_changed event which is distilled from the
You could alternatively have one component which you provide that handles
relation-joined and proxies the rest of the data for
relation-changed et al to other classes.