Skip to content

Commit

Permalink
Adding unit of work and replay
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean Crystal committed Aug 23, 2011
1 parent 370ab5d commit da4c4ce
Show file tree
Hide file tree
Showing 13 changed files with 484 additions and 5 deletions.
12 changes: 12 additions & 0 deletions library/Tracks/EventStore/IRepository.php
@@ -0,0 +1,12 @@
<?php
namespace Tracks\EventStore;
use Tracks\Model\Guid;
use Tracks\Model\AggregateRoot;

interface IRepository
{
public function load(Guid $guid);
public function save(AggregateRoot $aggregateRoot);
public function setSnapshotFrequency($numEvents);
}

3 changes: 1 addition & 2 deletions library/Tracks/EventStore/Repository.php
Expand Up @@ -26,9 +26,8 @@
* @license http://www.opensource.org/licenses/BSD-3-Clause BSD 3-Clause
* @link https://github.com/spiralout/Tracks
*/
class Repository
class Repository implements IRepository
{

const SNAPSHOT_FREQUENCY = 100;

/**
Expand Down
3 changes: 1 addition & 2 deletions library/Tracks/EventStore/SnapshotStorage/File.php
Expand Up @@ -31,7 +31,6 @@
*/
class File implements ISnapshotStore
{

/**
* Constructor
*
Expand Down Expand Up @@ -94,4 +93,4 @@ private function _getFilename(Guid $guid)

/** @var string */
private $_directory;
}
}
1 change: 0 additions & 1 deletion library/Tracks/Model/Entity.php
Expand Up @@ -27,7 +27,6 @@
*/
abstract class Entity
{

/**
* Load an array of events onto this entity
*
Expand Down
7 changes: 7 additions & 0 deletions library/Tracks/Replay/EventStream/IEventStream.php
@@ -0,0 +1,7 @@
<?php
namespace Tracks\Replay;

interface IEventStream extends \Iterator
{
public function getDryRunInfo();
}
115 changes: 115 additions & 0 deletions library/Tracks/Replay/EventStream/ZendDb.php
@@ -0,0 +1,115 @@
<?php
namespace Tracks\Replay\EventStream;

class ZendDb implements IEventStream
{
/** @staticvar int */
const BUFFER_SIZE = 100;

/** @var Zend_Db_Select */
private $_query;

/** @var array */
private $_rowBuffer = array();

/** @var int */
private $_cursor = 0;

/** @var int */
private $_offset = 0;

/** @var int */
private $_bufferSize;

/**
* Constructor
*/
public function __construct(Zend_Db_Select $query, $bufferSize = self::BUFFER_SIZE)
{
assert('is_int($bufferSize)');

$this->_query = $query;
$this->_bufferSize = $bufferSize;
}

/**
* Get the current element
* @see Iterator::current()
*/
public function current()
{
if (empty($this->_rowBuffer)) {
$this->loadMore();
}

return unserialize($this->_rowBuffer[$this->_cursor]['data']);
}

/**
* Get the key for the current element
* @see Iterator::key()
*/
public function key()
{
return $this->_cursor;
}

/**
* Move the cursor to the next element
* @see Iterator::next()
*/
public function next()
{
if (++$this->_cursor >= $this->_bufferSize) {
$this->loadMore();
$this->_cursor = 0;
}
}

/**
* Rewind the cursor to the first element
* @see Iterator::rewind()
*/
public function rewind()
{
$this->_cursor = 0;

if (empty($this->_rowBuffer)) {
$this->loadMore();
}
}

/**
* Is the current key valid?
* @see Iterator::valid()
*/
public function valid()
{
return $this->_cursor < count($this->_rowBuffer);
}

/**
* Get the SQL string for the current query
*
* @return string
*/
public function getQueryAsString()
{
return $this->_query->assemble();
}

/**
* Load more rows from the database and put them in the buffer
*/
private function loadMore()
{
$eventTable = new Zend_Db_Table('event');
$this->_rowBuffer = $eventTable
->fetchAll(
$this->_query
->limit(self::BUFFER_SIZE, $this->_offset)
)->toArray();

$this->_offset += self::BUFFER_SIZE;
}
}
178 changes: 178 additions & 0 deletions library/Tracks/Replay/EventStream/ZendDbBuilder.php
@@ -0,0 +1,178 @@
<?php
namespace Tracks\Replay\EventStream;

