Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'internal/rollout/rollout.go')
-rw-r--r--internal/rollout/rollout.go53
1 files changed, 53 insertions, 0 deletions
diff --git a/internal/rollout/rollout.go b/internal/rollout/rollout.go
new file mode 100644
index 00000000..ec592c38
--- /dev/null
+++ b/internal/rollout/rollout.go
@@ -0,0 +1,53 @@
+package rollout
+
+import (
+ "errors"
+ "hash/fnv"
+ "math/rand"
+)
+
+// Rollout returns true and no error when during this run something should
+// happen for given actor according to the stickiness and likelyhood passed
+// as a percentage value to this function. It returns false rollout and an
+// error if the percentage value is negative or higher than 100.
+func Rollout(actor string, percentage int, stickiness string) (bool, error) {
+ if percentage < 0 || percentage > 100 {
+ return false, errors.New("Rollout value should be between 0 and 100 inclusive")
+ }
+
+ if percentage == 0 {
+ return false, nil
+ }
+
+ if percentage == 100 {
+ return true, nil
+ }
+
+ switch stickiness {
+ case "random":
+ return random(percentage), nil
+ default:
+ return forActor(actor, percentage), nil
+ }
+}
+
+// random guarantees no stickiness. For every call it will yield a random
+// true/false based on the provided rollout percentage.
+func random(percentage int) bool {
+ return rand.Intn(100) < percentage
+}
+
+// forActor provides "stickines", i.e. guarantees that the same actor
+// gets the same result every time. It also assures that an actor which is
+// among the first 10% will also be among the first 20%.
+func forActor(actor string, percentage int) bool {
+ h := fnv.New32a()
+ h.Write([]byte(actor))
+ sum32 := h.Sum32()
+
+ if sum32 == 0 {
+ return false
+ }
+
+ return (sum32 % uint32(100)) < uint32(percentage)
+}