Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
73345bef
Commit
73345bef
authored
Mar 01, 2017
by
Kamil Trzcinski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor source to look way nicer
parent
25d46f88
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
77 additions
and
38 deletions
+77
-38
internal/builds/register.go
internal/builds/register.go
+55
-38
internal/helper/helpers.go
internal/helper/helpers.go
+22
-0
No files found.
internal/builds/register.go
View file @
73345bef
package
builds
import
(
"bytes"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/redis"
"io"
"io/ioutil"
"net/http"
"time"
)
const
MaxRegisterBodySize
=
4
*
1024
"github.com/prometheus/client_golang/prometheus"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/redis"
)
func
readRunnerQueueKey
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
string
,
error
)
{
limitedBody
:=
http
.
MaxBytesReader
(
w
,
r
.
Body
,
MaxRegisterBodySize
)
defer
limitedBody
.
Close
()
const
(
maxRegisterBodySize
=
4
*
1024
runnerBuildQueue
=
"runner:build_queue:"
runnerBuildQueueKey
=
"token"
runnerBuildQueueValue
=
"X-GitLab-Last-Update"
)
// Read body
var
body
bytes
.
Buffer
_
,
err
:=
io
.
Copy
(
&
body
,
limitedBody
)
if
err
!=
nil
{
return
""
,
err
}
var
(
registerHandlerHits
=
prometheus
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Name
:
"gitlab_workhorse_builds_register_handler"
,
Help
:
"How many connections gitlab-workhorse has opened in total. Can be used to track Redis connection rate for this process"
,
},
[]
string
{
"status"
},
)
)
r
.
Body
=
ioutil
.
NopCloser
(
&
body
)
type
largeBodyError
struct
{
error
}
type
watchError
struct
{
error
}
tmpReq
:=
*
r
tmpReq
.
Body
=
ioutil
.
NopCloser
(
bytes
.
NewReader
(
body
.
Bytes
()))
func
init
()
{
prometheus
.
MustRegister
(
registerHandlerHits
,
)
}
err
=
tmpReq
.
ParseForm
()
func
readRunnerToken
(
r
*
http
.
Request
)
(
string
,
error
)
{
err
:=
r
.
ParseForm
()
if
err
!=
nil
{
return
""
,
err
}
token
:=
tmpReq
.
FormValue
(
"token"
)
if
token
==
""
{
return
""
,
nil
}
key
:=
"runner:build_queue:"
+
token
return
key
,
nil
token
:=
r
.
FormValue
(
runnerBuildQueueKey
)
return
token
,
nil
}
func
RegisterHandler
(
h
http
.
Handler
,
pollingDuration
time
.
Duration
)
http
.
Handler
{
...
...
@@ -48,25 +51,32 @@ func RegisterHandler(h http.Handler, pollingDuration time.Duration) http.Handler
}
return
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
lastUpdate
:=
r
.
Header
.
Get
(
"X-GitLab-Last-Update"
)
lastUpdate
:=
r
.
Header
.
Get
(
runnerBuildQueueValue
)
if
lastUpdate
==
""
{
// We could have a fail-over implementation here, for old runners, that:
// Proxies the requests, if this is 204, we delay the response to client,
// By checking the response from handler, and reading `X-GitLab-Last-Update`,
// and then watching on a key
// The client doesn't have update, fail
registerHandlerHits
.
WithLabelValues
(
"missing-value"
)
.
Inc
()
h
.
ServeHTTP
(
w
,
r
)
return
}
queueKey
,
err
:=
readRunnerQueueKey
(
w
,
r
)
requestBody
,
err
:=
helper
.
ReadRequestBody
(
w
,
r
,
maxRegisterBodySize
)
if
err
!=
nil
{
helper
.
Fail500
(
w
,
r
,
err
)
registerHandlerHits
.
WithLabelValues
(
"body-read-error"
)
.
Inc
()
helper
.
Fail500
(
w
,
r
,
&
largeBodyError
{
err
})
return
}
runnerToken
,
err
:=
readRunnerToken
(
helper
.
CloneRequestWithNewBody
(
r
,
requestBody
))
if
runnerToken
==
""
||
err
!=
nil
{
registerHandlerHits
.
WithLabelValues
(
"body-parse-error"
)
.
Inc
()
h
.
ServeHTTP
(
w
,
r
)
return
}
result
,
err
:=
redis
.
WatchKey
(
queueKey
,
lastUpdate
,
pollingDuration
)
result
,
err
:=
redis
.
WatchKey
(
runnerBuildQueue
+
runnerToken
,
lastUpdate
,
pollingDuration
)
if
err
!=
nil
{
helper
.
Fail500
(
w
,
r
,
err
)
registerHandlerHits
.
WithLabelValues
(
"watch-error"
)
.
Inc
()
helper
.
Fail500
(
w
,
r
,
&
watchError
{
err
})
return
}
...
...
@@ -74,7 +84,8 @@ func RegisterHandler(h http.Handler, pollingDuration time.Duration) http.Handler
// It means that we detected a change before starting watching on change,
// We proxy request to Rails, to see whether we can receive the build
case
redis
.
WatchKeyStatusAlreadyChanged
:
h
.
ServeHTTP
(
w
,
r
)
registerHandlerHits
.
WithLabelValues
(
"already-changed"
)
.
Inc
()
h
.
ServeHTTP
(
w
,
helper
.
CloneRequestWithNewBody
(
r
,
requestBody
))
// It means that we detected a change after watching.
// We could potentially proxy request to Rails, but...
...
...
@@ -82,12 +93,18 @@ func RegisterHandler(h http.Handler, pollingDuration time.Duration) http.Handler
// as don't really know whether ResponseWriter is still in a sane state,
// whether the connection is not dead
case
redis
.
WatchKeyStatusSeenChange
:
registerHandlerHits
.
WithLabelValues
(
"seen-change"
)
.
Inc
()
w
.
WriteHeader
(
204
)
// When we receive one of these statuses, it means that we detected no change,
// so we return to runner 204, which means nothing got changed,
// and there's no new builds to process
case
redis
.
WatchKeyStatusTimeout
,
redis
.
WatchKeyStatusNoChange
:
case
redis
.
WatchKeyStatusTimeout
:
registerHandlerHits
.
WithLabelValues
(
"timeout"
)
.
Inc
()
w
.
WriteHeader
(
204
)
case
redis
.
WatchKeyStatusNoChange
:
registerHandlerHits
.
WithLabelValues
(
"no-change"
)
.
Inc
()
w
.
WriteHeader
(
204
)
}
})
...
...
internal/helper/helpers.go
View file @
73345bef
package
helper
import
(
"bytes"
"errors"
"io"
"io/ioutil"
"log"
"mime"
"net"
...
...
@@ -166,3 +169,22 @@ func IsContentType(expected, actual string) bool {
parsed
,
_
,
err
:=
mime
.
ParseMediaType
(
actual
)
return
err
==
nil
&&
parsed
==
expected
}
func
ReadRequestBody
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
maxBodySize
int64
)
([]
byte
,
error
)
{
limitedBody
:=
http
.
MaxBytesReader
(
w
,
r
.
Body
,
maxBodySize
)
defer
limitedBody
.
Close
()
var
body
bytes
.
Buffer
_
,
err
:=
io
.
Copy
(
&
body
,
limitedBody
)
if
err
!=
nil
{
return
nil
,
err
}
return
body
.
Bytes
(),
nil
}
func
CloneRequestWithNewBody
(
r
*
http
.
Request
,
body
[]
byte
)
*
http
.
Request
{
newReq
:=
*
r
newReq
.
Body
=
ioutil
.
NopCloser
(
bytes
.
NewReader
(
body
))
return
&
newReq
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment