/
header.go
157 lines (125 loc) · 4.21 KB
/
header.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package appengine
import (
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"time"
)
// ErrNotFoundHeader is Cloud Tasks の Headerがない時に利用されます。
var ErrNotFoundHeader = errors.New("not found cloudtasks header")
const (
// AppEngineTaskName Header Key
AppEngineTaskName = "X-AppEngine-TaskName"
// AppEngineQueueName Header Key
AppEngineQueueName = "X-AppEngine-QueueName"
// AppEngineTaskRetryCount Header Key
AppEngineTaskRetryCount = "X-AppEngine-TaskRetryCount"
// AppEngineTaskExecutionCount Header Key
AppEngineTaskExecutionCount = "X-AppEngine-TaskExecutionCount"
// AppEngineTaskETA Header Key
AppEngineTaskETA = "X-AppEngine-TaskETA"
// AppEngineTaskPreviousResponse Header Key
AppEngineTaskPreviousResponse = "X-AppEngine-TaskPreviousResponse"
// AppEngineTaskRetryReason Header Key
AppEngineTaskRetryReason = "X-AppEngine-TaskRetryReason"
// AppEngineFailFast Header Key
AppEngineFailFast = "X-AppEngine-FailFast"
// GoogleInternalSkipAdminCheck Header Key
GoogleInternalSkipAdminCheck = "X-Google-Internal-Skipadmincheck"
)
// Header is App Engine task handlers
// plz see https://cloud.google.com/tasks/docs/creating-appengine-handlers
type Header struct {
// QueueName is The name of the queue.
// Always there
QueueName string
// TaskName is The "short" name of the task, or, if no name was specified at creation, a unique system-generated id.
// This is the 'my-task-id' value in the complete task name, ie, task_name = projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/my-task-id.
// Always there
TaskName string
// TaskRetryCount is The number of times this task has been retried.
// For the first attempt, this value is 0.
// This number includes attempts where the task failed due to a lack of available instances and never reached the execution phase.
// Always there
TaskRetryCount int64
// TaskExecutionCount is The total number of times that the task has received a response from the handler.
// Since Cloud Tasks deletes the task once a successful response has been received, all previous handler responses were failures.
// This number does not include failures due to a lack of available instances.
// Always there
TaskExecutionCount int64
// TaskEAT is The schedule time of the task
// Always there
TaskETA time.Time
// TaskPreviousResponse is The HTTP response code from the previous retry.
// optional
TaskPreviousResponse string
// TaskRetryReason is The reason for retrying the task.
// optional
TaskRetryReason string
// FailFast is Indicates that a task fails immediately if an existing instance is not available.
// optional
FailFast bool
}
// GetHeader return App Engine task header
func GetHeader(r *http.Request) (*Header, error) {
var ret Header
v := r.Header.Get(GoogleInternalSkipAdminCheck)
if v != "true" {
return nil, ErrNotFoundHeader
}
v = r.Header.Get(AppEngineTaskName)
if len(v) > 0 {
ret.TaskName = v
}
v = r.Header.Get(AppEngineQueueName)
if len(v) > 0 {
ret.QueueName = v
}
v = r.Header.Get(AppEngineTaskRetryCount)
if len(v) > 0 {
i, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid %s. v=%v", AppEngineTaskRetryCount, v)
}
ret.TaskRetryCount = i
}
v = r.Header.Get(AppEngineTaskExecutionCount)
if len(v) > 0 {
i, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid %s. v=%v", AppEngineTaskExecutionCount, v)
}
ret.TaskExecutionCount = i
}
v = r.Header.Get(AppEngineTaskETA)
if len(v) > 0 {
l := strings.Split(v, ".")
if len(l) < 2 {
return nil, fmt.Errorf("invalid %s. v=%v", AppEngineTaskETA, v)
}
sec, err := strconv.ParseInt(l[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid %s. v=%v", AppEngineTaskETA, v)
}
microsec, err := strconv.ParseInt(l[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid %s. v=%v", AppEngineTaskETA, v)
}
ret.TaskETA = time.Unix(sec, microsec*1000)
}
v = r.Header.Get(AppEngineTaskPreviousResponse)
if len(v) > 0 {
ret.TaskPreviousResponse = v
}
v = r.Header.Get(AppEngineTaskRetryReason)
if len(v) > 0 {
ret.TaskRetryReason = v
}
v = r.Header.Get(AppEngineFailFast)
if len(v) > 0 {
ret.FailFast = true
}
return &ret, nil
}