Repository navigation
Expand file tree
/
Copy pathSequentialExchangeSelector.php
More file actions
67 lines (55 loc) · 2.46 KB
/
Copy pathSequentialExchangeSelector.php
File metadata and controls
67 lines (55 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
declare(strict_types=1);
namespace CleatSquad\HttpReplay\Selector;
use CleatSquad\HttpReplay\Contract\ExchangeSelectorInterface;
use CleatSquad\HttpReplay\Contract\RequestMatcherInterface;
use CleatSquad\HttpReplay\Model\ExchangeSelectionResult;
use CleatSquad\HttpReplay\Model\MatchResult;
use Psr\Http\Message\RequestInterface;
final class SequentialExchangeSelector implements ExchangeSelectorInterface
{
/** @var (\Closure(): int)|null */
private ?\Closure $clock;
/**
* @param ?int $exchangeTtl Time-to-live in seconds for an exchange.
* @param ?(\Closure(): int) $clock Custom clock callable for testing.
*/
public function __construct(
private ?int $exchangeTtl = null,
?\Closure $clock = null,
) {
$this->clock = $clock;
}
public function select(
RequestInterface $request,
array $exchanges,
array $consumedIndices,
RequestMatcherInterface $matcher
): ExchangeSelectionResult {
// Next sequential index is equal to the number of consumed exchanges in sequential mode
$currentIndex = count($consumedIndices);
$totalExchanges = count($exchanges);
if (!array_key_exists($currentIndex, $exchanges)) {
$differences = ['index' => sprintf('Cassette sequence exhausted: index %d requested, total exchanges: %d', $currentIndex, $totalExchanges)];
return ExchangeSelectionResult::exhausted($currentIndex, MatchResult::mismatch($differences));
}
$recordedExchange = $exchanges[$currentIndex];
$now = $this->clock !== null ? ($this->clock)() : time();
if ($this->exchangeTtl !== null && $this->exchangeTtl > 0 && $recordedExchange->isExpired($this->exchangeTtl, $now)) {
$matchResult = MatchResult::mismatch([
'ttl' => sprintf(
'Exchange at index %d has expired (recorded at %d, TTL %d seconds)',
$currentIndex,
(int) $recordedExchange->recordedAt(),
$this->exchangeTtl
),
]);
return ExchangeSelectionResult::mismatch($currentIndex, $matchResult, 1);
}
$matchResult = $matcher->match($request, $recordedExchange);
if ($matchResult->matched()) {
return ExchangeSelectionResult::match($currentIndex, $recordedExchange, $matchResult, 1);
}
return ExchangeSelectionResult::mismatch($currentIndex, $matchResult, 1);
}
}