Skip to content

Commit

Permalink
Refactor order of bucketing logic (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeproeng37 committed Apr 4, 2017
1 parent e94d3ef commit 1d52b38
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 261 deletions.
42 changes: 28 additions & 14 deletions src/Optimizely/Bucketer.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,6 @@ public function bucket(ProjectConfig $config, Experiment $experiment, $userId)
return new Variation();
}

// Check if user is whitelisted for a variation.
$forcedVariations = $experiment->getForcedVariations();
if (!is_null($forcedVariations) && isset($forcedVariations[$userId])) {
$variationKey = $forcedVariations[$userId];
$variation = $config->getVariationFromKey($experiment->getKey(), $variationKey);
if ($variationKey) {
$this->_logger->log(
Logger::INFO,
sprintf('User "%s" is forced in variation "%s".', $userId, $variationKey)
);
}
return $variation;
}

// Determine if experiment is in a mutually exclusive group.
if ($experiment->isInMutexGroup()) {
$group = $config->getGroup($experiment->getGroupId());
Expand Down Expand Up @@ -184,4 +170,32 @@ public function bucket(ProjectConfig $config, Experiment $experiment, $userId)
$this->_logger->log(Logger::INFO, sprintf('User "%s" is in no variation.', $userId));
return new Variation();
}

/**
* Determine variation the user has been forced into.
*
* @param $config ProjectConfig Configuration for the project.
* @param $experiment Experiment Experiment in which user is to be bucketed.
* @param $userId string User identifier.
*
* @return null|Variation Representing the variation the user is forced into.
*/
public function getForcedVariation($config, $experiment, $userId)
{
// Check if user is whitelisted for a variation.
$forcedVariations = $experiment->getForcedVariations();
if (!is_null($forcedVariations) && isset($forcedVariations[$userId])) {
$variationKey = $forcedVariations[$userId];
$variation = $config->getVariationFromKey($experiment->getKey(), $variationKey);
if ($variationKey) {
$this->_logger->log(
Logger::INFO,
sprintf('User "%s" is forced in variation "%s" of experiment "%s".', $userId, $variationKey, $experiment->getKey())
);
}
return $variation;
}

return null;
}
}
63 changes: 24 additions & 39 deletions src/Optimizely/Event/Builder/EventBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
namespace Optimizely\Event\Builder;
include('Params.php');

use Optimizely\Bucketer;
use Optimizely\Entity\Experiment;
use Optimizely\Event\LogEvent;
use Optimizely\ProjectConfig;
Expand Down Expand Up @@ -63,21 +62,6 @@ class EventBuilder
*/
private $_eventParams;

/**
* @var Bucketer Providing Optimizely's bucket method.
*/
private $_bucketer;

/**
* EventBuilder constructor.
*
* @param $bucketer Bucketer
*/
public function __construct(Bucketer $bucketer)
{
$this->_bucketer = $bucketer;
}

/**
* Helper function to reset event params.
*/
Expand Down Expand Up @@ -153,11 +137,11 @@ private function setImpressionParams(Experiment $experiment, $variationId)
*
* @param $config ProjectConfig Configuration for the project.
* @param $eventKey string Key representing the event.
* @param $experiments array Experiments for which conversion event needs to be recorded.
* @param $experimentVariationMap array Map of experiment ID to the ID of the variation that the user is bucketed into.
* @param $userId string ID of user.
* @param $eventTags array Hash representing metadata associated with the event.
*/
private function setConversionParams($config, $eventKey, $experiments, $userId, $eventTags)
private function setConversionParams($config, $eventKey, $experimentVariationMap, $userId, $eventTags)
{
$this->_eventParams[EVENT_FEATURES] = [];
$this->_eventParams[EVENT_METRICS] = [];
Expand Down Expand Up @@ -190,39 +174,40 @@ private function setConversionParams($config, $eventKey, $experiments, $userId,
$this->_eventParams[EVENT_NAME] = $eventKey;

$this->_eventParams[LAYER_STATES] = [];
forEach ($experiments as $experiment) {
$variation = $this->_bucketer->bucket($config, $experiment, $userId);
if (!is_null($variation->getKey())) {
array_push($this->_eventParams[LAYER_STATES], [
LAYER_ID => $experiment->getLayerId(),
ACTION_TRIGGERED => true,
REVISION => $config->getRevision(),
DECISION => [
EXPERIMENT_ID => $experiment->getId(),
VARIATION_ID => $variation->getId(),
IS_LAYER_HOLDBACK => false
]
]);
}
forEach ($experimentVariationMap as $experimentId => $variationId) {
$experiment = $config->getExperimentFromId($experimentId);
array_push($this->_eventParams[LAYER_STATES], [
LAYER_ID => $experiment->getLayerId(),
ACTION_TRIGGERED => true,
REVISION => $config->getRevision(),
DECISION => [
EXPERIMENT_ID => $experimentId,
VARIATION_ID => $variationId,
IS_LAYER_HOLDBACK => false
]
]);
}
}

/**
* Create impression event to be sent to the logging endpoint.
*
* @param $config ProjectConfig Configuration for the project.
* @param $experiment Experiment Experiment being activated.
* @param $variationId string Variation user
* @param $experimentKey Experiment Experiment being activated.
* @param $variationKey string Variation user
* @param $userId string ID of user.
* @param $attributes array Attributes of the user.
*
* @return LogEvent Event object to be sent to dispatcher.
*/
public function createImpressionEvent($config, Experiment $experiment, $variationId, $userId, $attributes)
public function createImpressionEvent($config, $experimentKey, $variationKey, $userId, $attributes)
{
$this->resetParams();
$this->setCommonParams($config, $userId, $attributes);
$this->setImpressionParams($experiment, $variationId);

$experiment = $config->getExperimentFromKey($experimentKey);
$variation = $config->getVariationFromKey($experimentKey, $variationKey);
$this->setImpressionParams($experiment, $variation->getId());

return new LogEvent(self::$IMPRESSION_ENDPOINT, $this->getParams(), self::$HTTP_VERB, self::$HTTP_HEADERS);
}
Expand All @@ -232,18 +217,18 @@ public function createImpressionEvent($config, Experiment $experiment, $variatio
*
* @param $config ProjectConfig Configuration for the project.
* @param $eventKey string Key representing the event.
* @param $experiments array Experiments for which conversion event needs to be recorded.
* @param $experimentVariationMap array Map of experiment ID to the ID of the variation that the user is bucketed into.
* @param $userId string ID of user.
* @param $attributes array Attributes of the user.
* @param $eventTags array Hash representing metadata associated with the event.
*
* @return LogEvent Event object to be sent to dispatcher.
*/
public function createConversionEvent($config, $eventKey, $experiments, $userId, $attributes, $eventTags)
public function createConversionEvent($config, $eventKey, $experimentVariationMap, $userId, $attributes, $eventTags)
{
$this->resetParams();
$this->setCommonParams($config, $userId, $attributes);
$this->setConversionParams($config, $eventKey, $experiments, $userId, $eventTags);
$this->setConversionParams($config, $eventKey, $experimentVariationMap, $userId, $eventTags);

return new LogEvent(self::$CONVERSION_ENDPOINT, $this->getParams(), self::$HTTP_VERB, self::$HTTP_HEADERS);
}
Expand Down
Loading

0 comments on commit 1d52b38

Please sign in to comment.