@@ -27,6 +27,16 @@ class Cache
27
27
*/
28
28
const REDIS_DATABASE_PAGE_CACHE = 2 ;
29
29
30
+ const REDIS_BACKEND_CM_CACHE = 'Cm_Cache_Backend_Redis ' ;
31
+ const REDIS_BACKEND_REDIS_CACHE = '\Magento\Framework\Cache\Backend\Redis ' ;
32
+ const REDIS_BACKEND_REMOTE_SYNHRONIZED_CACHE = '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache ' ;
33
+
34
+ const AVAILABLE_REDIS_BACKEND = [
35
+ self ::REDIS_BACKEND_CM_CACHE ,
36
+ self ::REDIS_BACKEND_REDIS_CACHE ,
37
+ self ::REDIS_BACKEND_REMOTE_SYNHRONIZED_CACHE
38
+ ];
39
+
30
40
/**
31
41
* @var Redis
32
42
*/
@@ -73,19 +83,22 @@ public function __construct(
73
83
* Returns an empty array in other case.
74
84
*
75
85
* @return array
86
+ * @throws \Magento\MagentoCloud\Config\ConfigException
76
87
*/
77
88
public function get (): array
78
89
{
79
90
$ envCacheConfiguration = (array )$ this ->stageConfig ->get (DeployInterface::VAR_CACHE_CONFIGURATION );
91
+ $ envCacheBackendModel = (string )$ this ->stageConfig ->get (DeployInterface::VAR_CACHE_REDIS_BACKEND );
80
92
81
93
if ($ this ->isCacheConfigurationValid ($ envCacheConfiguration )
82
94
&& !$ this ->configMerger ->isMergeRequired ($ envCacheConfiguration )
83
95
) {
84
96
if ($ this ->stageConfig ->get (DeployInterface::VAR_REDIS_USE_SLAVE_CONNECTION )) {
85
97
$ this ->logger ->notice (
86
98
sprintf (
87
- 'The variable \'%s \' is ignored as you set your own cache connection in \'%s \'' ,
99
+ 'The variables \'%s \', \' %s \' are ignored as you set your own cache connection in \'%s \'' ,
88
100
DeployInterface::VAR_REDIS_USE_SLAVE_CONNECTION ,
101
+ DeployInterface::VAR_CACHE_REDIS_BACKEND ,
89
102
DeployInterface::VAR_CACHE_CONFIGURATION
90
103
)
91
104
);
@@ -100,21 +113,69 @@ public function get(): array
100
113
return [];
101
114
}
102
115
103
- $ redisCache = [
104
- 'backend ' => 'Cm_Cache_Backend_Redis ' ,
105
- 'backend_options ' => [
106
- 'server ' => $ redisConfig ['host ' ],
107
- 'port ' => $ redisConfig ['port ' ],
108
- ],
109
- ];
116
+ if ($ this ->isSynchronizedConfigStructure ()) {
117
+ $ redisCache = $ this ->getSynchronizedConfigStructure ($ envCacheBackendModel , $ redisConfig );
118
+ $ redisCache ['backend_options ' ]['remote_backend_options ' ] = array_merge (
119
+ $ redisCache ['backend_options ' ]['remote_backend_options ' ],
120
+ $ this ->getSlaveConnection ($ envCacheConfiguration , $ redisConfig )
121
+ );
122
+ $ finalConfig = [
123
+ 'frontend ' => [
124
+ 'default ' => $ redisCache ,
125
+ ],
126
+ 'type ' => [
127
+ 'default ' => ['frontend ' => 'default ' ],
128
+ ],
129
+ ];
130
+ } else {
131
+ $ redisCache = $ this ->getUnsyncedConfigStructure ($ envCacheBackendModel , $ redisConfig );
132
+ $ slaveConnection = $ this ->getSlaveConnection ($ envCacheConfiguration , $ redisConfig );
133
+ if ($ slaveConnection ) {
134
+ $ redisCache ['frontend_options ' ]['write_control ' ] = false ;
135
+ $ redisCache ['backend_options ' ] = array_merge (
136
+ $ redisCache ['backend_options ' ],
137
+ $ slaveConnection
138
+ );
139
+ }
140
+ $ finalConfig = [
141
+ 'frontend ' => [
142
+ 'default ' => array_replace_recursive (
143
+ $ redisCache ,
144
+ ['backend_options ' => ['database ' => self ::REDIS_DATABASE_DEFAULT ]]
145
+ ),
146
+ 'page_cache ' => array_replace_recursive (
147
+ $ redisCache ,
148
+ ['backend_options ' => ['database ' => self ::REDIS_DATABASE_PAGE_CACHE ]]
149
+ ),
150
+ ]
151
+ ];
152
+ }
153
+
154
+ return $ this ->configMerger ->merge ($ finalConfig , $ envCacheConfiguration );
155
+ }
110
156
111
- $ slaveConnectionData = $ this ->getSlaveConnection ();
112
- if ($ slaveConnectionData ) {
157
+ /**
158
+ * Retrieves Redis read connection data if it exists and variable REDIS_USE_SLAVE_CONNECTION was set as true,
159
+ * also if CACHE_CONFIGURATION is compatible with slave connections.
160
+ * Otherwise retrieves an empty array.
161
+ *
162
+ * @param array $envCacheConfiguration
163
+ * @param array $redisConfig
164
+ * @return array
165
+ * @throws \Magento\MagentoCloud\Config\ConfigException
166
+ */
167
+ private function getSlaveConnection (array $ envCacheConfiguration , array $ redisConfig ): array
168
+ {
169
+ $ config = [];
170
+ $ redisSlaveConfig = $ this ->redis ->getSlaveConfiguration ();
171
+ $ slaveHost = $ redisSlaveConfig ['host ' ] ?? null ;
172
+
173
+ if ($ this ->stageConfig ->get (DeployInterface::VAR_REDIS_USE_SLAVE_CONNECTION ) && $ slaveHost ) {
113
174
if ($ this ->isConfigurationCompatibleWithSlaveConnection ($ envCacheConfiguration , $ redisConfig )) {
114
- $ redisCache [ ' backend_options ' ]['load_from_slave ' ] = $ slaveConnectionData ;
115
- $ redisCache [ ' backend_options ' ]['read_timeout ' ] = 1 ;
116
- $ redisCache [ ' backend_options ' ][ ' retry_reads_on_master ' ] = 1 ;
117
- $ redisCache [ ' frontend_options ' ][ ' write_control ' ] = false ;
175
+ $ config [ ' load_from_slave ' ]['server ' ] = $ slaveHost ;
176
+ $ config [ ' load_from_slave ' ]['port ' ] = $ redisSlaveConfig [ ' port ' ] ?? '' ;
177
+ $ config [ ' read_timeout ' ] = 1 ;
178
+ $ config [ ' retry_reads_on_master ' ] = 1 ;
118
179
$ this ->logger ->info ('Set Redis slave connection ' );
119
180
} else {
120
181
$ this ->logger ->notice (
@@ -127,18 +188,7 @@ public function get(): array
127
188
}
128
189
}
129
190
130
- return $ this ->configMerger ->merge ([
131
- 'frontend ' => [
132
- 'default ' => array_replace_recursive (
133
- $ redisCache ,
134
- ['backend_options ' => ['database ' => self ::REDIS_DATABASE_DEFAULT ]]
135
- ),
136
- 'page_cache ' => array_replace_recursive (
137
- $ redisCache ,
138
- ['backend_options ' => ['database ' => self ::REDIS_DATABASE_PAGE_CACHE ]]
139
- ),
140
- ],
141
- ], $ envCacheConfiguration );
191
+ return $ config ;
142
192
}
143
193
144
194
/**
@@ -152,28 +202,6 @@ private function isCacheConfigurationValid(array $cacheConfiguration): bool
152
202
return !$ this ->configMerger ->isEmpty ($ cacheConfiguration ) && !empty ($ cacheConfiguration ['frontend ' ]);
153
203
}
154
204
155
- /**
156
- * Retrieves Redis read connection data if it exists and variable REDIS_USE_SLAVE_CONNECTION was set as true.
157
- * Otherwise retrieves an empty array.
158
- *
159
- * @return array
160
- */
161
- private function getSlaveConnection (): array
162
- {
163
- $ connectionData = [];
164
- $ redisSlaveConfig = $ this ->redis ->getSlaveConfiguration ();
165
- $ slaveHost = $ redisSlaveConfig ['host ' ] ?? null ;
166
-
167
- if ($ this ->stageConfig ->get (DeployInterface::VAR_REDIS_USE_SLAVE_CONNECTION ) && $ slaveHost ) {
168
- $ connectionData = [
169
- 'server ' => $ slaveHost ,
170
- 'port ' => $ redisSlaveConfig ['port ' ] ?? '' ,
171
- ];
172
- }
173
-
174
- return $ connectionData ;
175
- }
176
-
177
205
/**
178
206
* Checks that cache configuration was changed in CACHE_CONFIGURATION variable
179
207
* in not compatible way with slave connection.
@@ -183,21 +211,98 @@ private function getSlaveConnection(): array
183
211
* @param array $envCacheConfig
184
212
* @param array $redisConfig
185
213
* @return bool
214
+ * @throws \Magento\MagentoCloud\Config\ConfigException
215
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
186
216
*/
187
217
private function isConfigurationCompatibleWithSlaveConnection (
188
218
array $ envCacheConfig ,
189
219
array $ redisConfig
190
220
): bool {
191
- foreach (['default ' , 'page_cache ' ] as $ type ) {
192
- if ((isset ($ envCacheConfig ['frontend ' ][$ type ]['backend_options ' ]['server ' ])
193
- && $ envCacheConfig ['frontend ' ][$ type ]['backend_options ' ]['server ' ] !== $ redisConfig ['host ' ])
194
- || (isset ($ envCacheConfig ['frontend ' ][$ type ]['backend_options ' ]['port ' ])
195
- && $ envCacheConfig ['frontend ' ][$ type ]['backend_options ' ]['port ' ] !== $ redisConfig ['port ' ])
196
- ) {
221
+ if ($ this ->isSynchronizedConfigStructure ()) {
222
+ $ host = $ envCacheConfig ['frontend ' ]['default ' ]['backend_options ' ]['remote_backend_options ' ]['server ' ]
223
+ ?? null ;
224
+
225
+ $ port = $ envCacheConfig ['frontend ' ]['default ' ]['backend_options ' ]['remote_backend_options ' ]['port ' ]
226
+ ?? null ;
227
+
228
+ if (($ host !== null && $ host !== $ redisConfig ['host ' ])
229
+ || ($ port !== null && $ port !== $ redisConfig ['port ' ])) {
197
230
return false ;
198
231
}
232
+ } else {
233
+ foreach (['default ' , 'page_cache ' ] as $ type ) {
234
+ $ host = $ envCacheConfig ['frontend ' ][$ type ]['backend_options ' ]['server ' ] ?? null ;
235
+ $ port = $ envCacheConfig ['frontend ' ][$ type ]['backend_options ' ]['port ' ] ?? null ;
236
+
237
+ if (($ host !== null && $ host !== $ redisConfig ['host ' ])
238
+ || ($ port !== null && $ port !== $ redisConfig ['port ' ])) {
239
+ return false ;
240
+ }
241
+ }
199
242
}
200
243
201
244
return true ;
202
245
}
246
+
247
+ /**
248
+ * Returns backend config for unsynced cache implementation.
249
+ *
250
+ * @param string $envCacheBackendModel
251
+ * @param array $redisConfig
252
+ * @return array
253
+ */
254
+ private function getUnsyncedConfigStructure (string $ envCacheBackendModel , array $ redisConfig ): array
255
+ {
256
+ return [
257
+ 'backend ' => addslashes ($ envCacheBackendModel ),
258
+ 'backend_options ' => [
259
+ 'server ' => $ redisConfig ['host ' ],
260
+ 'port ' => $ redisConfig ['port ' ],
261
+ ]
262
+ ];
263
+ }
264
+
265
+ /**
266
+ * Returns backend config for synchronized cache implementation.
267
+ *
268
+ * @param string $envCacheBackendModel
269
+ * @param array $redisConfig
270
+ * @return array
271
+ */
272
+ private function getSynchronizedConfigStructure (string $ envCacheBackendModel , array $ redisConfig ): array
273
+ {
274
+ return [
275
+ 'backend ' => addslashes ($ envCacheBackendModel ),
276
+ 'backend_options ' => [
277
+ 'remote_backend ' => addslashes ('\Magento\Framework\Cache\Backend\Redis ' ),
278
+ 'remote_backend_options ' => [
279
+ 'server ' => $ redisConfig ['host ' ],
280
+ 'port ' => $ redisConfig ['port ' ],
281
+ 'database ' => self ::REDIS_DATABASE_DEFAULT ,
282
+ 'persistent ' => 0 ,
283
+ 'password ' => '' ,
284
+ 'compress_data ' => '1 ' ,
285
+ ],
286
+ 'local_backend ' => 'Cm_Cache_Backend_File ' ,
287
+ 'local_backend_options ' => [
288
+ 'cache_dir ' => '/dev/shm/ '
289
+ ]
290
+ ],
291
+ 'frontend_options ' => [
292
+ 'write_control ' => false ,
293
+ ]
294
+ ];
295
+ }
296
+
297
+ /**
298
+ * Checks that config contains synchronized cache model and need to use synchronized config structure.
299
+ *
300
+ * @return bool
301
+ * @throws \Magento\MagentoCloud\Config\ConfigException
302
+ */
303
+ private function isSynchronizedConfigStructure (): bool
304
+ {
305
+ $ model = (string )$ this ->stageConfig ->get (DeployInterface::VAR_CACHE_REDIS_BACKEND );
306
+ return $ model === self ::REDIS_BACKEND_REMOTE_SYNHRONIZED_CACHE ;
307
+ }
203
308
}
0 commit comments