public function addHistory(Identifier $identifier, $state, $message = null, $is_exception = false)
{
$redis = $this->getRedis();
try {
$machine = $identifier->getMachine();
$entity_id = $identifier->getEntityId();
//counter for the number of transitions.
$key = self::KEY_COUNTERS_TRANSITIONS_ALL;
//this will function as the id of the transition data, stored as a redis hash
$counter = $redis->incr($key);
//now that we have the counter, start a redis multi command in pipeline mode
$redis->multi(\Redis::PIPELINE);
//create the record for the transition to store in a redis hash
$timestamp = time();
$record = array();
$record['state'] = $state;
$record['machine'] = $machine;
$record['entity_id'] = $entity_id;
if ($message) {
if (is_string($message)) {
$info = new \stdClass();
$info->message = $message;
$message = $info;
}
//always json_encode so we can pass objects as messages
$message = json_encode($message);
}
$record['message'] = $message;
$record['timestamp'] = $timestamp;
$record['datetime'] = date('Y-m-d H:i:s', $timestamp);
//ISO_8601
$record['exception'] = $is_exception ? 1 : 0;
$record['id'] = $counter;
/*
* set the canonical form of the transition as a hash with the counter as the id.
* This allows you to get data from the canonical from by storing a reference to the transaction id
* in other lists or sets (memory optimization) via:
* sort izzum:transitions:all:normal by nosort get izzum:transitions:canonical:*->message STORE mymessages
* @see http://redis.io/commands/sort
*/
$key_hash_id = sprintf(self::KEY_TRANSITIONS_CANONICAL, $counter);
$redis->hmset($key_hash_id, $record);
//store all transitions referencing the id of the canonical form in sorted sets (keyed by timestamp),
//set manipulations are powerful in redis (diff, union, intersect etc with the exceptions for example)
$key = self::KEY_TRANSITIONS_ALL;
$redis->zadd($key, $timestamp, $counter);
$key = sprintf(self::KEY_TRANSITIONS_MACHINES, $machine);
$redis->zadd($key, $timestamp, $counter);
$key = sprintf(self::KEY_TRANSITIONS_STATES, $machine, $state);
$redis->zadd($key, $timestamp, $counter);
$key = sprintf(self::KEY_TRANSITIONS_ENTITIES, $machine, $entity_id);
$redis->zadd($key, $timestamp, $counter);
if ($is_exception) {
//store all failed transitions referencing the id of the canonical form in sets
$key = self::KEY_TRANSITIONS_ALL_FAILED;
$redis->zadd($key, $timestamp, $counter);
$key = sprintf(self::KEY_TRANSITIONS_MACHINES_FAILED, $machine);
$redis->zadd($key, $timestamp, $counter);
$key = sprintf(self::KEY_TRANSITIONS_STATES_FAILED, $machine, $state);
$redis->zadd($key, $timestamp, $counter);
$key = sprintf(self::KEY_TRANSITIONS_ENTITIES_FAILED, $machine, $entity_id);
$redis->zadd($key, $timestamp, $counter);
}
//execute the sequence of redis commands
$redis->exec();
} catch (\Exception $e) {
$redis->discard();
throw new Exception(sprintf('adding history failed: [%s]', $e->getMessage()), Exception::PERSISTENCE_LAYER_EXCEPTION);
}
}