-
Notifications
You must be signed in to change notification settings - Fork 622
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
JSONB and KeyspaceMetadata fixes for Yugabyte #1675
Conversation
fc5acec
to
b6aedec
Compare
@martin-sucha can you take a look at this? Thanks! |
Hi! Previously, @Zariel was against including ScyllaDB-specific code to this repository (see the Scylla pull requests), including Yugabyte-specific code seems like the same category of issue, so I guess we should agree first whether to include such code or not. It seems we should not prefer one DB over the other. Personally I don't mind including database-specific code to the gocql/gocql repository, but there needs to be a clear way how to maintain it and test it. Ideally we should run integration tests in CI automatically. Alternately, is there a way to include an extension mechanism so the required functionality could be provided by an external package instead? |
@martin-sucha Thanks for the quick reply. I definitely understand the concern. I think it makes sense to include changes per-database provided they aren't huge. I'm definitely fine maintaining the YB-specific code since we use it in production along with this repo. One issue I see is that I called the value I added a specific test file that can use the YB docker image to run tests and I confirmed that they pass. What's the path to adding that to CI? The type might be a place where we could expose a The metadata issues are just a quirk from YB and I don't think an extension could work for that. I also expect it to be fixed on YB's end eventually. |
@Zariel would appreciate your thoughts as well |
Right, it seems similar to handling different Cassandra versions. The question is where is the line :)
Help with maintaining is always appreciated. Maybe we could even increase the bus factor here if you are willing to help with maintaining even the non-YB-specific code. What do you think?
Yes, it seems that the YB prefix might be useful as the JSONB type is an extension of the cql protocol. Or maybe we could have a I was also thinking what would happen in case a different database uses the same type number for a different type. Should we check that the database is yugabyte before checking for the 0x0080 value or it is unlikely to happen in practice? Or maybe we should update the upstream Cassandra CQL documentation and mention the 0x0080 value there?
Currently the CI is broken because Ubuntu 18.04 machine is no longer available. I tried some upgrades in #1685 but it seems that the upgrading is not enough. I think it might be better to just write the Docker setup in Go from scratch than rely on ccm, see #1686.
How is Jsonb type usually used? Do you unmarshal it to strings, []byte etc? Would a type like package yugabyte
import "errors"
const TypeJsonb = gocql.Type(0x0080)
var ErrNotJsonb = errors.New("type is not jsonb")
type Jsonb []byte
func (jb *Jsonb) UnmarshalCQL(info gocql.TypeInfo, data []byte) error {
if info.Type() != TypeJsonb {
return ErrNotJsonb
}
if data != nil {
*jb = append((*v)[:0], data...)
} else {
*jb = nil
}
} work or is it too restrictive? The downside would be that the users would have to use type in all structs and it won't automatically work with maps. In any case it seems registering types with current (un)marshal interfaces is not straightforward. Global registration would work but I'd rather not add more global state. Per-session registration would need a different MarshalCQL/UnmarshalCQL signature that gets a callback function to unmarshal sub-values, since the usual implementations currently call the global gocql.Marshal/gocql.Unmarhal. Or we'd need to hack it and pass the type map inside gocql.TypeInfo.
Yep, makes sense. |
Totally agree. Not sure where it makes sense to define the line other than I agree with your intuition to try and externalize as much of it as possible, whenever we reasonably can.
Definitely open to help maintain the repo as a whole. We rely on this library in production and I've already had several PRs merged over the last few years.
I wouldn't want to introduce another round-trip to determine if its YB and I'm not finding a way to determine, with confidence, that it's YB from the handshake or the frame headers. At the expense of another public field, what if the Let me play around with an alternative way to implement this and see what you think.
Typically type MyStruct struct {
...
}
func (s MyStruct) MarshalCQL(info gocql.TypeInfo) ([]byte, error) {
return json.Marshal(s)
}
func (s *MyStruct) UnmarshalCQL(info gocql.TypeInfo, data []byte) error {
return json.Unmarshal(data, &s)
} Which wouldn't require the type to be registered since you're overriding the marshaling or unmarshaling. If we wanted to make this a first-class type then it would be useful to automatically do the marshaling/unmarshaling if the destination type isn't a byte array but that feels like it should be in a separate PR.
Yes, this would also break uses that might have multiple instances of gocql across packages. |
@martin-sucha So the biggest issue I ran into when trying to remove the yugabyte-specific type and instead have some opt-in "extension" is the package-level
|
Yugabyte merged a commit to bring the system_schema tables in alignment which means we don't need to do a bunch of this work. yugabyte/yugabyte-db@7fc3b76 We still need to handle the custom jsonb column. I'm going to see if there's a way for a library user to add a custom type. |
Superseded by #1855 |
Ran the latest tests against yb 2.16.1.0-b50
I didn't include them in
all
and I'm not sure how we want to automate testing going forward.