diff options
author | Sami Hiltunen <shiltunen@gitlab.com> | 2021-02-02 21:45:25 +0300 |
---|---|---|
committer | Sami Hiltunen <shiltunen@gitlab.com> | 2021-02-08 17:49:58 +0300 |
commit | 0c68a6c5ae348178fe01ef1ad96852d9cde39a01 (patch) | |
tree | 989d10cadd7e046ed2a8df668d4e50c8297bfae0 /internal/praefect/router_per_repository.go | |
parent | 3a6d6b150d7bd4dc2c84c22e6a0efe3630c3b529 (diff) |
support default replication factor in PerRepositoryRouter
This commit adds support for selecting host nodes randomly on
repository creation in PerRepositoryRouter. New repositories get
random secondaries assigned as host nodes until the default
replication factor is met. If the virtual storage has no default
replication factor configured, every configured node, except the
randomly picked primary, is included as secondaries. This is
fallback behavior to match Praefect's behavior prior to variable
replication factor.
Diffstat (limited to 'internal/praefect/router_per_repository.go')
-rw-r--r-- | internal/praefect/router_per_repository.go | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/internal/praefect/router_per_repository.go b/internal/praefect/router_per_repository.go index 317e0e21a..9159f3c29 100644 --- a/internal/praefect/router_per_repository.go +++ b/internal/praefect/router_per_repository.go @@ -58,23 +58,25 @@ type PrimaryGetter interface { // PerRepositoryRouter implements a router that routes requests respecting per repository primary nodes. type PerRepositoryRouter struct { - conns Connections - ag AssignmentGetter - pg PrimaryGetter - rand Random - hc HealthChecker - rs datastore.RepositoryStore + conns Connections + ag AssignmentGetter + pg PrimaryGetter + rand Random + hc HealthChecker + rs datastore.RepositoryStore + defaultReplicationFactors map[string]int } // NewPerRepositoryRouter returns a new PerRepositoryRouter using the passed configuration. -func NewPerRepositoryRouter(conns Connections, pg PrimaryGetter, hc HealthChecker, rand Random, rs datastore.RepositoryStore, ag AssignmentGetter) *PerRepositoryRouter { +func NewPerRepositoryRouter(conns Connections, pg PrimaryGetter, hc HealthChecker, rand Random, rs datastore.RepositoryStore, ag AssignmentGetter, defaultReplicationFactors map[string]int) *PerRepositoryRouter { return &PerRepositoryRouter{ - conns: conns, - pg: pg, - rand: rand, - hc: hc, - rs: rs, - ag: ag, + conns: conns, + pg: pg, + rand: rand, + hc: hc, + rs: rs, + ag: ag, + defaultReplicationFactors: defaultReplicationFactors, } } @@ -260,6 +262,11 @@ func (r *PerRepositoryRouter) RouteRepositoryCreation(ctx context.Context, virtu return RepositoryMutatorRoute{}, err } + replicationFactor := r.defaultReplicationFactors[virtualStorage] + if replicationFactor == 1 { + return RepositoryMutatorRoute{Primary: primary}, nil + } + // NodeManagerRouter doesn't consider any secondaries as consistent when creating a repository, // thus the primary is the only participant in the transaction and the secondaries get replicated to. // PerRepositoryRouter matches that behavior here for consistency. @@ -272,6 +279,17 @@ func (r *PerRepositoryRouter) RouteRepositoryCreation(ctx context.Context, virtu replicationTargets = append(replicationTargets, storage) } + // replicationFactor being zero indicates it has not been configured. If so, we fallback to the behavior + // of no assignments and replicate everywhere. + if replicationFactor > 1 { + r.rand.Shuffle(len(replicationTargets), func(i, j int) { + replicationTargets[i], replicationTargets[j] = replicationTargets[j], replicationTargets[i] + }) + + // deduct one as the primary is also hosting the repository + replicationTargets = replicationTargets[:replicationFactor-1] + } + return RepositoryMutatorRoute{ Primary: primary, ReplicationTargets: replicationTargets, |