runMultiple<R, P> method

List<FutureOr<R>> runMultiple<R, P>(
  1. int count,
  2. FutureOr<R> function(
    1. P argument
    ),
  3. P argument, {
  4. Duration? timeout,
  5. FutureOr<R> onTimeout()?,
  6. int load = 100,
})

Execute the same function in the least loaded count isolates.

This guarantees that the function isn't run twice in the same isolate, so count is not allowed to exceed length.

The optional load parameter represents the load that the command is causing on the isolate where it runs. The number has no fixed meaning, but should be seen as relative to other commands run in the same load balancer. The load must not be negative.

If timeout and onTimeout are provided, they are forwarded to the runners running the function, which will handle any timeouts as normal.

Implementation

List<FutureOr<R>> runMultiple<R, P>(
    int count, FutureOr<R> Function(P argument) function, P argument,
    {Duration? timeout, FutureOr<R> Function()? onTimeout, int load = 100}) {
  RangeError.checkValueInInterval(count, 1, length, 'count');
  RangeError.checkNotNegative(load, 'load');
  if (count == 1) {
    return List<FutureOr<R>>.filled(
        1,
        run(function, argument,
            load: load, timeout: timeout, onTimeout: onTimeout));
  }
  final placeholderFuture = Future<R>.value();
  final result = List<FutureOr<R>>.filled(count, placeholderFuture);
  if (count == length) {
    // No need to change the order of entries in the queue.
    _queue.unorderedElements.mapIndexed((index, entry) {
      entry.load += load;
      result[index] =
          entry.run(this, load, function, argument, timeout, onTimeout);
    }).forEach(ignore);
  } else {
    // Remove the [count] least loaded services and run the
    // command on each, then add them back to the queue.
    // This avoids running the same command twice in the same
    // isolate.
    // We can't assume that the first [count] entries in the
    // heap list are the least loaded.
    var entries = List<_LoadBalancerEntry>.generate(
      count,
      (_) => _queue.removeFirst(),
      growable: false,
    );
    for (var i = 0; i < count; i++) {
      var entry = entries[i];
      entry.load += load;
      _queue.add(entry);
      result[i] =
          entry.run(this, load, function, argument, timeout, onTimeout);
    }
  }
  return result;
}