@@ -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+
236255func (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
284302func (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
298320func (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.
314378func (h SchedulerApiHandler ) resolveOwnerScope (ctx common.ExtendedContext , w http.ResponseWriter , r * http.Request , symbol * string ) ([]string , bool ) {
0 commit comments