package orbit import ( "context" "errors" "net/url" "strconv" "strings" "time" "unicode/utf8" ) // ListTasks 查询同一队列内的任务摘要,筛选固定后沿NextCursor分页;不承诺跨页快照。 func (c *Client) ListTasks(ctx context.Context, in ListTasksRequest) (TaskPage, error) { var out TaskPage if !validID(in.QueueID) || in.Limit < 0 || in.Limit > 100 || len(in.Cursor) > 1024 { return out, errors.New("invalid task query queue or page") } switch in.State { case "", TaskWaiting, TaskLeased, TaskRunning, TaskNeedsReview, TaskSucceeded, TaskFailed, TaskCancelled: default: return out, errors.New("invalid task state") } if !utf8.ValidString(in.BusinessKey) || utf8.RuneCountInString(in.BusinessKey) > 191 || strings.ContainsAny(in.BusinessKey, "\x00\r\n") { return out, errors.New("invalid business key filter") } q := url.Values{} q.Set("queue_id", in.QueueID) if in.State != "" { q.Set("state", string(in.State)) } if in.BusinessKey != "" { q.Set("business_key", in.BusinessKey) } if in.Limit != 0 { q.Set("limit", strconv.Itoa(in.Limit)) } if in.Cursor != "" { q.Set("cursor", in.Cursor) } for name, field := range map[string]*time.Time{"created_from": in.CreatedFrom, "created_before": in.CreatedBefore} { if field == nil { continue } v := field.UTC() if v.Year() < 2000 || v.Year() > 9998 || v.Nanosecond()%1000 != 0 { return out, errors.New("invalid task creation bound") } q.Set(name, v.Format(time.RFC3339Nano)) } if in.CreatedFrom != nil && in.CreatedBefore != nil && !in.CreatedFrom.Before(*in.CreatedBefore) { return out, errors.New("created_from must be before created_before") } err := c.call(ctx, "GET", "/v1/tasks?"+q.Encode(), "", nil, &out) return out, err }