-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make riverdriver/riverpgxv5
its own submodule
#3
Conversation
I'll also update riverdemo to make sure that all still works properly with the bifurcated package. |
1a7176a
to
5bbaa4e
Compare
@@ -22,9 +22,10 @@ require ( | |||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect | |||
github.com/kr/text v0.2.0 // indirect | |||
github.com/pmezard/go-difflib v1.0.0 // indirect | |||
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.0.0-20231110014757-1a7176abdf3c // indirect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now I had to lock this to the commit hash in this branch, which is obviously problematic, but it's a bit of a chicken and egg problem. I can't go get
the new module without specifying this branch. We can fix if/when this comes in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, does bun
get away with not needing this because they don't directly use their driver packages within the main package? I'm just wondering if this is going to cause more pain than it's worth right now, like will we have to bump this with every version and always run into a chicken & egg issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into that, and they get away with it by making every single example in the examples directory its own Go module as well :$ (You also can't use the specific driver in tests, which we do a lot.)
Maybe something we should do eventually, but man, kind of the nuclear option.
I figure that we could probably keep the dependency for now, and one day when the project's more mature, detach it by following a path closer to Bun's. (Removing the dependency would not be a breaking change, which is good.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So how do we actually publish an updated riverdriver/riverpgxv5
and a plain river
at the same time? Do we need to do a double tag and release?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think that's basically it ...
If you take a look at Bun, the latest release is v0.1.17 and its examples are pegged to v1.1.16.
It kind of makes sense. If the two modules lived in separate Git repos, you'd need to do a double-release there too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling this is going to be painful and error prone but let's give it a shot, I don't think Go gives us any better options 😆
// GetSentinel returns a sentinal value of a type that's internal to River. | ||
// Its purpose is to prevent public code from implementing this interface | ||
// because it's not meant to be used externally at this time. | ||
GetSentinel() internal.Sentinel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See PR description, but I had to drop the sentinel because the two packages can no longer share an internal type (and a cyclic dependency is not allowed anyway).
@bgentry Oh man, I've never really used branch protection I guess, but if I rebase locally and re-push, does that dismiss your review and prevent a merge? I get a pretty confused interface that says "approved", all checks passing, but merge not allowed. I'm going to bypass for now, but kind of obnoxious. |
Huh, actually NM. I think GitHub is having problems. None of checks are even starting on other PRs. |
1178410
to
dc5b1fd
Compare
Here, make `riverdriver/riverpgxv5` its own submodule. This does nothing for the time being since the top-level River package is entirely dependent on `riverpgxv5` as the only driver (and its used in examples and tests), but the general idea is that in the future each driver could bring in its own dependencies, and applications using River wouldn't have to pull in every 3rd party database package that River supports. The only problem is that there's a tradeoff: the way I had `riverpgxv5` before is that it referenced `riverdriver.Driver` and made use of an `internal.Sentinel` value from the top-level package to guarantee no one could implement the driver interface externally. That no longer works because it introduce a dependency cycle: `river` needs `riverpgxv5` and `riverpgxv5` needs `river`. So I can remove the top-level types referenced in `riverpgxv5` so the dependency only goes one way, but we lose `internal.Sentinel`, and can no longer guarantee that `Driver` isn't implemented. So put simply: `riverpgxv5` gets its own module, but we move to only a soft guarantee that external users don't implement `Driver` (we spell it out in the docs, but there's nothing technical preventing people from doing it). Overall: I think it's probably worth it. It's pretty clear `Driver` isn't meant for external implementation, there's no advantage to doing so, and the interface is already a little leaky because users could technically call functions on the interface already like `GetDBPool()` and break themselves as those disappear in the future.
dc5b1fd
to
af2caba
Compare
Here, make
riverdriver/riverpgxv5
its own submodule. This does nothingfor the time being since the top-level River package is entirely
dependent on
riverpgxv5
as the only driver (and its used in examplesand tests), but the general idea is that in the future each driver could
bring in its own dependencies, and applications using River wouldn't
have to pull in every 3rd party database package that River supports.
The only problem is that there's a tradeoff: the way I had
riverpgxv5
before is that it referenced
riverdriver.Driver
and made use of aninternal.Sentinel
value from the top-level package to guarantee no onecould implement the driver interface externally. That no longer works
because it introduce a dependency cycle:
river
needsriverpgxv5
andriverpgxv5
needsriver
. So I can remove the top-level typesreferenced in
riverpgxv5
so the dependency only goes one way, but welose
internal.Sentinel
, and can no longer guarantee thatDriver
isn't implemented.
So put simply:
riverpgxv5
gets its own module, but we move to only asoft guarantee that external users don't implement
Driver
(we spell itout in the docs, but there's nothing technical preventing people from
doing it).
Overall: I think it's probably worth it. It's pretty clear
Driver
isn't meant for external implementation, there's no advantage to doing
so, and the interface is already a little leaky because users could
technically call functions on the interface already like
GetDBPool()
and break themselves as those disappear in the future.