class ZendDbBuilder
{
/** @var Zend_Db_Select */
private $_query;

/** @var array */
private $_eventClasses = array();

/** @var array */
private $_entities = array();

/** @var Zend_Date */
private $_startDate;

/** @var Zend_Date */
private $_endDate;

/**
* Start building an event stream
*
* @return Replay_EventStreamBuilder
*/
public static function start()
{
return new self;
}

/**
* Stream all events
*
* @return Replay_EventStreamBuilder
*/
public function withAllEvents()
{
$this->_eventClasses = array();

return $this;
}

/**
* Stream a specific event class
*
* @param string $eventClass
* @return Replay_EventStreamBuilder
*/
public function withEvent($eventClass)
{
assert('is_string($eventClass)');

$this->_eventClasses[] = $eventClass;

return $this;
}

/**
* Stream from all entities
*
* @return Replay_EventStreamBuilder
*/
public function fromAllEntities()
{
$this->_entities = array();

return $this;
}

/**
* Get events that belong to an entity
*
* @param string $guid
* @return Replay_EventStreamBuilder
*/
public function fromEntity($guid)
{
assert('is_string($guid)');

$this->_entities[] = $guid;

return $this;
}

/**
* Stream events for all time
*
* @return Replay_EventStreamBuilder
*/
public function forAllTime()
{
$this->_startDate = null;
$this->_endDate = null;

return $this;
}

/**
* Specify a date range from which to select events
* Only one date range may be specified
*
* @param Zend_Date $startDate
* @param Zend_Date $endDate
* @return Replay_EventStreamBuilder
*/
public function inDateRange(Zend_Date $startDate, Zend_Date $endDate)
{
$this->_startDate = $startDate;
$this->_endDate = $endDate;

return $this;
}

/**
* Get the Replay_EventStream object
*
* @return Replay_EventStream
*/
public function build()
{
$this->buildBaseQuery();
$this->buildEventsQuery();
$this->buildDateRangeQuery();
$this->buildEntitiesQuery();

return new Replay_EventStream($this->_query);
}

/**
* Build the base query to load events
*/
private function buildBaseQuery()
{
$eventTable = new Table_Event;
$this->_query = $eventTable
->select()
->from('event', '*')
->setIntegrityCheck(false)
->order('date_created ASC')
->order('event.id');
}

/**
* Build the event class filter part of the query
*/
private function buildEventsQuery()
{
if (count($this->_eventClasses) > 0) {
$this->_query->where(implode('OR', array_map(function($x) { return " data LIKE '%{$x}%' "; }, $this->_eventClasses)));
}
}

/**
* Build the entity guid filter part of the query
*/
private function buildEntitiesQuery()
{
if (count($this->_entities) > 0) {
$this->_query
->join('event_provider', 'event.event_provider_id = event_provider.id')
->where(new Zend_Db_Expr("event_provider.guid IN (". implode(',', array_map(function($x) { return "'{$x}'"; }, $this->_entities)) .")"));
}
}

/**
* Build the date range filter part of the query
*/
private function buildDateRangeQuery()
{
if ($this->_startDate) {
$this->_query->where('date_created >= ?', $this->_startDate->toString('Y-m-d'));
}

if ($this->_endDate) {
$this->_query->where('date_created <= ?', $this->_endDate->toString('Y-m-d'));
}
}
}

0 comments on commit da4c4ce

Please sign in to comment.