Skip to content

Commit 80a1cdd

Browse files
authored
Check the batch action is not running when removing, cascade events (#687)
* Check the batch action is not running when removing, cascade events * CoPilot
1 parent 30b6adb commit 80a1cdd

9 files changed

Lines changed: 432 additions & 81 deletions

File tree

broker/oapi/open-api.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,6 +2665,12 @@ paths:
26652665
application/json:
26662666
schema:
26672667
$ref: '#/components/schemas/Error'
2668+
'409':
2669+
description: Batch action is queued or being processed
2670+
content:
2671+
application/json:
2672+
schema:
2673+
$ref: '#/components/schemas/Error'
26682674
'500':
26692675
description: Internal Server Error
26702676
content:

broker/scheduler/api/api_handler.go

Lines changed: 93 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ func (h SchedulerApiHandler) getScheduledTask(w http.ResponseWriter, r *http.Req
198198
brokerapi.AddInternalError(ctx, w, err)
199199
return sched_db.ScheduledTask{}, ctx, true
200200
}
201-
if task.ActionData.BatchActionData == nil {
202-
brokerapi.AddInternalError(ctx, w, errors.New("missing batchActionData"))
201+
if err := validateBatchActionTask(task); err != nil {
202+
brokerapi.AddInternalError(ctx, w, err)
203203
return sched_db.ScheduledTask{}, ctx, true
204204
}
205205
return task, ctx, false
@@ -216,26 +216,48 @@ func (h SchedulerApiHandler) DeleteBatchActionsId(w http.ResponseWriter, r *http
216216
}
217217

218218
err := h.schedRepo.WithTxFunc(ctx, func(schedRepo sched_db.SchedRepo) error {
219-
task, inErr := schedRepo.GetScheduledTaskById(ctx, id, owners)
219+
task, inErr := schedRepo.GetScheduledTaskByIdForUpdate(ctx, id, owners)
220+
if inErr != nil {
221+
return inErr
222+
}
223+
if inErr = validateBatchActionTask(task); inErr != nil {
224+
return inErr
225+
}
226+
active, inErr := schedRepo.HasActiveBatchActionEvents(ctx, task.ID)
220227
if inErr != nil {
221228
return inErr
222229
}
230+
if active {
231+
return errBatchActionInProgress
232+
}
233+
if inErr = schedRepo.DeleteBatchActionEvents(ctx, task.ID); inErr != nil {
234+
return inErr
235+
}
223236
return schedRepo.DeleteScheduledTask(ctx, task.ID, owners)
224237
})
225238
if err != nil {
226239
if errors.Is(err, pgx.ErrNoRows) {
227240
brokerapi.AddNotFoundError(w)
228241
return
229242
}
243+
if errors.Is(err, errBatchActionInProgress) {
244+
brokerapi.WriteJsonErrorResponse(w, err, http.StatusConflict)
245+
return
246+
}
230247
brokerapi.AddInternalError(ctx, w, err)
231248
return
232249
}
233250
w.WriteHeader(http.StatusNoContent)
234251
}
235252

253+
var errBatchActionInProgress = errors.New("batch action is currently queued or being processed")
254+
236255
func (h SchedulerApiHandler) PutBatchActionsId(w http.ResponseWriter, r *http.Request, id string, params schedoapi.PutBatchActionsIdParams) {
237-
task, ctx, done := h.getScheduledTask(w, r, "PutBatchActionsId", id, params.Symbol)
238-
if done {
256+
ctx := common.CreateExtCtxWithArgs(r.Context(), &common.LoggerArgs{
257+
Other: map[string]string{"method": "PutBatchActionsId", "id": id},
258+
})
259+
owners, ok := h.resolveOwnerScope(ctx, w, r, params.Symbol)
260+
if !ok {
239261
return
240262
}
241263
if r.Body == nil || r.Body == http.NoBody {
@@ -260,55 +282,97 @@ func (h SchedulerApiHandler) PutBatchActionsId(w http.ResponseWriter, r *http.Re
260282
brokerapi.AddBadRequestError(ctx, w, err)
261283
return
262284
}
263-
task.Schedule = update.Schedule
264-
task.RunAt = next
265-
if task.ActionData.BatchActionData == nil {
266-
task.ActionData.BatchActionData = &events.BatchActionData{}
267-
}
268-
task.ActionData.BatchActionData.Selector = update.BatchQuery
269-
task.Title = toPgText(update.Title)
270-
271-
if update.ActionParams != nil {
272-
task.ActionData.CustomData = *update.ActionParams
273-
}
274-
275-
task, err = h.schedRepo.SaveScheduledTask(ctx, sched_db.SaveScheduledTaskParams(task))
285+
task, err := h.mutateScheduledTask(ctx, id, owners, func(task *sched_db.ScheduledTask) {
286+
task.Schedule = update.Schedule
287+
task.RunAt = next
288+
task.ActionData.BatchActionData.Selector = update.BatchQuery
289+
task.Title = toPgText(update.Title)
290+
if update.ActionParams != nil {
291+
task.ActionData.CustomData = *update.ActionParams
292+
}
293+
})
276294
if err != nil {
277-
brokerapi.AddInternalError(ctx, w, err)
295+
h.writeScheduledTaskMutationError(ctx, w, err)
278296
return
279297
}
280298

281299
brokerapi.WriteJsonResponse(w, toBatchAction(r, task))
282300
}
283301

284302
func (h SchedulerApiHandler) PostBatchActionsIdDisable(w http.ResponseWriter, r *http.Request, id string, params schedoapi.PostBatchActionsIdDisableParams) {
285-
task, ctx, done := h.getScheduledTask(w, r, "PostBatchActionsIdDisable", id, params.Symbol)
286-
if done {
303+
ctx := common.CreateExtCtxWithArgs(r.Context(), &common.LoggerArgs{
304+
Other: map[string]string{"method": "PostBatchActionsIdDisable", "id": id},
305+
})
306+
owners, ok := h.resolveOwnerScope(ctx, w, r, params.Symbol)
307+
if !ok {
287308
return
288309
}
289-
task.Status = sched_db.ScheduledTaskStatusStopped
290-
_, err := h.schedRepo.SaveScheduledTask(ctx, sched_db.SaveScheduledTaskParams(task))
310+
_, err := h.mutateScheduledTask(ctx, id, owners, func(task *sched_db.ScheduledTask) {
311+
task.Status = sched_db.ScheduledTaskStatusStopped
312+
})
291313
if err != nil {
292-
brokerapi.AddInternalError(ctx, w, err)
314+
h.writeScheduledTaskMutationError(ctx, w, err)
293315
return
294316
}
295317
w.WriteHeader(http.StatusNoContent)
296318
}
297319

298320
func (h SchedulerApiHandler) PostBatchActionsIdEnable(w http.ResponseWriter, r *http.Request, id string, params schedoapi.PostBatchActionsIdEnableParams) {
299-
task, ctx, done := h.getScheduledTask(w, r, "PostBatchActionsIdEnable", id, params.Symbol)
300-
if done {
321+
ctx := common.CreateExtCtxWithArgs(r.Context(), &common.LoggerArgs{
322+
Other: map[string]string{"method": "PostBatchActionsIdEnable", "id": id},
323+
})
324+
owners, ok := h.resolveOwnerScope(ctx, w, r, params.Symbol)
325+
if !ok {
301326
return
302327
}
303-
task.Status = sched_db.ScheduledTaskStatusPending
304-
_, err := h.schedRepo.SaveScheduledTask(ctx, sched_db.SaveScheduledTaskParams(task))
328+
_, err := h.mutateScheduledTask(ctx, id, owners, func(task *sched_db.ScheduledTask) {
329+
task.Status = sched_db.ScheduledTaskStatusPending
330+
})
305331
if err != nil {
306-
brokerapi.AddInternalError(ctx, w, err)
332+
h.writeScheduledTaskMutationError(ctx, w, err)
307333
return
308334
}
309335
w.WriteHeader(http.StatusNoContent)
310336
}
311337

338+
func (h SchedulerApiHandler) mutateScheduledTask(
339+
ctx common.ExtendedContext,
340+
id string,
341+
owners []string,
342+
mutate func(*sched_db.ScheduledTask),
343+
) (sched_db.ScheduledTask, error) {
344+
var task sched_db.ScheduledTask
345+
err := h.schedRepo.WithTxFunc(ctx, func(repo sched_db.SchedRepo) error {
346+
var inErr error
347+
task, inErr = repo.GetScheduledTaskByIdForUpdate(ctx, id, owners)
348+
if inErr != nil {
349+
return inErr
350+
}
351+
if inErr = validateBatchActionTask(task); inErr != nil {
352+
return inErr
353+
}
354+
mutate(&task)
355+
task, inErr = repo.SaveScheduledTask(ctx, sched_db.SaveScheduledTaskParams(task))
356+
return inErr
357+
})
358+
return task, err
359+
}
360+
361+
func validateBatchActionTask(task sched_db.ScheduledTask) error {
362+
if task.ActionData.BatchActionData == nil {
363+
return errors.New("missing batchActionData")
364+
}
365+
return nil
366+
}
367+
368+
func (h SchedulerApiHandler) writeScheduledTaskMutationError(ctx common.ExtendedContext, w http.ResponseWriter, err error) {
369+
if errors.Is(err, pgx.ErrNoRows) {
370+
brokerapi.AddNotFoundError(w)
371+
return
372+
}
373+
brokerapi.AddInternalError(ctx, w, err)
374+
}
375+
312376
// resolveOwnerScope returns the owners the request may access. A nil scope
313377
// means unrestricted master access.
314378
func (h SchedulerApiHandler) resolveOwnerScope(ctx common.ExtendedContext, w http.ResponseWriter, r *http.Request, symbol *string) ([]string, bool) {

0 commit comments

Comments
 (0)