-
Notifications
You must be signed in to change notification settings - Fork 278
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
Add API support for transaction metadata on WriteRels and DeleteRels #2084
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import ( | |
"github.com/prometheus/client_golang/prometheus/promauto" | ||
"go.opentelemetry.io/otel/trace" | ||
"google.golang.org/protobuf/proto" | ||
"google.golang.org/protobuf/types/known/structpb" | ||
|
||
"github.com/authzed/spicedb/internal/dispatch" | ||
"github.com/authzed/spicedb/internal/middleware" | ||
|
@@ -42,6 +43,8 @@ var writeUpdateCounter = promauto.NewHistogramVec(prometheus.HistogramOpts{ | |
Buckets: []float64{0, 1, 2, 5, 10, 15, 25, 50, 100, 250, 500, 1000}, | ||
}, []string{"kind"}) | ||
|
||
const MaximumTransactionMetadataSize = 65000 // bytes. Limited by the BLOB size used in MySQL driver | ||
|
||
// PermissionsServerConfig is configuration for the permissions server. | ||
type PermissionsServerConfig struct { | ||
// MaxUpdatesPerWrite holds the maximum number of updates allowed per | ||
|
@@ -273,6 +276,10 @@ func (ps *permissionServer) ReadRelationships(req *v1.ReadRelationshipsRequest, | |
} | ||
|
||
func (ps *permissionServer) WriteRelationships(ctx context.Context, req *v1.WriteRelationshipsRequest) (*v1.WriteRelationshipsResponse, error) { | ||
if err := ps.validateTransactionMetadata(req.OptionalTransactionMetadata); err != nil { | ||
return nil, ps.rewriteError(ctx, err) | ||
} | ||
|
||
ds := datastoremw.MustFromContext(ctx) | ||
|
||
span := trace.SpanFromContext(ctx) | ||
|
@@ -347,7 +354,7 @@ func (ps *permissionServer) WriteRelationships(ctx context.Context, req *v1.Writ | |
|
||
span.AddEvent("write relationships") | ||
return rwt.WriteRelationships(ctx, tupleUpdates) | ||
}) | ||
}, options.WithMetadata(req.OptionalTransactionMetadata)) | ||
if err != nil { | ||
return nil, ps.rewriteError(ctx, err) | ||
} | ||
|
@@ -367,7 +374,28 @@ func (ps *permissionServer) WriteRelationships(ctx context.Context, req *v1.Writ | |
}, nil | ||
} | ||
|
||
func (ps *permissionServer) validateTransactionMetadata(metadata *structpb.Struct) error { | ||
if metadata == nil { | ||
return nil | ||
} | ||
|
||
b, err := metadata.MarshalJSON() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(b) > MaximumTransactionMetadataSize { | ||
return NewTransactionMetadataTooLargeErr(len(b), MaximumTransactionMetadataSize) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we guaranteed that the client encoding will match the JSON encoding? i.e. will the size that that the client sees on their machine match what we're validating against here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No; this is a rough estimate but since the drivers store JSON too, it should be sufficient |
||
} | ||
|
||
return nil | ||
} | ||
|
||
func (ps *permissionServer) DeleteRelationships(ctx context.Context, req *v1.DeleteRelationshipsRequest) (*v1.DeleteRelationshipsResponse, error) { | ||
if err := ps.validateTransactionMetadata(req.OptionalTransactionMetadata); err != nil { | ||
return nil, ps.rewriteError(ctx, err) | ||
} | ||
|
||
if len(req.OptionalPreconditions) > int(ps.config.MaxPreconditionsCount) { | ||
return nil, ps.rewriteError( | ||
ctx, | ||
|
@@ -456,7 +484,7 @@ func (ps *permissionServer) DeleteRelationships(ctx context.Context, req *v1.Del | |
// Otherwise, kick off an unlimited deletion. | ||
_, err = rwt.DeleteRelationships(ctx, req.RelationshipFilter) | ||
return err | ||
}) | ||
}, options.WithMetadata(req.OptionalTransactionMetadata)) | ||
if err != nil { | ||
return nil, ps.rewriteError(ctx, err) | ||
} | ||
|
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 it worth making this datastore-specific? Or will we burn that bridge when we get to it?
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.
I'd rather set it to the low amount and reevaluate in the future if need be. "65K should be enough for anyone!"