Skip to content

Commit af802f3

Browse files
authored
feat(2798): Enable timeout configuration using options and environment variables (#81)
1 parent 1e2d91a commit af802f3

File tree

4 files changed

+173
-15
lines changed

4 files changed

+173
-15
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ COMMANDS:
2222
GLOBAL OPTIONS:
2323
--scope value Scope of command. For example: event, build, pipeline
2424
--type value Type of the command. For example: cache, artifacts, steps (default: "stable")
25+
--timeout value Specifies the timeout in seconds for commands. (default: 60(get) or 300(set,remove))
2526
--help, -h show help
2627
--version, -v print the version
2728
@@ -43,8 +44,8 @@ For example, if you want to cache the `node_modules` folder within the `event` s
4344

4445
## Dependency
4546

46-
store-cli has dependency on ZStandard (https://github.com/facebook/zstd)
47+
store-cli has dependency on ZStandard v1.4.8 (https://github.com/facebook/zstd)
4748

4849
To test locally in download binaries from screwdrivercd bintray and set path
49-
<li> mac => download zstd-cli-macosx binary from https://bintray.com/screwdrivercd/screwdrivercd/download_file?file_path=zstd-cli-1.4.8-macosx.tar.gz
50-
<li> linux => download zstd-cli-linux binary from https://bintray.com/screwdrivercd/screwdrivercd/download_file?file_path=zstd-cli-1.4.8-linux.tar.gz
50+
<li> mac => download zstd-cli-macosx binary from https://github.com/screwdriver-cd/sd-packages/releases/download/v0.0.30/zstd-cli-macosx.tar.gz
51+
<li> linux => download zstd-cli-linux binary from https://github.com/screwdriver-cd/sd-packages/releases/download/v0.0.30/zstd-cli-linux.tar.gz

sdstore/cache2disk.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ func acquireLock(path string, read bool) error {
103103
}
104104

105105
// ZStandard from https://github.com/facebook/zstd
106-
// To test in mac - download from https://bintray.com/screwdrivercd/screwdrivercd/download_file?file_path=zstd-cli-1.4.8-macosx.tar.gz and set path
107-
// To test in linux - download from https://bintray.com/screwdrivercd/screwdrivercd/download_file?file_path=zstd-cli-1.4.8-linux.tar.gz and set path
106+
// To test in mac - download from https://github.com/screwdriver-cd/sd-packages/releases/download/v0.0.30/zstd-cli-macosx.tar.gz and set path
107+
// To test in linux - download from https://github.com/screwdriver-cd/sd-packages/releases/download/v0.0.30/zstd-cli-linux.tar.gz and set path
108108
func getZstdBinary() string {
109109
switch runtime.GOOS {
110110
case "darwin":

store-cli.go

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var MAX_RETRIES = 5 // int
2424
var RETRY_WAIT_MIN = 100 // ms
2525
var RETRY_WAIT_MAX = 300 // ms
2626

27-
// http timeout for Upload/Download/Remove operations
27+
// default http timeout for Upload/Download/Remove operations
2828
var UPLOAD_HTTP_TIMEOUT = 60 // seconds
2929
var DOWNLOAD_HTTP_TIMEOUT = 300 // seconds
3030
var REMOVE_HTTP_TIMEOUT = 300 // seconds
@@ -122,7 +122,7 @@ func makeURL(storeType, scope, key string) (*url.URL, error) {
122122
return url.Parse(fullpath)
123123
}
124124

125-
func get(storeType, scope, key string) error {
125+
func get(storeType, scope, key string, timeout int) error {
126126
if skipCache(storeType, scope, "get") {
127127
return nil
128128
}
@@ -136,7 +136,7 @@ func get(storeType, scope, key string) error {
136136
if err != nil {
137137
return err
138138
}
139-
store := sdstore.NewStore(sdToken, MAX_RETRIES, DOWNLOAD_HTTP_TIMEOUT, RETRY_WAIT_MIN, RETRY_WAIT_MAX)
139+
store := sdstore.NewStore(sdToken, MAX_RETRIES, timeout, RETRY_WAIT_MIN, RETRY_WAIT_MAX)
140140

141141
var toExtract bool
142142

@@ -152,7 +152,7 @@ func get(storeType, scope, key string) error {
152152
}
153153
}
154154

155-
func set(storeType, scope, filePath string) error {
155+
func set(storeType, scope, filePath string, timeout int) error {
156156
if skipCache(storeType, scope, "set") {
157157
return nil
158158
}
@@ -166,7 +166,7 @@ func set(storeType, scope, filePath string) error {
166166
if err != nil {
167167
return err
168168
}
169-
store := sdstore.NewStore(sdToken, MAX_RETRIES, UPLOAD_HTTP_TIMEOUT, RETRY_WAIT_MIN, RETRY_WAIT_MAX)
169+
store := sdstore.NewStore(sdToken, MAX_RETRIES, timeout, RETRY_WAIT_MIN, RETRY_WAIT_MAX)
170170

171171
var toCompress bool
172172

@@ -181,7 +181,7 @@ func set(storeType, scope, filePath string) error {
181181

182182
}
183183

184-
func remove(storeType, scope, key string) error {
184+
func remove(storeType, scope, key string, timeout int) error {
185185
if skipCache(storeType, scope, "remove") {
186186
return nil
187187
}
@@ -190,7 +190,7 @@ func remove(storeType, scope, key string) error {
190190
return sdstore.Cache2Disk("remove", scope, key, CacheMaxSizeInMB)
191191
} else {
192192
sdToken := os.Getenv("SD_TOKEN")
193-
store := sdstore.NewStore(sdToken, MAX_RETRIES, REMOVE_HTTP_TIMEOUT, RETRY_WAIT_MIN, RETRY_WAIT_MAX)
193+
store := sdstore.NewStore(sdToken, MAX_RETRIES, timeout, RETRY_WAIT_MIN, RETRY_WAIT_MAX)
194194

195195
if storeType == "cache" {
196196
md5URL, err := makeURL(storeType, scope, fmt.Sprintf("%s%s", filepath.Clean(key), "_md5.json"))
@@ -225,6 +225,22 @@ func remove(storeType, scope, key string) error {
225225
}
226226
}
227227

228+
func getTimeout(flagTimeout string, envValue string, defaultTimeout int) (int, error) {
229+
230+
if flagTimeout != "" {
231+
flagTimeoutInt, err := strconv.Atoi(flagTimeout)
232+
return flagTimeoutInt, err
233+
}
234+
235+
envTimeout := os.Getenv(envValue)
236+
if envTimeout != "" {
237+
envTimeoutInt, err := strconv.Atoi(envTimeout)
238+
return envTimeoutInt, err
239+
}
240+
241+
return defaultTimeout, nil
242+
}
243+
228244
func main() {
229245
defer finalRecover()
230246

@@ -247,6 +263,11 @@ func main() {
247263
Usage: "Type of the command. For example: cache, artifacts, steps",
248264
Value: "stable",
249265
},
266+
cli.StringFlag{
267+
Name: "timeout",
268+
Usage: "Specifies the timeout in seconds.",
269+
Value: "",
270+
},
250271
}
251272

252273
app.Commands = []cli.Command{
@@ -259,8 +280,12 @@ func main() {
259280
}
260281
scope := strings.ToLower(c.String("scope"))
261282
storeType := strings.ToLower(c.String("type"))
283+
timeout, err := getTimeout(c.String("timeout"), "SD_STORE_CLI_DOWNLOAD_HTTP_TIMEOUT", DOWNLOAD_HTTP_TIMEOUT)
284+
if err != nil {
285+
failureExit(err)
286+
}
262287
key := c.Args().Get(0)
263-
err := get(storeType, scope, key)
288+
err = get(storeType, scope, key, timeout)
264289
if err != nil {
265290
failureExit(err)
266291
}
@@ -278,8 +303,12 @@ func main() {
278303
}
279304
scope := strings.ToLower(c.String("scope"))
280305
storeType := strings.ToLower(c.String("type"))
306+
timeout, err := getTimeout(c.String("timeout"), "SD_STORE_CLI_UPLOAD_HTTP_TIMEOUT", UPLOAD_HTTP_TIMEOUT)
307+
if err != nil {
308+
failureExit(err)
309+
}
281310
key := c.Args().Get(0)
282-
err := set(storeType, scope, key)
311+
err = set(storeType, scope, key, timeout)
283312
if err != nil {
284313
failureExit(err)
285314
}
@@ -297,8 +326,12 @@ func main() {
297326
}
298327
scope := strings.ToLower(c.String("scope"))
299328
storeType := strings.ToLower(c.String("type"))
329+
timeout, err := getTimeout(c.String("timeout"), "SD_STORE_CLI_REMOVE_HTTP_TIMEOUT", REMOVE_HTTP_TIMEOUT)
330+
if err != nil {
331+
failureExit(err)
332+
}
300333
key := c.Args().Get(0)
301-
err := remove(storeType, scope, key)
334+
err = remove(storeType, scope, key, timeout)
302335
if err != nil {
303336
failureExit(err)
304337
}

store-cli_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,127 @@ func TestMakeURL(t *testing.T) {
100100
t.Fatalf("Expected error, got nil")
101101
}
102102
}
103+
104+
func TestGetTimeout(t *testing.T) {
105+
testCases := []struct {
106+
name string
107+
flagTimeout string
108+
envName string
109+
defaultTimeout int
110+
expected int
111+
envValue string
112+
shouldError bool
113+
}{
114+
{
115+
name: "use flag timeout",
116+
flagTimeout: "50",
117+
envName: "SD_STORE_CLI_DOWNLOAD_HTTP_TIMEOUT",
118+
defaultTimeout: 60,
119+
expected: 50,
120+
envValue: "",
121+
shouldError: false,
122+
},
123+
{
124+
name: "use environment timeout",
125+
flagTimeout: "",
126+
envName: "SD_STORE_CLI_DOWNLOAD_HTTP_TIMEOUT",
127+
defaultTimeout: 60,
128+
expected: 70,
129+
envValue: "70",
130+
shouldError: false,
131+
},
132+
{
133+
name: "use default upload timeout",
134+
flagTimeout: "",
135+
envName: "SD_STORE_CLI_UPLOAD_HTTP_TIMEOUT",
136+
defaultTimeout: UPLOAD_HTTP_TIMEOUT,
137+
expected: 60,
138+
envValue: "",
139+
shouldError: false,
140+
},
141+
{
142+
name: "use default download timeout",
143+
flagTimeout: "",
144+
envName: "SD_STORE_CLI_DOWNLOAD_HTTP_TIMEOUT",
145+
defaultTimeout: DOWNLOAD_HTTP_TIMEOUT,
146+
expected: 300,
147+
envValue: "",
148+
shouldError: false,
149+
},
150+
{
151+
name: "use default remove timeout",
152+
flagTimeout: "",
153+
envName: "SD_STORE_CLI_REMOVE_HTTP_TIMEOUT",
154+
defaultTimeout: REMOVE_HTTP_TIMEOUT,
155+
expected: 300,
156+
envValue: "",
157+
shouldError: false,
158+
},
159+
{
160+
name: "set flagTimeout to zero",
161+
flagTimeout: "0",
162+
envName: "SD_STORE_CLI_UPLOAD_HTTP_TIMEOUT",
163+
defaultTimeout: UPLOAD_HTTP_TIMEOUT,
164+
expected: 0,
165+
envValue: "",
166+
shouldError: false,
167+
},
168+
{
169+
name: "set envValue to zero",
170+
flagTimeout: "",
171+
envName: "SD_STORE_CLI_UPLOAD_HTTP_TIMEOUT",
172+
defaultTimeout: UPLOAD_HTTP_TIMEOUT,
173+
expected: 0,
174+
envValue: "0",
175+
shouldError: false,
176+
},
177+
{
178+
name: "Error case set flagTimeout to string",
179+
flagTimeout: "dummystring",
180+
envName: "SD_STORE_CLI_UPLOAD_HTTP_TIMEOUT",
181+
defaultTimeout: UPLOAD_HTTP_TIMEOUT,
182+
expected: 0,
183+
envValue: "",
184+
shouldError: true,
185+
},
186+
{
187+
name: "Error case set envValue to string",
188+
flagTimeout: "",
189+
envName: "SD_STORE_CLI_UPLOAD_HTTP_TIMEOUT",
190+
defaultTimeout: UPLOAD_HTTP_TIMEOUT,
191+
expected: 0,
192+
envValue: "dummystring",
193+
shouldError: true,
194+
},
195+
}
196+
197+
for _, tc := range testCases {
198+
t.Run(tc.name, func(t *testing.T) {
199+
if tc.envValue != "" {
200+
os.Setenv(tc.envName, tc.envValue)
201+
}
202+
203+
got, err := getTimeout(tc.flagTimeout, tc.envName, tc.defaultTimeout)
204+
205+
if err != nil {
206+
if tc.shouldError {
207+
return
208+
}
209+
t.Fatalf("getTimeout() error = %v", err)
210+
return
211+
}
212+
213+
// If we reach here, the test get error.
214+
if tc.shouldError {
215+
t.Fatal("getTimeout() expected an error, but got nil")
216+
}
217+
218+
if got != tc.expected {
219+
t.Fatalf("getTimeout() got = %v, want %v", got, tc.expected)
220+
}
221+
222+
// Clear environment value for the next test case.
223+
os.Unsetenv(tc.envName)
224+
})
225+
}
226+
}

0 commit comments

Comments
 (0)