Skip to content

Commit df79df2

Browse files
committed
add sync modes for copy and delete, always use background context instead of request context
1 parent 283d539 commit df79df2

File tree

5 files changed

+59
-13
lines changed

5 files changed

+59
-13
lines changed

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ zipserver copy --key path/to/file.zip --target s3backup
141141

142142
**HTTP API:**
143143
```bash
144+
# Sync mode (waits for completion)
145+
curl "http://localhost:8090/copy?key=path/to/file.zip&target=s3backup"
146+
147+
# Async mode (returns immediately, notifies callback when done)
144148
curl "http://localhost:8090/copy?key=path/to/file.zip&target=s3backup&callback=http://example.com/done"
145149
```
146150

@@ -155,6 +159,13 @@ zipserver delete --key file1.zip --key file2.zip --target s3backup
155159

156160
**HTTP API:**
157161
```bash
162+
# Sync mode (waits for completion)
163+
curl -X POST "http://localhost:8090/delete" \
164+
-d "keys[]=file1.zip" \
165+
-d "keys[]=file2.zip" \
166+
-d "target=s3backup"
167+
168+
# Async mode (returns immediately, notifies callback when done)
158169
curl -X POST "http://localhost:8090/delete" \
159170
-d "keys[]=file1.zip" \
160171
-d "keys[]=file2.zip" \
@@ -265,8 +276,8 @@ Some HTTP handlers support callbacks to notify your application when long-runnin
265276
|----------|-----------|---------------------|
266277
| `/extract` | `async` | Yes (omit `async` for sync) |
267278
| `/slurp` | `async` | Yes (omit `async` for sync) |
268-
| `/copy` | `callback` | No (always async) |
269-
| `/delete` | `callback` | No (always async) |
279+
| `/copy` | `callback` | Yes (omit `callback` for sync) |
280+
| `/delete` | `callback` | Yes (omit `callback` for sync) |
270281

271282
### How It Works
272283

zipserver/copy_handler.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,7 @@ func copyHandler(w http.ResponseWriter, r *http.Request) error {
144144
return err
145145
}
146146

147-
callbackURL, err := getParam(params, "callback")
148-
if err != nil {
149-
return err
150-
}
147+
callbackURL := params.Get("callback")
151148

152149
targetName, err := getParam(params, "target")
153150
if err != nil {
@@ -177,6 +174,28 @@ func copyHandler(w http.ResponseWriter, r *http.Request) error {
177174
ExpectedBucket: expectedBucket,
178175
}
179176

177+
// sync codepath
178+
if callbackURL == "" {
179+
defer copyLockTable.releaseKey(lockKey)
180+
181+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(globalConfig.JobTimeout))
182+
defer cancel()
183+
184+
result := ops.Copy(ctx, copyParams)
185+
if result.Err != nil {
186+
return writeJSONError(w, "CopyError", result.Err)
187+
}
188+
189+
return writeJSONMessage(w, struct {
190+
Success bool
191+
Key string
192+
Duration string
193+
Size int64
194+
Md5 string
195+
}{true, result.Key, result.Duration, result.Size, result.Md5})
196+
}
197+
198+
// async codepath
180199
go (func() {
181200
defer copyLockTable.releaseKey(lockKey)
182201

zipserver/delete_handler.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,7 @@ func deleteHandler(w http.ResponseWriter, r *http.Request) error {
210210

211211
params := r.Form
212212

213-
callbackURL, err := getParam(params, "callback")
214-
if err != nil {
215-
return err
216-
}
213+
callbackURL := params.Get("callback")
217214

218215
// target is optional; if not provided, delete from primary storage (restricted to ExtractPrefix)
219216
// Validation of target and prefix constraints is handled by Operations.Delete
@@ -225,6 +222,25 @@ func deleteHandler(w http.ResponseWriter, r *http.Request) error {
225222
TargetName: targetName,
226223
}
227224

225+
// sync codepath
226+
if callbackURL == "" {
227+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(globalConfig.JobTimeout))
228+
defer cancel()
229+
230+
result := ops.Delete(ctx, deleteParams)
231+
if result.Err != nil {
232+
return writeJSONError(w, "DeleteError", result.Err)
233+
}
234+
235+
return writeJSONMessage(w, struct {
236+
Success bool
237+
TotalKeys int
238+
DeletedKeys int
239+
Errors []DeleteError
240+
}{len(result.Errors) == 0, result.TotalKeys, result.DeletedKeys, result.Errors})
241+
}
242+
243+
// async codepath
228244
go func() {
229245
jobCtx, cancel := context.WithTimeout(context.Background(), time.Duration(globalConfig.JobTimeout))
230246
defer cancel()

zipserver/extract_handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ func extractHandler(w http.ResponseWriter, r *http.Request) error {
182182
if asyncURL == "" {
183183
defer extractLockTable.releaseKey(lockKey)
184184

185-
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(globalConfig.JobTimeout))
186-
defer cancel()
185+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(globalConfig.JobTimeout))
186+
defer cancel()
187187

188188
result := ops.Extract(ctx, extractParams)
189189
if result.Err != nil {

zipserver/slurp_handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func slurpHandler(w http.ResponseWriter, r *http.Request) error {
159159

160160
asyncURL := params.Get("async")
161161
if asyncURL == "" {
162-
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(globalConfig.JobTimeout))
162+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(globalConfig.JobTimeout))
163163
defer cancel()
164164

165165
err = process(ctx)

0 commit comments

Comments
 (0)