schema/mysql: add sync_run history table

This commit is contained in:
Thomas Gelf 2016-02-24 10:50:57 +01:00
parent 5c202b57ff
commit 42e87476fb
6 changed files with 87 additions and 44 deletions

View File

@ -61,12 +61,12 @@ class JobsCommand extends Command
foreach (SyncRule::loadAll($this->db) as $rule) { foreach (SyncRule::loadAll($this->db) as $rule) {
Benchmark::measure('Checking sync rule ' . $rule->rule_name); Benchmark::measure('Checking sync rule ' . $rule->rule_name);
$mod = Sync::getExpectedModifications($rule); $sync = new Sync($rule);
if (count($mod) > 0) { if ($sync->hasModifications()) {
printf('Sync rule "%s" provides changes, triggering sync... ', $rule->rule_name); printf('Sync rule "%s" provides changes, triggering sync... ', $rule->rule_name);
Benchmark::measure('Got modifications for sync rule ' . $rule->rule_name); Benchmark::measure('Got modifications for sync rule ' . $rule->rule_name);
if (Sync::run($rule)) { if ($sync->apply()) {
Benchmark::measure('Successfully synced rule ' . $rule->rule_name); Benchmark::measure('Successfully synced rule ' . $rule->rule_name);
print "SUCCEEDED\n"; print "SUCCEEDED\n";
} }

View File

@ -22,7 +22,8 @@ class SyncruleController extends ActionController
public function runAction() public function runAction()
{ {
if ($runId = Sync::run(SyncRule::load($this->params->get('id'), $this->db()))) { $sync = new Sync(SyncRule::load($this->params->get('id'), $this->db()));
if ($runId = $sync->apply()) {
Notification::success('Source has successfully been synchronized'); Notification::success('Source has successfully been synchronized');
$this->redirectNow('director/list/syncrule'); $this->redirectNow('director/list/syncrule');
} else { } else {

View File

@ -51,9 +51,9 @@ class SyncruleTable extends QuickTable
try { try {
// $mod = Sync::hasModifications( // $mod = Sync::hasModifications(
$mod = Sync::getExpectedModifications( $sync = new Sync(SyncRule::load($row->id, $this->connection()));
SyncRule::load($row->id, $this->connection()) $mod = $sync->getExpectedModifications();
);
if (count($mod) > 0) { if (count($mod) > 0) {
$row->rule_name = $row->rule_name . ' (' . count($mod) . ')'; $row->rule_name = $row->rule_name . ' (' . count($mod) . ')';
return 'pending-changes'; return 'pending-changes';

View File

@ -60,51 +60,32 @@ class Sync
* Constructor. No direct initialization allowed right now. Please use one * Constructor. No direct initialization allowed right now. Please use one
* of the available static factory methods * of the available static factory methods
*/ */
protected function __construct(SyncRule $rule) public function __construct(SyncRule $rule)
{ {
$this->rule = $rule; $this->rule = $rule;
$this->db = $rule->getConnection(); $this->db = $rule->getConnection();
$this->syncProperties = $rule->fetchSyncProperties(); $this->syncProperties = $rule->fetchSyncProperties();
} }
/**
* Run the given sync rule
*/
public static function run(SyncRule $rule)
{
$sync = new static($rule);
// Raise limits. TODO: do this in a failsafe way, and only if necessary
ini_set('memory_limit', '768M');
ini_set('max_execution_time', 0);
return $sync->apply();
}
/** /**
* Whether the given sync rule would apply modifications * Whether the given sync rule would apply modifications
* *
* @param SyncRule $rule SyncRule object
*
* @return boolean * @return boolean
*/ */
public static function hasModifications(SyncRule $rule) public function hasModifications()
{ {
return count(self::getExpectedModifications()) > 0; return count($this->getExpectedModifications()) > 0;
} }
/** /**
* Retrieve modifications a given SyncRule would apply * Retrieve modifications a given SyncRule would apply
* *
* @param SyncRule $rule SyncRule object
*
* @return array Array of IcingaObject elements * @return array Array of IcingaObject elements
*/ */
public static function getExpectedModifications(SyncRule $rule) public function getExpectedModifications()
{ {
$modified = array(); $modified = array();
$sync = new static($rule); $objects = $this->prepare();
$objects = $sync->prepare();
foreach ($objects as $object) { foreach ($objects as $object) {
if ($object->hasBeenModified()) { if ($object->hasBeenModified()) {
$modified[] = $object; $modified[] = $object;
@ -234,6 +215,21 @@ class Sync
return preg_replace_callback('/\${([A-Za-z0-9\._-]+)}/', $func, $string); return preg_replace_callback('/\${([A-Za-z0-9\._-]+)}/', $func, $string);
} }
/**
* Raise PHP resource limits
*
* TODO: do this in a failsafe way, and only if necessary
*
* @return self;
*/
protected function raiseLimits()
{
ini_set('memory_limit', '768M');
ini_set('max_execution_time', 0);
return $this;
}
/** /**
* Instantiates all related ImportSource objects * Instantiates all related ImportSource objects
* *
@ -291,6 +287,7 @@ class Sync
if ($this->rule->object_type === 'service') { if ($this->rule->object_type === 'service') {
$hasHost = false; $hasHost = false;
$hasObjectName = false; $hasObjectName = false;
foreach ($this->syncProperties as $key => $property) { foreach ($this->syncProperties as $key => $property) {
if ($property->destination_field === 'host') { if ($property->destination_field === 'host') {
$hasHost = $property->source_expression; $hasHost = $property->source_expression;
@ -302,8 +299,13 @@ class Sync
if ($hasHost !== false && $hasObjectName !== false) { if ($hasHost !== false && $hasObjectName !== false) {
$this->hasCombinedKey = true; $this->hasCombinedKey = true;
$this->sourceKeyPattern = sprintf('%s!%s', $hasHost, $hasObjectName); $this->sourceKeyPattern = sprintf(
$this->destinationKeyPattern = 'host!object_name'; '%s!%s',
$hasHost,
$hasObjectName
);
$this->destinationKeyPattern = '${host}!${object_name}';
} }
} }
} }
@ -505,7 +507,8 @@ class Sync
protected function prepare() protected function prepare()
{ {
$rule = $this->rule; $rule = $this->rule;
$this->prepareRelatedImportSources() $this->raiseLimits()
->prepareRelatedImportSources()
->prepareSourceColumns() ->prepareSourceColumns()
->fetchImportedData() ->fetchImportedData()
->loadExistingObjects(); ->loadExistingObjects();
@ -515,7 +518,7 @@ class Sync
foreach ($newObjects as $key => $object) { foreach ($newObjects as $key => $object) {
if (array_key_exists($key, $this->objects)) { if (array_key_exists($key, $this->objects)) {
switch ($rule->update_policy) { switch ($this->rule->update_policy) {
case 'override': case 'override':
$this->objects[$key]->replaceWith($object); $this->objects[$key]->replaceWith($object);
break; break;
@ -534,7 +537,6 @@ class Sync
} }
} }
$objectKey = $rule->object_type === 'datalistEntry' ? 'entry_name' : 'object_name';
$noAction = array(); $noAction = array();
foreach ($this->objects as $key => $object) { foreach ($this->objects as $key => $object) {
@ -542,7 +544,7 @@ class Sync
if (array_key_exists($key, $newObjects)) { if (array_key_exists($key, $newObjects)) {
// Stats? // Stats?
} elseif ($object->hasBeenLoadedFromDb() && $rule->purge_existing === 'y') { } elseif ($object->hasBeenLoadedFromDb() && $this->rule->purge_existing === 'y') {
$object->markForRemoval(); $object->markForRemoval();
// TODO: this is for stats, preview, summary: // TODO: this is for stats, preview, summary:
@ -567,14 +569,12 @@ class Sync
* *
* @return int * @return int
*/ */
protected function apply() public function apply()
{ {
$db = $this->db;
// TODO: Evaluate whether fetching data should happen within the same transaction // TODO: Evaluate whether fetching data should happen within the same transaction
$objects = $this->prepare(); $objects = $this->prepare();
$dba = $db->getDbAdapter(); $dba = $this->db->getDbAdapter();
$dba->beginTransaction(); $dba->beginTransaction();
foreach ($objects as $object) { foreach ($objects as $object) {
if ($object instanceof IcingaObject && $object->isTemplate()) { if ($object instanceof IcingaObject && $object->isTemplate()) {
@ -588,12 +588,12 @@ class Sync
} }
if ($object instanceof IcingaObject && $object->shouldBeRemoved()) { if ($object instanceof IcingaObject && $object->shouldBeRemoved()) {
$object->delete($db); $object->delete($this->db);
continue; continue;
} }
if ($object->hasBeenModified()) { if ($object->hasBeenModified()) {
$object->store($db); $object->store($this->db);
} }
} }

View File

@ -0,0 +1,23 @@
CREATE TABLE sync_run (
id BIGINT(10) UNSIGNED AUTO_INCREMENT NOT NULL,
rule_id INT(10) UNSIGNED DEFAULT NULL,
rule_name VARCHAR(255) NOT NULL,
start_time DATETIME NOT NULL,
duration_ms INT(10) UNSIGNED NOT NULL,
objects_deleted INT(10) UNSIGNED DEFAULT 0,
objects_created INT(10) UNSIGNED DEFAULT 0,
objects_modified INT(10) UNSIGNED DEFAULT 0,
first_related_activity VARBINARY(20) DEFAULT NULL,
last_related_activity VARBINARY(20) DEFAULT NULL,
PRIMARY KEY (id),
CONSTRAINT sync_run_rule
FOREIGN KEY sync_rule (rule_id)
REFERENCES sync_rule (id)
ON DELETE SET NULL
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO director_schema_migration
SET migration_time = NOW(),
schema_version = 67;

View File

@ -1055,7 +1055,26 @@ CREATE TABLE sync_property (
ON UPDATE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE sync_run (
id BIGINT(10) UNSIGNED AUTO_INCREMENT NOT NULL,
rule_id INT(10) UNSIGNED DEFAULT NULL,
rule_name VARCHAR(255) NOT NULL,
start_time DATETIME NOT NULL,
duration_ms INT(10) UNSIGNED NOT NULL,
objects_deleted INT(10) UNSIGNED DEFAULT 0,
objects_created INT(10) UNSIGNED DEFAULT 0,
objects_modified INT(10) UNSIGNED DEFAULT 0,
first_related_activity VARBINARY(20) DEFAULT NULL,
last_related_activity VARBINARY(20) DEFAULT NULL,
PRIMARY KEY (id),
CONSTRAINT sync_run_rule
FOREIGN KEY sync_rule (rule_id)
REFERENCES sync_rule (id)
ON DELETE SET NULL
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO director_schema_migration INSERT INTO director_schema_migration
SET migration_time = NOW(), SET migration_time = NOW(),
schema_version = 66; schema_version = 67;