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

refactor: persistence table structure #638

Merged
merged 30 commits into from
Aug 10, 2021
Merged

refactor: persistence table structure #638

merged 30 commits into from
Aug 10, 2021

Conversation

zepatrik
Copy link
Member

@zepatrik zepatrik commented Jun 29, 2021

Related issue

closes #613
closes #448
closes #665

Proposed changes

As outlined in #613 we now have one table for all relation tuples:

CREATE TABLE keto_relation_tuples
(
    shard_id                 UUID        NOT NULL,
    network_id               UUID        NOT NULL,
    namespace_id             INTEGER     NOT NULL,
    object                   VARCHAR(64) NOT NULL,
    relation                 VARCHAR(64) NOT NULL,
    subject_id               VARCHAR(64) NULL,
    subject_set_namespace_id INTEGER NULL,
    subject_set_object       VARCHAR(64) NULL,
    subject_set_relation     VARCHAR(64) NULL,
    commit_time              TIMESTAMP   NOT NULL,

    PRIMARY KEY (shard_id, network_id),

    -- enforce to have exactly one of subject_id or subject_set
    CONSTRAINT chk_keto_rt_subject_type CHECK
        ((subject_id IS NULL AND
          subject_set_namespace_id IS NOT NULL AND subject_set_object IS NOT NULL AND subject_set_relation IS NOT NULL)
            OR
         (subject_id IS NOT NULL AND
          subject_set_namespace_id IS NULL AND subject_set_object IS NULL AND subject_set_relation IS NULL))
);

Checklist

Further comments

Outstanding are still
#628
#618
but those will be separate PRs.

Makefile Outdated Show resolved Hide resolved
cmd/migrate/migrate_test.go Outdated Show resolved Hide resolved
cmd/namespace/migrate_down.go Outdated Show resolved Hide resolved
cmd/namespace/migrate_status.go Outdated Show resolved Hide resolved
cmd/namespace/migrate_up.go Outdated Show resolved Hide resolved
internal/persistence/sql/persister.go Outdated Show resolved Hide resolved
@zepatrik zepatrik requested a review from aeneasr July 5, 2021 07:46
Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

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

So how would a migration from the old model to the new model look like? Given that we need that in prod and stage

.bin/go.mod Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
cmd/namespace/migrate_down.go Show resolved Hide resolved
internal/driver/config/provider.go Outdated Show resolved Hide resolved
internal/driver/config/provider.go Show resolved Hide resolved
internal/persistence/sql/network_test.go Outdated Show resolved Hide resolved
internal/persistence/sql/network.go Outdated Show resolved Hide resolved
@zepatrik zepatrik requested a review from aeneasr July 8, 2021 11:57
cmd/server/serve.go Outdated Show resolved Hide resolved
@zepatrik zepatrik requested a review from aeneasr July 13, 2021 14:01
Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

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

I found a few things:

  • Files 20201110175414_relationtuple do not follow the new strategy. I think appending trailing 0 should be enough.
  • Missing index for DELETE FROM keto_relation_tuples WHERE nid = ? AND namespace_id = ? AND object = ? AND relation = ? AND subject_id = ?
  • Missing index for DELETE FROM keto_relation_tuples WHERE nid = ? AND namespace_id = ? AND object = ? AND relation = ? AND subject_set_namespace_id = ? AND subject_set_object = ? AND subject_set_relation = ?
  • Missing index for GetRelationTuples()

And a few more questions:

  • What is the difference between RelationQuery and InternalRelationTuple?

Also we do not have network isolation tests yet. Do you want to include that in this PR or in another one?

@zepatrik
Copy link
Member Author

zepatrik commented Jul 14, 2021

Files 20201110175414_relationtuple do not follow the new strategy. I think appending trailing 0 should be enough.

I can't change the migration ID for already applied migrations right? That would break existing installations as far as I can tell.


Missing index for GetRelationTuples()

