-
Notifications
You must be signed in to change notification settings - Fork 460
/
request.go
70 lines (58 loc) · 2.05 KB
/
request.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// SPDX-License-Identifier: AGPL-3.0-only
package distributor
import (
"fmt"
"github.com/grafana/mimir/pkg/mimirpb"
)
// supplierFunc should return either a non-nil body or a non-nil error. The returned cleanup function can be nil.
type supplierFunc func() (req *mimirpb.WriteRequest, cleanup func(), err error)
// Request represents a push request. It allows lazy body reading from the underlying http request
// and adding cleanup functions that should be called after the request has been handled.
type Request struct {
// have a backing array to avoid extra allocations
cleanupsArr [10]func()
cleanups []func()
getRequest supplierFunc
request *mimirpb.WriteRequest
err error
}
func newRequest(p supplierFunc) *Request {
r := &Request{
getRequest: p,
}
r.cleanups = r.cleanupsArr[:0]
return r
}
func NewParsedRequest(r *mimirpb.WriteRequest) *Request {
return newRequest(func() (*mimirpb.WriteRequest, func(), error) {
return r, nil, nil
})
}
// WriteRequest returns request from supplier function. Function is only called once,
// and subsequent calls to WriteRequest return the same value.
func (r *Request) WriteRequest() (*mimirpb.WriteRequest, error) {
if r.request == nil && r.err == nil {
var cleanup func()
r.request, cleanup, r.err = r.getRequest()
if r.request == nil && r.err == nil {
r.err = fmt.Errorf("push.Request supplierFunc returned a nil body and a nil error, either should be non-nil")
}
r.AddCleanup(cleanup)
}
return r.request, r.err
}
// AddCleanup adds a function that will be called once CleanUp is called. If f is nil, it will not be invoked.
func (r *Request) AddCleanup(f func()) {
if f == nil {
return
}
r.cleanups = append(r.cleanups, f)
}
// CleanUp calls all added cleanups in reverse order - the last added is the first invoked. CleanUp removes
// each called cleanup function from the list of cleanups. So subsequent calls to CleanUp will not invoke the same cleanup functions.
func (r *Request) CleanUp() {
for i := len(r.cleanups) - 1; i >= 0; i-- {
r.cleanups[i]()
}
r.cleanups = r.cleanups[:0]
}