-
Notifications
You must be signed in to change notification settings - Fork 270
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
Internal redispatch #39
Conversation
18e3edd
to
c33c5a2
Compare
.github/workflows/build.yaml
Outdated
@@ -71,9 +71,11 @@ jobs: | |||
- name: "Generate & Diff Servok Protos" | |||
run: | | |||
./buf.gen.yaml | |||
git diff |
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.
Why these additions? Just to make the errors nicer?
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.
Yeah it was impossible for me to see what the difference was.
cmd/spicedb/root.go
Outdated
@@ -77,8 +82,11 @@ func newRootCmd() *cobra.Command { | |||
// Flags for parsing and validating schemas. | |||
rootCmd.Flags().Bool("schema-prefixes-required", false, "require prefixes on all object definitions in schemas") | |||
|
|||
// Flags for internal dispatch API | |||
rootCmd.Flags().String("internal-grpc-addr", ":50052", "address to listen for internal requests") |
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.
Since we use 50052 for corrino currently, can we default to this something like 50053?
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.
everything uses 50051 now (inherited from cobrautil), but we might want to make this port totally different so that there's no mistaking it
internal/dispatch/caching/caching.go
Outdated
} | ||
|
||
totalCounter := prometheus.NewCounter(prometheus.CounterOpts{ | ||
Namespace: "spicedb", |
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.
Move the "spicedb" into a constant
|
||
// DispatchExpand implements dispatch.Expand interface | ||
func (cd *cachingDispatcher) DispatchExpand(ctx context.Context, req *v1.DispatchExpandRequest) (*v1.DispatchExpandResponse, error) { | ||
return cd.d.DispatchExpand(ctx, req) |
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.
Add comments here and in Lookup that we're not doing caching yet
internal/dispatch/caching/caching.go
Outdated
return nil, fmt.Errorf(errCachingInitialization, err) | ||
} | ||
|
||
totalCounter := prometheus.NewCounter(prometheus.CounterOpts{ |
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.
Probably should name this differently, since I'd expect it to be for all api calls, not just checks
cd.c.Set(requestKey, toCache, checkResultEntryCost) | ||
} | ||
|
||
return computed, 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.
Maybe be explicit here in returning nil
for the result?
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.
It's not always nil here.
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.
We have a non-nil result when there is an error?
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.
the error condition doesn't short circuit
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.
Oh... that's highly unexpected to me. Maybe just return the error if it occurs and move the cache update outside of the branch?
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.
yeah i think adding the short circuit would make this less prone to getting broken in a future refactor
}) | ||
|
||
require.NoError(err) | ||
require.Equal(expected.isMember, checkResult.Membership == v1.DispatchCheckResponse_MEMBER) |
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.
Perhaps add a dispatch again and verify again, to ensure caching is working as expected?
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.
which caching? This only has namespace manager caching, not dispatch caching.
fa34750
to
94baf04
Compare
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.
Sorry a bunch of my comments were on early commits from before refactors and then I just decided to jump ahead to the final state.
pkg/smartclient/v2/client.go
Outdated
sync.Mutex{}, | ||
consistent.NewHashring(xxhash.Sum64, hashringReplicationFactor), | ||
cancel, | ||
proto.MarshalOptions{Deterministic: 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.
Is there a time we don't want this to be deterministic? Why bother parameterizing it?
pkg/smartclient/v2/client.go
Outdated
} | ||
|
||
for ctx.Err() == nil { | ||
endpointResponse, err := stream.Recv() |
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.
isn't the first response always an empty one? (i'm remembering this from an earlier iteration of this code)
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 fixed that. It was a disaster when servok restarted.
pkg/smartclient/v2/client.go
Outdated
} | ||
|
||
// Stop will cancel the client watch and clean up the pool | ||
func (sc *SmartClient) Stop() { |
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.
It might be more idiomatic to support context cancellation for this rather than an explicit Stop function.
I can see arguments both ways, but I think we should strive to use one cohesive strategy across the codebase.
pkg/smartclient/v2/client.go
Outdated
|
||
var errNoBackends = errors.New("no backends available for request") | ||
|
||
// SmartClient is a client which utilizes a dynamic source of backends and a consistent |
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 know it's a nit, but I really dislike "smart client" -- it doesn't really mean anything and gives absolutely no information about the behavior of the client other than it has "some kind of logic".
LiveHashringDispatchClient
or UpdatingHashringDispatchClient
maybe would be better?
pkg/smartclient/v2/options.go
Outdated
"github.com/authzed/spicedb/pkg/x509util" | ||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials" |
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.
import mixing
cd.c.Set(requestKey, toCache, checkResultEntryCost) | ||
} | ||
|
||
return computed, 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.
yeah i think adding the short circuit would make this less prone to getting broken in a future refactor
var tracer = otel.Tracer("spicedb/internal/dispatch/local") | ||
|
||
// NewLocalOnlyDispatcher creates a dispatcher that consults with the graph to formulate a response. | ||
func NewLocalOnlyDispatcher( |
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 there a reason to call this LocalOnly rather than just Local?
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, because a "local" dispatcher can be configured to redispatch to the network.
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.
that's not at all obvious from the names
v1 "github.com/authzed/spicedb/internal/proto/dispatch/v1" | ||
) | ||
|
||
type clusterClient interface { |
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.
dispatchClient
|
||
// NewClusterDispatcher creates a dispatcher implementation that uses the provided client | ||
// to dispatch requests to peer nodes in the cluster. | ||
func NewClusterDispatcher(client clusterClient) dispatch.Dispatcher { |
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 get it -- but this API is kinda weird since you're creating a dispatcher from a dispatcher.
Maybe we can make this more specific and name this one the DepthCheckingDispatcher?
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.
Whoa that's a gross misrepresentation of what this does!
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'm pretty sure I'm just crazy overloading the term "dispatcher"
internal/dispatch/caching/caching.go
Outdated
cd.c.Set(requestKey, toCache, checkResultEntryCost) | ||
} | ||
|
||
// Return both the computed and err in ALL cases, computed contains resolved metadata even |
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.
,
-> :
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.
looks good to me after a rebase
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
Signed-off-by: Jake Moshenko <jacob.moshenko@gmail.com>
e1fce20
to
0ae9a5c
Compare
No description provided.