7
7
8
8
use Magento \Framework \Cache \InvalidateLogger ;
9
9
10
+ /**
11
+ * Purge cache action.
12
+ */
10
13
class PurgeCache
11
14
{
12
15
const HEADER_X_MAGENTO_TAGS_PATTERN = 'X-Magento-Tags-Pattern ' ;
@@ -26,6 +29,18 @@ class PurgeCache
26
29
*/
27
30
private $ logger ;
28
31
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
+
29
44
/**
30
45
* Constructor
31
46
*
@@ -44,18 +59,68 @@ public function __construct(
44
59
}
45
60
46
61
/**
47
- * Send curl purge request
48
- * to invalidate cache by tags pattern
62
+ * Send curl purge request to invalidate cache by tags pattern.
49
63
*
50
64
* @param string $tagsPattern
51
65
* @return bool Return true if successful; otherwise return false
52
66
*/
53
67
public function sendPurgeRequest ($ tagsPattern )
54
68
{
69
+ $ successful = true ;
55
70
$ socketAdapter = $ this ->socketAdapterFactory ->create ();
56
71
$ servers = $ this ->cacheServer ->getUris ();
57
- $ headers = [self ::HEADER_X_MAGENTO_TAGS_PATTERN => $ tagsPattern ];
58
72
$ 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 ];
59
124
foreach ($ servers as $ server ) {
60
125
$ headers ['Host ' ] = $ server ->getHost ();
61
126
try {
@@ -69,12 +134,13 @@ public function sendPurgeRequest($tagsPattern)
69
134
$ socketAdapter ->read ();
70
135
$ socketAdapter ->close ();
71
136
} catch (\Exception $ e ) {
72
- $ this ->logger ->critical ($ e ->getMessage (), compact ('server ' , 'tagsPattern ' ));
137
+ $ this ->logger ->critical ($ e ->getMessage (), compact ('server ' , 'formattedTagsChunk ' ));
138
+
73
139
return false ;
74
140
}
75
141
}
142
+ $ this ->logger ->execute (compact ('servers ' , 'formattedTagsChunk ' ));
76
143
77
- $ this ->logger ->execute (compact ('servers ' , 'tagsPattern ' ));
78
144
return true ;
79
145
}
80
146
}
0 commit comments