Absolutely correct, but I would have to index everything in various orders to match all cases. Depending on the application needs you have different queries. That was the whole point of why we had tables per namespace until now, so that we could add indexes matching the application needs, and not having to index everything. IMO we should right now have some slow queries whenever the indexes are not there, but add the ones required for check evaluation. Later we can add configuration to the namespaces that would enable partial indexes, so that we can say in the groups namespace, we want to query by object and relation (think: listing all members), while in the files namespace we want to query by subject and relation (think: listing all files a user is the owner of).

TL;DR

I will add indexes required for the check and expand APIs, but not for user-defined queries.


What is the difference between RelationQuery and InternalRelationTuple?

The swagger annotations and receiver functions.

@aeneasr
Copy link
Member

aeneasr commented Jul 15, 2021

I can't change the migration ID for already applied migrations right? That would break existing installations as far as I can tell.

Ah, I missed that the files were moved, not created.

I will add indexes required for the check and expand APIs, but not for user-defined queries.

SGTM

Comment on lines +66 to +67
// same registry, but different persisters only differing in the network ID
relationtuple.IsolationTest(t, p0, p1, addNamespace(r, nspaces))
Copy link
Member Author

Choose a reason for hiding this comment

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

@aeneasr this is where we call the isolation test
We have the same registry and therefore same DB connection, but initialize the persisters with different network IDs.

@@ -0,0 +1,87 @@
package sql
Copy link
Member Author

Choose a reason for hiding this comment

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

This file contains everything relevant for the mapping between the serial namespace ID and the UUID stored in the database.
Because it is expected to have few namespaces that are used all the time, I added a ristretto cache for that mapping.

p.l.WithError(err).Error("Unable to ping the database connection, retrying.")
return errors.WithStack(err)
}
func (p *Persister) CreateWithNetwork(ctx context.Context, v interface{}) error {
Copy link
Member Author

Choose a reason for hiding this comment

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

Wow this diff is super messy... Please especially look into this function here, and whether it is a good approach. IMO this is a valid use-case for reflect, but we should think about that.

Copy link
Member

Choose a reason for hiding this comment

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

So generally this looks pretty smart. Personally I feel that reflection should not belong into strict enforcement code of things that do isolation. Since we have panics here, it kind of feels ok though!

internal/driver/config/namespace_memory.go Outdated Show resolved Hide resolved
internal/driver/config/namespace_memory.go Outdated Show resolved Hide resolved
internal/driver/config/namespace_watcher.go Outdated Show resolved Hide resolved
internal/driver/config/namespace_watcher.go Outdated Show resolved Hide resolved
internal/persistence/sql/persister.go Outdated Show resolved Hide resolved
internal/persistence/sql/namespaces.go Outdated Show resolved Hide resolved
internal/persistence/sql/namespaces.go Outdated Show resolved Hide resolved
internal/relationtuple/manager_isolation.go Show resolved Hide resolved
internal/persistence/sql/namespaces.go Outdated Show resolved Hide resolved
internal/persistence/sql/namespaces.go Outdated Show resolved Hide resolved
internal/persistence/sql/namespaces.go Outdated Show resolved Hide resolved
@zepatrik zepatrik requested a review from aeneasr August 9, 2021 15:23
@zepatrik zepatrik merged commit d02b818 into master Aug 10, 2021
@zepatrik zepatrik deleted the persistence-v2-2 branch August 10, 2021 15:52
zepatrik added a commit that referenced this pull request Sep 24, 2021
This change adds a migration path from Keto version v0.6.x to the new persistence structure introduced by #638. Every namespace has to be migrated separately, or you can use the CLI to detect and migrate all namespaces at once. Have a look at `keto help namespace migrate legacy` for all details.
**Please make sure that you backup the database before running the migration command**. Please note that this migration might be a bit slower than usual, as we have to pull the data from the database, transcode it in Keto, and then write it to the new table structure.
Versions of Keto >v0.7 will not include this migration script, so you will first have to migrate to v0.7 and move on from there.
@zepatrik zepatrik mentioned this pull request Dec 7, 2021
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants