Skip to content

Commit

Permalink
Merge pull request #1980 from Permify/feature/distributed-consistent-…
Browse files Browse the repository at this point in the history
…hashing

refactor: enhance distributed consistent hashing configuration and er…
  • Loading branch information
tolgaOzen authored Jan 28, 2025
2 parents b9a458f + 16a2e3a commit e79a13f
Show file tree
Hide file tree
Showing 25 changed files with 1,227 additions and 850 deletions.
4 changes: 3 additions & 1 deletion cmd/permify/permify.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package main
import (
"os"

"github.com/cespare/xxhash/v2"

"github.com/sercand/kuberesolver/v5"
"google.golang.org/grpc/balancer"

Expand All @@ -12,7 +14,7 @@ import (

func main() {
kuberesolver.RegisterInCluster()
balancer.Register(consistentbalancer.NewConsistentHashBalancerBuilder())
balancer.Register(consistentbalancer.NewBuilder(xxhash.Sum64))

root := cmd.NewRootCommand()

Expand Down
2 changes: 1 addition & 1 deletion docs/api-reference/apidocs.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "Permify API",
"description": "Permify is an open source authorization service for creating fine-grained and scalable authorization systems.",
"version": "v1.2.7",
"version": "v1.2.8",
"contact": {
"name": "API Support",
"url": "https://github.com/Permify/permify/issues",
Expand Down
2 changes: 1 addition & 1 deletion docs/api-reference/openapiv2/apidocs.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "Permify API",
"description": "Permify is an open source authorization service for creating fine-grained and scalable authorization systems.",
"version": "v1.2.7",
"version": "v1.2.8",
"contact": {
"name": "API Support",
"url": "https://github.com/Permify/permify/issues",
Expand Down
10 changes: 7 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,13 @@ type (
}

Distributed struct {
Enabled bool `mapstructure:"enabled"`
Address string `mapstructure:"address"`
Port string `mapstructure:"port"`
Enabled bool `mapstructure:"enabled"`
Address string `mapstructure:"address"`
Port string `mapstructure:"port"`
PartitionCount int `mapstructure:"partition_count"`
ReplicationFactor int `mapstructure:"replication_factor"`
Load float64 `mapstructure:"load"`
PickerWidth int `mapstructure:"picker_width"`
}
)

Expand Down
46 changes: 17 additions & 29 deletions internal/engines/balancer/balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package balancer

import (
"context"
"encoding/hex"
"fmt"
"log/slog"
"time"

"github.com/cespare/xxhash/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
Expand All @@ -16,15 +14,10 @@ import (
"github.com/Permify/permify/internal/engines"
"github.com/Permify/permify/internal/invoke"
"github.com/Permify/permify/internal/storage"

"github.com/Permify/permify/pkg/balancer"
base "github.com/Permify/permify/pkg/pb/base/v1"
)

var grpcServicePolicy = fmt.Sprintf(`{
"loadBalancingPolicy": "%s"
}`, balancer.Policy)

// Balancer is a wrapper around the balancer hash implementation that
type Balancer struct {
schemaReader storage.SchemaReader
Expand Down Expand Up @@ -52,7 +45,7 @@ func NewCheckEngineWithBalancer(
)

// Set up TLS credentials if paths are provided
if srv.TLSConfig.CertPath != "" && srv.TLSConfig.KeyPath != "" {
if srv.TLSConfig.Enabled && srv.TLSConfig.CertPath != "" && srv.TLSConfig.KeyPath != "" {
isSecure = true
creds, err = credentials.NewClientTLSFromFile(srv.TLSConfig.CertPath, srv.TLSConfig.KeyPath)
if err != nil {
Expand All @@ -62,10 +55,22 @@ func NewCheckEngineWithBalancer(
creds = insecure.NewCredentials()
}

bc := &balancer.Config{
PartitionCount: dst.PartitionCount,
ReplicationFactor: dst.ReplicationFactor,
Load: dst.Load,
PickerWidth: dst.PickerWidth,
}

bcjson, err := bc.ServiceConfigJSON()
if err != nil {
return nil, err
}

// Append common options
options = append(
options,
grpc.WithDefaultServiceConfig(grpcServicePolicy),
grpc.WithDefaultServiceConfig(bcjson),
grpc.WithTransportCredentials(creds),
)

Expand All @@ -82,7 +87,7 @@ func NewCheckEngineWithBalancer(
}
}

conn, err := grpc.Dial(dst.Address, options...)
conn, err := grpc.NewClient(dst.Address, options...)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -112,29 +117,12 @@ func (c *Balancer) Check(ctx context.Context, request *base.PermissionCheckReque

isRelational := engines.IsRelational(en, request.GetPermission())

// Create a new xxhash instance.
h := xxhash.New()

// Generate a unique key for the request based on its relational state.
// This key helps in distributing the request.
_, err = h.Write([]byte(engines.GenerateKey(request, isRelational)))
if err != nil {
slog.ErrorContext(ctx, err.Error())
return &base.PermissionCheckResponse{
Can: base.CheckResult_CHECK_RESULT_DENIED,
Metadata: &base.PermissionCheckResponseMetadata{
CheckCount: 0,
},
}, err
}
k := hex.EncodeToString(h.Sum(nil))

// Add a timeout of 2 seconds to the context and also set the generated key as a value.
withTimeout, cancel := context.WithTimeout(context.WithValue(ctx, balancer.Key, k), 4*time.Second)
withTimeout, cancel := context.WithTimeout(context.WithValue(ctx, balancer.Key, []byte(engines.GenerateKey(request, isRelational))), 4*time.Second)
defer cancel()

// Logging the intention to forward the request to the underlying client.
slog.DebugContext(ctx, "Forwarding request with key to the underlying client", slog.String("key", k))
slog.InfoContext(ctx, "Forwarding request with key to the underlying client")

// Perform the actual permission check by making a call to the underlying client.
response, err := c.client.Check(withTimeout, request)
Expand Down
2 changes: 1 addition & 1 deletion internal/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var Identifier = ""
*/
const (
// Version is the last release of the Permify (e.g. v0.1.0)
Version = "v1.2.7"
Version = "v1.2.8"
)

// Function to create a single line of the ASCII art with centered content and color
Expand Down
Loading

0 comments on commit e79a13f

Please sign in to comment.