Restructure Microcluster packages
This started out small but after some changes I realized we have to properly hide structs behind interfaces to not anymore return datatypes which aren't usable by the user as they are placed inside the internal package.
With this PR I tried to remove all the pain points we have identified over the last years. Furthermore a user of Microcluster can now properly mock all the types to allow testing their DB and API handler logic.
More description and commit messages pending.
This started out small but after some changes I realized we have to properly hide structs behind interfaces to not anymore return datatypes which aren't usable by the user as they are placed inside the
internalpackage.More description and commit messages pending.
I've not looked at the code, but if these structs need to be accessible to the caller why are they being moved to internal and then interfaces being used to solve the problem?
I've not looked at the code, but if these structs need to be accessible to the caller why are they being moved to internal and then interfaces being used to solve the problem?
One aspect is that we don't have to expose code which is not intended for public use. Another (most important in my opinion) is that you can mock the types for unit testing. Just updated the initial comment.
I've not looked at the code, but if these structs need to be accessible to the caller why are they being moved to internal and then interfaces being used to solve the problem?
One aspect is that we don't have to expose code which is not intended for public use. Another (most important in my opinion) is that you can mock the types for unit testing. Just updated the initial comment.
Can you define the types externally to internal and then use them from both the /internal functions and the call sites (like shared.api)?
Can you define the types externally to
internaland then use them from both the/internalfunctions and the call sites (likeshared.api)?
Yes that is the idea. This PR introduces a microcluster/types package which doesn't import "back" to prevent cycles (same as shared.api).
But in order to do this lots of structs required to move some of their fields from structs to interfaces to prevent import cycles.
Also a pattern this PR gets rid of is the following, exposing internal types by redefining them publicly, see https://github.com/canonical/microcluster/blob/v3/state/state.go.
I'll rework both commits and PR description to be more concrete about what is happening but just wanted to push so that I have something to discuss with @markylaing in our next meet.
Can you define the types externally to
internaland then use them from both the/internalfunctions and the call sites (likeshared.api)?Yes that is the idea. This PR introduces a
microcluster/typespackage which doesn't import "back" to prevent cycles (same asshared.api). But in order to do this lots of structs required to move some of their fields from structs to interfaces to prevent import cycles. Also a pattern this PR gets rid of is the following, exposing internal types by redefining them publicly, see https://github.com/canonical/microcluster/blob/v3/state/state.go.I'll rework both commits and PR description to be more concrete about what is happening but just wanted to push so that I have something to discuss with @markylaing in our next meet.
OK thanks for explaining. I would just say be cautious in using too many Interfaces and check they are truly needed because there is a cost to using them. I myself have used interfaces to break import cycles in the past so I understand what you are doing.
Few points from meeting:
- Summary of which endpoints have been moved where and why. Anything
/internalshould be something that a client will never call. Any changes need careful consideration for upgrades from v2 to v3. Mixed versions could be breaking if APIs have moved around. - Package moves all good :+1:
/internal/sqlshould not be on TLS listener (unix only).
/internal/sqlshould not be on TLS listener (unix only).
So important!
The new package structure LGTM overall. Shall we also update the Makefile
update-schematarget in this PR?
Good catch. We should drop this overall as we agreed on not anymore using lxd-generate and instead maintain the few queries manually.