/** * * @param Identifier $identifier * @param string $state */ public function __construct(Identifier $identifier, $state, $message = null) { $this->id = $identifier->getEntityId(); $this->machine = $identifier->getMachine(); $this->state = $state; $this->timestamp = time(); $this->message = $message; }
protected function build(Identifier $identifier) { $light = new TrafficLight($identifier->getEntityId()); return $light; }
/** * {@inheritDoc} */ public function isPersisted(Identifier $identifier) { $is_persisted = false; try { //https://php.net/manual/en/mongocollection.findone.php $query = array("entity_id" => $identifier->getEntityId(), "machine" => $identifier->getMachine()); $data = $this->getClient()->izzum->states->findOne($query); if ($data) { $is_persisted = true; } } catch (\Exception $e) { throw new Exception(sprintf('getting persistence info failed: [%s]', $e->getMessage()), Exception::PERSISTENCE_LAYER_EXCEPTION); } return $is_persisted; }
/** * {@inheritDoc} */ 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); } }
/** *{@inheritDoc} */ public function addHistory(Identifier $identifier, $state, $message = null, $is_exception = false) { $connection = $this->getConnection(); $prefix = $this->getPrefix(); try { $query = 'INSERT INTO ' . $prefix . 'statemachine_history (machine, entity_id, state, message, changetime, exception) VALUES (:machine, :entity_id, :state, :message, :timestamp, :exception)'; $statement = $connection->prepare($query); $machine = $identifier->getMachine(); $entity_id = $identifier->getEntityId(); $timestamp = $this->getTimestampForDriver(); $is_exception = $this->getBooleanForDriver($is_exception); $statement->bindParam(":machine", $machine); $statement->bindParam(":entity_id", $entity_id); $statement->bindParam(":state", $state); if ($message) { if (is_string($message)) { $info = new \stdClass(); $info->message = $message; $message = $info; } //always json encode it so we can pass objects as the message and store it $message = json_encode($message); } $statement->bindParam(":message", $message); $statement->bindParam(":timestamp", $timestamp); $statement->bindParam(":exception", $is_exception); $result = $statement->execute(); if ($result === false) { throw new Exception($this->getErrorInfo($statement)); } } catch (\Exception $e) { throw new Exception(sprintf('query for updating state failed: [%s]', $e->getMessage()), Exception::PERSISTENCE_LAYER_EXCEPTION); } }
protected function build(Identifier $identifier) { $output = new \stdClass(); $output->entity_id = $identifier->getEntityId(); $output->machine = $identifier->getMachine(); return $output; }