Skip to content

Commit 485ad0b

Browse files
committed
MAGETWO-95276: Varnish "Connection reset by peer" error when large catalog is reindexed on schedule
1 parent 401203a commit 485ad0b

File tree

1 file changed

+71
-5
lines changed

1 file changed

+71
-5
lines changed

app/code/Magento/CacheInvalidate/Model/PurgeCache.php

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
use Magento\Framework\Cache\InvalidateLogger;
99

10+
/**
11+
* Purge cache action.
12+
*/
1013
class PurgeCache
1114
{
1215
const HEADER_X_MAGENTO_TAGS_PATTERN = 'X-Magento-Tags-Pattern';
@@ -26,6 +29,18 @@ class PurgeCache
2629
*/
2730
private $logger;
2831

32+
/**
33+
* Batch size of the purge request.
34+
*
35+
* Based on default Varnish 4 http_req_hdr_len size minus a 512 bytes margin for method,
36+
* header name, line feeds etc.
37+
*
38+
* @see https://varnish-cache.org/docs/4.1/reference/varnishd.html
39+
*
40+
* @var int
41+
*/
42+
private $requestSize = 7680;
43+
2944
/**
3045
* Constructor
3146
*
@@ -44,18 +59,68 @@ public function __construct(
4459
}
4560

4661
/**
47-
* Send curl purge request
48-
* to invalidate cache by tags pattern
62+
* Send curl purge request to invalidate cache by tags pattern.
4963
*
5064
* @param string $tagsPattern
5165
* @return bool Return true if successful; otherwise return false
5266
*/
5367
public function sendPurgeRequest($tagsPattern)
5468
{
69+
$successful = true;
5570
$socketAdapter = $this->socketAdapterFactory->create();
5671
$servers = $this->cacheServer->getUris();
57-
$headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $tagsPattern];
5872
$socketAdapter->setOptions(['timeout' => 10]);
73+
74+
$formattedTagsChunks = $this->splitTags($tagsPattern);
75+
foreach ($formattedTagsChunks as $formattedTagsChunk) {
76+
if (!$this->sendPurgeRequestToServers($socketAdapter, $servers, $formattedTagsChunk)) {
77+
$successful = false;
78+
}
79+
}
80+
81+
return $successful;
82+
}
83+
84+
/**
85+
* Split tags by batches
86+
*
87+
* @param string $tagsPattern
88+
* @return \Generator
89+
*/
90+
private function splitTags(string $tagsPattern) : \Generator
91+
{
92+
$tagsBatchSize = 0;
93+
$formattedTagsChunk = [];
94+
$formattedTags = explode('|', $tagsPattern);
95+
foreach ($formattedTags as $formattedTag) {
96+
if ($tagsBatchSize + strlen($formattedTag) > $this->requestSize - count($formattedTagsChunk) - 1) {
97+
yield implode('|', array_unique($formattedTagsChunk));
98+
$formattedTagsChunk = [];
99+
$tagsBatchSize = 0;
100+
}
101+
102+
$tagsBatchSize += strlen($formattedTag);
103+
$formattedTagsChunk[] = $formattedTag;
104+
}
105+
if (!empty($formattedTagsChunk)) {
106+
yield implode('|', array_unique($formattedTagsChunk));
107+
}
108+
}
109+
110+
/**
111+
* Send curl purge request to servers to invalidate cache by tags pattern.
112+
*
113+
* @param \Zend\Http\Client\Adapter\Socket $socketAdapter
114+
* @param \Zend\Uri\Uri[] $servers
115+
* @param string $formattedTagsChunk
116+
* @return bool Return true if successful; otherwise return false
117+
*/
118+
private function sendPurgeRequestToServers(
119+
\Zend\Http\Client\Adapter\Socket $socketAdapter,
120+
array $servers,
121+
string $formattedTagsChunk
122+
): bool {
123+
$headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $formattedTagsChunk];
59124
foreach ($servers as $server) {
60125
$headers['Host'] = $server->getHost();
61126
try {
@@ -69,12 +134,13 @@ public function sendPurgeRequest($tagsPattern)
69134
$socketAdapter->read();
70135
$socketAdapter->close();
71136
} catch (\Exception $e) {
72-
$this->logger->critical($e->getMessage(), compact('server', 'tagsPattern'));
137+
$this->logger->critical($e->getMessage(), compact('server', 'formattedTagsChunk'));
138+
73139
return false;
74140
}
75141
}
142+
$this->logger->execute(compact('servers', 'formattedTagsChunk'));
76143

77-
$this->logger->execute(compact('servers', 'tagsPattern'));
78144
return true;
79145
}
80146
}

0 commit comments

Comments
 (0)