...
 
Commits (2)
......@@ -33,7 +33,8 @@
"monolog/monolog": "^2.0@dev",
"psr/simple-cache": "^1.0@dev",
"zendframework/zend-cache": "^2.9@dev",
"zendframework/zend-serializer": "^2.9@dev"
"zendframework/zend-serializer": "^2.9@dev",
"lastguest/murmurhash": "dev-master"
},
"require-dev": {
"bossa/phpspec2-expect": "^3.0",
......@@ -55,4 +56,4 @@
"scripts": {
"test": "phpspec run"
}
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7895660621f553b180c55a987a9ca0d2",
"content-hash": "5233dc84613db45ad7e9fa74a9af3c7b",
"packages": [
{
"name": "container-interop/container-interop",
......@@ -226,6 +226,53 @@
],
"time": "2019-08-13T16:05:52+00:00"
},
{
"name": "lastguest/murmurhash",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/lastguest/murmurhash-php.git",
"reference": "4fb7516f67e695e5d7fa129d1bbb925ec0ebe408"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lastguest/murmurhash-php/zipball/4fb7516f67e695e5d7fa129d1bbb925ec0ebe408",
"reference": "4fb7516f67e695e5d7fa129d1bbb925ec0ebe408",
"shasum": ""
},
"require": {
"php": "^7"
},
"require-dev": {
"phpstan/phpstan": "^0.6.3",
"phpunit/phpunit": "^5"
},
"type": "library",
"autoload": {
"psr-4": {
"lastguest\\": "src/lastguest/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Stefano Azzolini",
"email": "lastguest@gmail.com",
"homepage": "https://github.com/lastguest/murmurhash-php"
}
],
"description": "MurmurHash3 Hash",
"homepage": "https://github.com/lastguest/murmurhash-php",
"keywords": [
"hash",
"hashing",
"murmur"
],
"time": "2017-10-10T15:16:12+00:00"
},
{
"name": "monolog/monolog",
"version": "dev-master",
......@@ -2962,6 +3009,7 @@
"psr/simple-cache": 20,
"zendframework/zend-cache": 20,
"zendframework/zend-serializer": 20,
"lastguest/murmurhash": 20,
"friendsofphp/php-cs-fixer": 20
},
"prefer-stable": false,
......
......@@ -3,6 +3,7 @@ namespace Minds\UnleashClient;
require('vendor/autoload.php');
use Minds\UnleashClient\Entities\Context;
use Minds\UnleashClient\Unleash;
use Minds\UnleashClient\Config;
use Minds\UnleashClient\Logger;
......@@ -11,8 +12,25 @@ function main() : void
{
$logger = new Logger();
$logger->debug('Unleash client demo');
$config = new Config("https://gitlab.com/api/v4/feature_flags/unleash/14894840/", "F2qZp9PyWKXDas9mkEsH", "test", 300, 15);
$config = new Config(
"https://gitlab.com/api/v4/feature_flags/unleash/14894840/",
"F2qZp9PyWKXDas9mkEsH",
"test",
300,
15
);
$context = new Context();
$context
->setUserId('1000')
->setSessionId('asdasdqweqwe123123')
->setRemoteAddress('127.0.0.1')
->setHostName('www.minds.com');
$unleash = new Unleash($config, $logger);
$unleash
->setContext($context);
$enabled = $unleash->isEnabled('test', false);
$logger->info("'test' flag evaluates to {$enabled}");
......@@ -22,6 +40,9 @@ function main() : void
$enabled = $unleash->isEnabled('test-selective', false);
$logger->info("'test-selective' flag evaluates to {$enabled}");
$enabled = $unleash->isEnabled('test_on_test', false);
$logger->info("'test_on_test' flag evaluates to {$enabled}");
}
main();
......@@ -28,6 +28,9 @@ class Client
/** @var FeatureFactory */
protected $featureFactory;
/** @var string */
protected $id;
/**
* Client constructor.
* @param Config $config
......@@ -49,6 +52,19 @@ class Client
$this->logger->debug("Client configured. Base URL: {$this->config->getApiUrl()}");
}
/**
* Gets the client ID based on configuration
* @return string
*/
public function getId(): string
{
if (!$this->id) {
$this->generateId();
}
return $this->id;
}
/**
* Calls the Unleash api and registers the client
* @param string|null $date
......@@ -70,6 +86,8 @@ class Client
];
$this->logger->debug('Client payload', $payload);
$this->generateId();
$response = $this->httpClient->post('client/register', $payload);
return
......@@ -135,4 +153,14 @@ class Client
'handler' => $stack
]);
}
protected function generateId(): void
{
$this->id = substr(sha1(implode(':', [
$this->config->getApiUrl(),
$this->config->getApplicationName(),
$this->config->getInstanceId(),
$this->config->getVersion()
])), 4, 16);
}
}
<?php
/**
* Context
*
* @author edgebal
*/
namespace Minds\UnleashClient\Entities;
class Context
{
/** @var string */
protected $userId;
/** @var string */
protected $sessionId;
/** @var string */
protected $remoteAddress;
/** @var string */
protected $hostName;
/**
* Gets the context user ID
* @return string
*/
public function getUserId(): string
{
return $this->userId;
}
/**
* Sets the context user ID
* @param string $userId
* @return Context
*/
public function setUserId(string $userId): Context
{
$this->userId = $userId;
return $this;
}
/**
* Gets the context session ID
* @return string
*/
public function getSessionId(): string
{
return $this->sessionId;
}
/**
* Sets the context session ID
* @param string $sessionId
* @return Context
*/
public function setSessionId(string $sessionId): Context
{
$this->sessionId = $sessionId;
return $this;
}
/**
* Gets the context remote address
* @return string
*/
public function getRemoteAddress(): string
{
return $this->remoteAddress;
}
/**
* Sets the context remote address
* @param string $remoteAddress
* @return Context
*/
public function setRemoteAddress(string $remoteAddress): Context
{
$this->remoteAddress = $remoteAddress;
return $this;
}
/**
* Gets the context host name
* @return string
*/
public function getHostName(): string
{
return $this->hostName;
}
/**
* Sets the context host name
* @param string $hostName
* @return Context
*/
public function setHostName(string $hostName): Context
{
$this->hostName = $hostName;
return $this;
}
}
......@@ -2,12 +2,16 @@
namespace Minds\UnleashClient;
use Minds\UnleashClient\Entities\Context;
use Psr\SimpleCache\CacheInterface;
use Psr\Log\LoggerInterface;
use Psr\SimpleCache\InvalidArgumentException;
class Unleash
{
/** @var string */
const UNLEASH_CLIENT_CACHE_TIMEOUT_KEY = 'cache_timeout';
/** @var Config */
protected $config;
......@@ -23,6 +27,9 @@ class Unleash
/** @var bool */
protected $isClientRegistered = false;
/** @var Context */
protected $context;
/**
* Unleash constructor.
* @param Config|null $config
......@@ -44,7 +51,18 @@ class Unleash
}
/**
* Checks the current collection of feature flags to determine if a flag is enabled
* Sets the context for the upcoming feature flag checks
* @param Context $context
* @return Unleash
*/
public function setContext(Context $context): Unleash
{
$this->context = $context;
return $this;
}
/**
* Checks the current collection of feature flags to determine if a flag is enabled for said context
* @param string $featureName
* @param bool $default
* @return bool
......@@ -61,7 +79,7 @@ class Unleash
}
/** @var Entities\Feature|null */
$feature = $this->cache->get($featureName, null);
$feature = $this->cache->get($this->buildCacheKey($featureName), null);
if ($feature === null) {
return $default;
......@@ -82,7 +100,7 @@ class Unleash
*/
public function isCacheInvalid()
{
return $this->cache->get('_unleash_client_cache_timeout', -1) <= time();
return $this->cache->get($this->buildCacheKey(static::UNLEASH_CLIENT_CACHE_TIMEOUT_KEY), -1) <= time();
}
/**
......@@ -98,11 +116,24 @@ class Unleash
$this->logger->debug('Fetching feature flags from server');
foreach ($this->client->getFeatureFlags() as $feature) {
$this->logger->debug("Storing {$feature->getName()}");
$this->cache->set($feature->getName(), $feature);
$this->cache->set($this->buildCacheKey($feature->getName()), $feature);
}
$timeout = time() + $this->config->getPollingIntervalSeconds();
$this->logger->debug('Cache will timeout at ' . date('c', $timeout));
$this->cache->set('_unleash_client_cache_timeout', $timeout);
$this->cache
->set($this->buildCacheKey(static::UNLEASH_CLIENT_CACHE_TIMEOUT_KEY), $timeout);
}
/**
* Builds a config-aware cache key
* @param string $key
* @return string
*/
protected function buildCacheKey(string $key): string
{
return implode('_', [ '_unl', $this->client->getId(), $key ]);
}
}