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

fix: Ensure Index.Walk fetches matching foreign keys only #20097

Merged
merged 4 commits into from
Nov 23, 2020

Conversation

stuartcarnie
Copy link
Contributor

@stuartcarnie stuartcarnie commented Nov 19, 2020

Closes #20096

This PR ensures Influx.Walk validates that every matched key returned by the index prefix cursor is an exact match with the foreignKey argument. This change broke an invalid assumption made by the DBRP Find operations when searching for mappings by organisation ID only. This was fixed in a second commit.

The first commit modifies the behaviour of the internal indexWalk function to ensure it parses the key parts and matches the foreign key exactly. Unit tests ensure this behaviour.

The second commit adds a new index and migration to the DBRP service for finding all database and retention policy mappings for a single organisation. This change was required to resolve an invalid assumption of the DBRP service, which relied on a prefix match of the byOrgAndDatabase index when performing search operations using the organisation ID only.

@stuartcarnie stuartcarnie added the area/2.x OSS 2.0 related issues and PRs label Nov 19, 2020
@stuartcarnie stuartcarnie self-assigned this Nov 19, 2020
@stuartcarnie
Copy link
Contributor Author

@GeorgeMac, given your experience with implementing the index, can you review this draft PR and comment about the expected behaviour of Influx.Walk and whether we should introduce Index.WalkExact for the dbrp orgIDDatabase index:

influxdb/dbrp/service.go

Lines 70 to 76 in b274e15

byOrgAndDatabase: kv.NewIndex(kv.NewIndexMapping(bucket, indexBucket, func(v []byte) ([]byte, error) {
var dbrp influxdb.DBRPMappingV2
if err := json.Unmarshal(v, &dbrp); err != nil {
return nil, err
}
return indexForeignKey(dbrp), nil
}), kv.WithIndexReadPathEnabled),

kv/index.go Outdated Show resolved Hide resolved
func TestIndex_Walk(t *testing.T) {
t.Run("only selects exact keys", func(t *testing.T) {
ctrl := gomock.NewController(t)
t.Cleanup(ctrl.Finish)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take it or leave it: With 1.14+ this happens by default:
https://godoc.org/github.com/golang/mock/gomock#NewController

Suggested change
t.Cleanup(ctrl.Finish)

Copy link
Contributor Author

@stuartcarnie stuartcarnie Nov 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been waiting for this, however, the docs are misleading as there is no released version of gomock with this support yet:

mock@master has the Cleanup support 👍 :

https://github.com/golang/mock/blob/99aa9272d551d0d16f4bdcc43dc06a3077e69b3a/gomock/controller.go#L136-L141

latest tagged version is mock@1.4.4, which does not have Cleanup support 👎 :

https://github.com/golang/mock/blob/f7b1909c82a8958747e5c87c6a5c3b2eaed8a33d/gomock/controller.go#L118-L128

var keys [][]byte
for ik, pk := indexCursor.Next(); ik != nil; ik, pk = indexCursor.Next() {
keys = append(keys, pk)
if fk, _, err := indexKeyParts(ik); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌 awesome

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually @stuartcarnie you know what I've just thought of something better.
If we curse foreignKey + "/" then we push down the actual prefix to the db.
This does make me think the foreign key needs to be escaped for "/" as well though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unclear what I should change here – should we add some code to validate that foreign keys do not have / for now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spoke with @GeorgeMac and I am going to reject foreign keys with a /. Clients of the Index will be expected to partition their foreign keys with characters other than a /

Copy link
Contributor

@GeorgeMac GeorgeMac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great @stuartcarnie !

This commit modifies the behaviour of the indexWalk function to ensure
it parses the key parts and matches the foreign key exactly.

Closes #20096
This commit adds a new index and migration to the DBRP service for
retrieving all database and retention policy mappings for a single
organization.

This change was required to resolve an invalid assumption of the DBRP
service, which relied on a prefix match of the byOrgAndDatabase kv.Index
when performing search operations by organization ID only.

Closes #20096
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/2.x OSS 2.0 related issues and PRs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kv Index.Walk function matches the foreign key by prefix only
2 participants