Skip to content

Commit b1e8df4

Browse files
authored
Merge pull request #169 from splitio/develop
Develop
2 parents 784090a + 5085029 commit b1e8df4

File tree

6 files changed

+171
-57
lines changed

6 files changed

+171
-57
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name: ci
22
on:
3-
push:
3+
pull_request:
44
branches:
5+
- develop
56
- master
6-
pull_request:
7+
push:
78
branches:
89
- master
910

@@ -18,15 +19,15 @@ jobs:
1819
- 6379:6379
1920
strategy:
2021
matrix:
21-
php-versions: ['7.3', '8.0']
22+
version: ['7.3', '8.0']
2223
steps:
2324
- name: Checkout code
2425
uses: actions/checkout@v2
2526

2627
- name: Setup PHP
2728
uses: shivammathur/setup-php@v2
2829
with:
29-
php-version: ${{ matrix.php-versions }}
30+
php-version: ${{ matrix.version }}
3031
extensions: mbstring, intl
3132
ini-values: post_max_size=256M, max_execution_time=180
3233
coverage: xdebug
@@ -37,7 +38,49 @@ jobs:
3738
composer update
3839
composer dumpautoload
3940
40-
- name: script
41+
- name: Build
4142
run: |
4243
vendor/bin/phpcs --ignore=functions.php --standard=PSR2 src/
4344
vendor/bin/phpunit -c phpunit.xml.dist -v --testsuite integration
45+
46+
sonarqube:
47+
name: Sonarqube
48+
runs-on: ubuntu-latest
49+
steps:
50+
- name: Checkout code
51+
uses: actions/checkout@v2
52+
with:
53+
fetch-depth: 0
54+
55+
- name: SonarQube Scan (Push)
56+
if: github.event_name == 'push'
57+
uses: SonarSource/sonarcloud-github-action@v1.5
58+
env:
59+
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
60+
with:
61+
projectBaseDir: .
62+
args: >
63+
-Dsonar.host.url=${{ secrets.SONARQUBE_HOST }}
64+
-Dsonar.projectName=${{ github.event.repository.name }}
65+
-Dsonar.projectKey=splitsoftware_split-sdk-php
66+
-Dsonar.exclusions="**/tests/**/*.*"
67+
-Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions"
68+
-Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}"
69+
70+
- name: SonarQube Scan (Pull Request)
71+
if: github.event_name == 'pull_request'
72+
uses: SonarSource/sonarcloud-github-action@v1.5
73+
env:
74+
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
75+
with:
76+
projectBaseDir: .
77+
args: >
78+
-Dsonar.host.url=${{ secrets.SONARQUBE_HOST }}
79+
-Dsonar.projectName=${{ github.event.repository.name }}
80+
-Dsonar.projectKey=splitsoftware_split-sdk-php
81+
-Dsonar.exclusions="**/tests/**/*.*"
82+
-Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions"
83+
-Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}"
84+
-Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
85+
-Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }}
86+
-Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }}

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
7.1.0 (Dec 3, 2021)
2+
- Added a new option to use when running Redis in cluster mode called `keyHashTags` which receives a list of hashtags from which the SDK will randomly pick one to use on the generated instance.
3+
14
7.0.0 (Nov 23, 2021)
25
- BREAKING CHANGE: Removed support from versions older than PHP 7.3.
36
- BREAKING CHANGE: Removed SharedMemory (shmop) component for Segments.

sonar-scanner.sh

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/SplitIO/Component/Cache/Storage/Adapter/PRedis.php

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ private function isValidSentinelConfig($sentinels, $options)
6767
return true;
6868
}
6969

70+
private function validateKeyHashTag($keyHashTag)
71+
{
72+
if (!is_string($keyHashTag)) {
73+
return array('valid' => false, 'msg' => 'keyHashTag must be string.');
74+
}
75+
if ((strlen($keyHashTag) < 3) || ($keyHashTag[0] != "{") ||
76+
(substr($keyHashTag, -1) != "}") || (substr_count($keyHashTag, "{") != 1) ||
77+
(substr_count($keyHashTag, "}") != 1)) {
78+
return array('valid' => false, 'msg' => 'keyHashTag is not valid.');
79+
}
80+
return array('valid' => true, 'msg' => '');
81+
}
82+
7083
/**
7184
* @param mixed $options
7285
* @return string
@@ -77,19 +90,42 @@ private function getDefaultKeyHashTag($options)
7790
if (!isset($options['keyHashTag'])) {
7891
return "{SPLITIO}";
7992
}
80-
$keyHashTag = $options['keyHashTag'];
81-
if (!is_string($keyHashTag)) {
82-
throw new AdapterException("keyHashTag must be string.");
83-
} else {
84-
if ((strlen($keyHashTag) < 3) || ($keyHashTag[0] != "{") ||
85-
(substr($keyHashTag, -1) != "}") || (substr_count($keyHashTag, "{") != 1) ||
86-
(substr_count($keyHashTag, "}") != 1)) {
87-
throw new AdapterException("keyHashTag is not valid.");
93+
$validation = $this->validateKeyHashTag($options['keyHashTag']);
94+
if (!($validation['valid'])) {
95+
throw new AdapterException($validation['msg']);
96+
}
97+
return $options['keyHashTag'];
98+
}
99+
100+
101+
/**
102+
* @param mixed $options
103+
* @return string
104+
* @throws AdapterException
105+
*/
106+
private function selectKeyHashTag($options)
107+
{
108+
if (!isset($options['keyHashTags'])) { // check if array keyHashTags is set
109+
return $this->getDefaultKeyHashTag($options); // defaulting to keyHashTag or {SPLITIO}
110+
}
111+
$keyHashTags = $options['keyHashTags'];
112+
$msg = $this->isValidConfigArray($keyHashTags, 'keyHashTags'); // check if is valid array
113+
if (!is_null($msg)) {
114+
throw new AdapterException($msg);
115+
}
116+
$filteredArray = array_filter( // filter to only use string element {X}
117+
$keyHashTags,
118+
function ($value) {
119+
return $this->validateKeyHashTag($value)['valid'];
88120
}
121+
);
122+
if (count($filteredArray) == 0) {
123+
throw new AdapterException('keyHashTags size is zero after filtering valid elements.');
89124
}
90-
return $keyHashTag;
125+
return $selected = $filteredArray[array_rand($filteredArray, 1)];
91126
}
92127

