public function runMulti(ScenarioSet $scenarioSet, $concurrency = null)
{
$results = [];
$this->registerHandlers();
$requests = [];
foreach ($scenarioSet as $key => $scenario) {
$valueBag = new ValueBag($scenario->getValues());
$extraBag = new ValueBag();
$step = $scenario->getRoot();
$options = ['step' => $step, 'values' => $valueBag, 'extra' => $extraBag, 'http_errors' => true];
foreach ($this->extensions as $extension) {
$extension->preRun($scenario, $valueBag, $extraBag);
}
$requests[$key] = [$this->createRequest($step, $valueBag), $options, $scenario];
}
if (!$concurrency) {
$concurrency = min(count($requests), count($this->clients));
}
$this->logger and $this->logger->debug(sprintf('Concurrency set to "%d"', $concurrency));
if ($concurrency > count($this->clients)) {
throw new RuntimeException('Concurrency (%d) must be less than or equal to the number of Guzzle clients (%s)', $concurrency, count($this->clients));
}
$fulfilled = $rejected = function ($response, $key) use(&$results, $requests) {
$valueBag = $requests[$key][1]['values'];
$extraBag = $requests[$key][1]['extra'];
$scenario = $requests[$key][2];
$exception = null;
if ($response instanceof \Exception) {
$exception = $response;
$this->logger and $this->logger->error(sprintf('Scenario "%s" ended with an error: %s', $scenario->getTitle(), $exception->getMessage()));
}
foreach ($this->extensions as $extension) {
$extension->postRun($scenario, $valueBag, $extraBag);
}
$results[$key] = new Result($valueBag, $extraBag, $exception);
};
$requests = function () use($requests) {
$i = 0;
$count = count($this->clients);
foreach ($requests as $key => $data) {
$client = ++$i % $count;
$this->logger and $this->logger->info(sprintf('Starting scenario "%s" (sent to client %d)', $data[2]->getTitle(), $client));
(yield $key => $this->clients[$client]->sendAsync($data[0], $data[1]));
// cleanup cookies on the client
if ($cookieJar = $this->clients[$client]->getConfig('cookies')) {
$cookieJar->clear();
}
}
};
(new EachPromise($requests(), ['concurrency' => $concurrency, 'fulfilled' => $fulfilled, 'rejected' => $rejected]))->promise()->wait();
return $results;
}