-
Notifications
You must be signed in to change notification settings - Fork 282
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
End to end support for experimental first-class relationship expiration feature #2152
base: main
Are you sure you want to change the base?
Conversation
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 comments, otherwise LGTM
// even if an error happened, garbage would have been collected. This makes sure these are reflected even if the | ||
// worker eventually fails or times out. | ||
gcRelationshipsCounter.Add(float64(collected.Relationships)) | ||
gcTransactionsCounter.Add(float64(collected.Transactions)) | ||
gcNamespacesCounter.Add(float64(collected.Namespaces)) | ||
gcExpiredRelationshipsCounter.Add(float64(expiredRelationshipsCount)) |
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.
Is this being a float just because that's how Prometheus implements counters?
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.
Yes
Columns(colExpiresAt, colMetadata). | ||
Values(expiresAt, config.Metadata.AsMap()) | ||
// Write metadata onto the transaction. | ||
metadata := config.Metadata.AsMap() |
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.
Does the creation here also attach it to the transaction? Otherwise it looks like it's being constructed and modified but not attached.
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.
Line 362 executes the insert statement for it; I fixed the reference
@@ -549,7 +590,9 @@ func (cds *crdbDatastore) processChanges(ctx context.Context, changes pgx.Rows, | |||
return | |||
} | |||
|
|||
if err := tracked.SetRevisionMetadata(ctx, rev, details.After.Metadata); err != nil { | |||
adjustedMetadata := details.After.Metadata |
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 my own edification - when you set something equal to a struct rather than a pointer to that struct, is it functionally creating a copy of it, which is what lets us safely delete the key?
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.
In this case, its safe because we're not reusing it anywhere else
@@ -115,6 +118,7 @@ func NewPermissionsServer( | |||
MaxLookupResourcesLimit: defaultIfZero(config.MaxLookupResourcesLimit, 1_000), | |||
MaxBulkExportRelationshipsLimit: defaultIfZero(config.MaxBulkExportRelationshipsLimit, 100_000), | |||
DispatchChunkSize: defaultIfZero(config.DispatchChunkSize, 100), | |||
ExpiringRelationshipsEnabled: true, |
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.
Meaning it defaults to enabled? Or is this something that should look like the above?
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.
Yes, for testing. We then explicitly disable it when starting SpiceDB, as its default is false
@@ -480,6 +481,30 @@ func TestDeleteRelationshipViaWriteNoop(t *testing.T) { | |||
require.NoError(err) | |||
} | |||
|
|||
func TestWriteExpiringRelationshinps(t *testing.T) { |
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.
func TestWriteExpiringRelationshinps(t *testing.T) { | |
func TestWriteExpiringRelationships(t *testing.T) { |
@@ -84,6 +84,7 @@ func (c *Config) Complete() (RunnableTestServer, error) { | |||
MaxLookupResourcesLimit: c.MaxLookupResourcesLimit, | |||
MaxBulkExportRelationshipsLimit: c.MaxBulkExportRelationshipsLimit, | |||
DispatchChunkSize: defaultMaxChunkSize, | |||
ExpiringRelationshipsEnabled: true, |
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.
Same here - should this reference the config?
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.
No; I think its fine to enable by default in the test server
MaxPreconditionsCount: 50, | ||
MaximumAPIDepth: 50, | ||
MaxCaveatContextSize: 0, | ||
ExpiringRelationshipsEnabled: true, |
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.
Here as well
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.
LGTM
4f70c9b
to
2de262c
Compare
677802a
to
cccd06e
Compare
Fixes #1262 by superseding it
When the flag is enabled, relationship expiration can be used in schema via the
use expiration
directive and theexpiration
keyword onrelation
's:When a relationship reaches its expiration, it is immediately filtered from all relationship queries, making it appear as-if it was immediately deleted.
Subsequently (typically 24 hours later), the relationship will be actually removed from the underlying datastore to free space.
Warning
Currently, relationships are filtered using the wall clock found within the datastore, which has the following consequences:
at_exact_snapshot
calls, as they are made to the datastore, will reflect the expiration as of "now", which means they can return different results depending on when they are invoked. This is a change from current behavior when using caveats for expiration. Note that this may be changed in the future to instead use the timestamp of the revision itself; this change is currently under discussionNote
This PR does not yet implement returning of the
expires_at
in CheckPermissionResponse and CheckPermission debug information. That will be done in a followup PR.