Skip to content
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

Merged
merged 1 commit into from
Nov 11, 2023

Conversation

brandur
Copy link
Contributor

@brandur brandur commented Nov 10, 2023

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.

@brandur
Copy link
Contributor Author

brandur commented Nov 10, 2023

I'll also update riverdemo to make sure that all still works properly with the bifurcated package.

@@ -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
Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.)

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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
Copy link
Contributor Author

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).

@brandur brandur requested a review from bgentry November 10, 2023 02:06
@brandur brandur enabled auto-merge (squash) November 11, 2023 01:08
@brandur
Copy link
Contributor Author

brandur commented Nov 11, 2023

@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.

image

I'm going to bypass for now, but kind of obnoxious.

@brandur
Copy link
Contributor Author

brandur commented Nov 11, 2023

Huh, actually NM. I think GitHub is having problems. None of checks are even starting on other PRs.

@brandur brandur force-pushed the brandur-riverpgxv5-submodule branch 3 times, most recently from 1178410 to dc5b1fd Compare November 11, 2023 02:24
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.
@brandur brandur merged commit fa68ce5 into master Nov 11, 2023
5 checks passed
@brandur brandur deleted the brandur-riverpgxv5-submodule branch November 11, 2023 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants