dispatchTask dispatches tasks for the callers of popTask. At least one dispatcher is required in order to use popTask. The tasks are moved from InputTaskKey(k) to WaitingTaskKey(k). Once the task should be dispatched, it is moved form WaitingTaskKey(k) to ReadyTaskKey(k). group is the consumer group
( ctx context.Context, r redis.Cmdable, group, consumer string, maxLen int64, k string, blockLimit time.Duration, )
| 482 | // maxLen represents the maximum size of the streams used for dispatching. |
| 483 | // minIdleTime is used for automatic task reclaiming. Only tasks older than minIdleTime will be redispatched from the input stream to the waiting stream. |
| 484 | func dispatchTask( |
| 485 | ctx context.Context, |
| 486 | r redis.Cmdable, |
| 487 | group, consumer string, |
| 488 | maxLen int64, |
| 489 | k string, |
| 490 | blockLimit time.Duration, |
| 491 | ) error { |
| 492 | var ( |
| 493 | readyStream = ReadyTaskKey(k) |
| 494 | inputStream = InputTaskKey(k) |
| 495 | waitingStream = WaitingTaskKey(k) |
| 496 | ) |
| 497 | for { |
| 498 | ret, err := dispatchTaskScript.Run( |
| 499 | ctx, |
| 500 | r, |
| 501 | []string{readyStream, inputStream, waitingStream}, |
| 502 | group, |
| 503 | consumer, |
| 504 | time.Now().UnixNano(), |
| 505 | maxLen, |
| 506 | ).Result() |
| 507 | if err != nil && !errors.Is(err, redis.Nil) { |
| 508 | return ConvertError(err) |
| 509 | } |
| 510 | |
| 511 | block := blockLimit |
| 512 | if ret != nil { |
| 513 | s, ok := ret.(string) |
| 514 | if !ok { |
| 515 | return errInvalidKeyValueType.WithAttributes("key", nextAtKey).WithCause(err) |
| 516 | } |
| 517 | nextAt, err := parseTime(s) |
| 518 | if err != nil { |
| 519 | return errInvalidKeyValueType.WithAttributes("key", nextAtKey).WithCause(err) |
| 520 | } |
| 521 | if nextAt.IsZero() { |
| 522 | block = -1 |
| 523 | } else { |
| 524 | now := time.Now() |
| 525 | if nextAt.Before(now) { |
| 526 | continue |
| 527 | } |
| 528 | // If we have a task that we may dispatch into the future, we will block the |
| 529 | // input stream only for the duration between the current time and that future |
| 530 | // time. |
| 531 | if d := nextAt.Sub(now); block == 0 || d < block { |
| 532 | block = d |
| 533 | } |
| 534 | } |
| 535 | } |
| 536 | |
| 537 | _, err = r.XReadGroup(ctx, &redis.XReadGroupArgs{ |
| 538 | Group: group, |
| 539 | Consumer: consumer, |
| 540 | Streams: []string{inputStream, ">"}, |
| 541 | Count: 1, |
no test coverage detected