package common import ( "context" "time" "github.com/gogf/gf/v2/errors/gerror" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/consts" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/dao" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model/entity" ) const ( singleBatchWaitTimeout = 60 * time.Second singleBatchPollInterval = 500 * time.Millisecond ) func (s *sCommon) waitBatchCompletion(ctx context.Context, tenantID string, deptID int64, batchNo string) (int, error) { deadline := time.Now().Add(singleBatchWaitTimeout) for { status, err := s.loadBatchAsyncStatus(ctx, tenantID, deptID, batchNo) if err != nil { return 0, err } switch status { case consts.BatchAsyncStatusSuccess, consts.BatchAsyncStatusFailed, consts.BatchAsyncStatusPartialSuccess: return status, nil } remaining := time.Until(deadline) if remaining <= 0 { return 0, gerror.Newf("batch %s execution timed out; query batch status for the result", batchNo) } wait := singleBatchPollInterval if remaining < wait { wait = remaining } timer := time.NewTimer(wait) select { case <-ctx.Done(): if !timer.Stop() { <-timer.C } return 0, gerror.Wrap(ctx.Err(), "request canceled while waiting for batch completion") case <-timer.C: } } } func (s *sCommon) loadBatchAsyncStatus(ctx context.Context, tenantID string, deptID int64, batchNo string) (int, error) { columns := dao.BatchMain.Columns() var batch entity.BatchMain err := dao.BatchMain.Ctx(ctx). Where(columns.TenantId, tenantID). Where(columns.DeptId, deptID). Where(columns.BatchNo, batchNo). Scan(&batch) if err != nil { return 0, gerror.Wrap(err, "failed to query batch execution status") } if batch.Id == 0 { return 0, gerror.Newf("batch %s does not exist or is not accessible", batchNo) } return batch.BatchAsyncStatus, nil }