128+
93129
/**
94130
* @param array $clusters
95131
* @return bool
@@ -143,7 +179,7 @@ private function getRedisConfiguration($options)
143179
switch ($_options['distributedStrategy']) {
144180
case 'cluster':
145181
if ($this->isValidClusterConfig($clusters)) {
146-
$keyHashTag = $this->getDefaultKeyHashTag($_options);
182+
$keyHashTag = $this->selectKeyHashTag($_options);
147183
$_options['cluster'] = 'redis';
148184
$redisConfigutation['redis'] = $clusters;
149185
$prefix = isset($_options['prefix']) ? $_options['prefix'] : '';

src/SplitIO/Version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33

44
class Version
55
{
6-
const CURRENT = '7.0.0';
6+
const CURRENT = '7.1.0';
77
}

tests/Suite/Adapter/RedisAdapterTest.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,79 @@ public function testRedisWithoutCustomKeyHashtagClusters()
401401
$predis->getItem('this_is_a_test_key');
402402
}
403403

404+
public function testRedisWithClustersKeyHashTags()
405+
{
406+
$this->expectException(
407+
'SplitIO\Component\Cache\Storage\Exception\AdapterException',
408+
"keyHashTags must be array."
409+
);
410+
$predis = new PRedis(array(
411+
'clusterNodes' => array(
412+
'tcp://MYIP:26379?timeout=3'
413+
),
414+
'options' => array(
415+
'distributedStrategy' => 'cluster',
416+
'keyHashTags' => '{TEST}'
417+
)
418+
));
419+
420+
$predis->getItem('this_is_a_test_key');
421+
}
422+
423+
public function testRedisWithClustersKeyHashTagsInvalid()
424+
{
425+
$this->expectException(
426+
'SplitIO\Component\Cache\Storage\Exception\AdapterException',
427+
"keyHashTags size is zero after filtering valid elements."
428+
);
429+
$predis = new PRedis(array(
430+
'clusterNodes' => array(
431+
'tcp://MYIP:26379?timeout=3'
432+
),
433+
'options' => array(
434+
'distributedStrategy' => 'cluster',
435+
'keyHashTags' => array(1, 2)
436+
)
437+
));
438+
439+
$predis->getItem('this_is_a_test_key');
440+
}
441+
442+
public function testRedisWithClustersKeyHashTagsInvalidHashTags()
443+
{
444+
$this->expectException(
445+
'SplitIO\Component\Cache\Storage\Exception\AdapterException',
446+
"keyHashTags size is zero after filtering valid elements."
447+
);
448+
$predis = new PRedis(array(
449+
'clusterNodes' => array(
450+
'tcp://MYIP:26379?timeout=3'
451+
),
452+
'options' => array(
453+
'distributedStrategy' => 'cluster',
454+
'keyHashTags' => array("one", "two", "three")
455+
)
456+
));
457+
458+
$predis->getItem('this_is_a_test_key');
459+
}
460+
461+
public function testRedisWithClustersKeyHashTagsValid()
462+
{
463+
$this->expectException('\Predis\ClientException');
464+
$predis = new PRedis(array(
465+
'clusterNodes' => array(
466+
'tcp://MYIP:26379?timeout=3'
467+
),
468+
'options' => array(
469+
'distributedStrategy' => 'cluster',
470+
'keyHashTags' => array("{one}", "{two}", "{three}")
471+
)
472+
));
473+
474+
$predis->getItem('this_is_a_test_key');
475+
}
476+
404477
public function testRedisSSLWithClusterFails()
405478
{
406479
$this->expectException('SplitIO\Component\Cache\Storage\Exception\AdapterException');

0 commit comments

Comments
 (0)