summaryrefslogtreecommitdiff
path: root/workhorse/internal/queueing/requests.go
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/queueing/requests.go')
-rw-r--r--workhorse/internal/queueing/requests.go51
1 files changed, 51 insertions, 0 deletions
diff --git a/workhorse/internal/queueing/requests.go b/workhorse/internal/queueing/requests.go
new file mode 100644
index 00000000000..409a7656fa4
--- /dev/null
+++ b/workhorse/internal/queueing/requests.go
@@ -0,0 +1,51 @@
+package queueing
+
+import (
+ "net/http"
+ "time"
+
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+)
+
+const (
+ DefaultTimeout = 30 * time.Second
+ httpStatusTooManyRequests = 429
+)
+
+// QueueRequests creates a new request queue
+// name specifies the name of queue, used to label Prometheus metrics
+// Don't call QueueRequests twice with the same name argument!
+// h specifies a http.Handler which will handle the queue requests
+// limit specifies number of requests run concurrently
+// queueLimit specifies maximum number of requests that can be queued
+// queueTimeout specifies the time limit of storing the request in the queue
+func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTimeout time.Duration) http.Handler {
+ if limit == 0 {
+ return h
+ }
+ if queueTimeout == 0 {
+ queueTimeout = DefaultTimeout
+ }
+
+ queue := newQueue(name, limit, queueLimit, queueTimeout)
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ err := queue.Acquire()
+
+ switch err {
+ case nil:
+ defer queue.Release()
+ h.ServeHTTP(w, r)
+
+ case ErrTooManyRequests:
+ http.Error(w, "Too Many Requests", httpStatusTooManyRequests)
+
+ case ErrQueueingTimedout:
+ http.Error(w, "Service Unavailable", http.StatusServiceUnavailable)
+
+ default:
+ helper.Fail500(w, r, err)
+ }
+
+ })
+}