method sync documentation in bbn\Appui\Dbsync
function(bbn\Db $db, $dbs = '', $dbs_table = '', $num_try = 0)
{
if (!self::isInit()) {
die("DB sync is not initiated");
}
self::disable();
$mode_db = self::$db->getErrorMode();
$mode_dbs = self::$dbs->getErrorMode();
self::$db->setErrorMode("continue");
self::$dbs->setErrorMode("continue");
if ( !$num_try ){
self::def($dbs, $dbs_table);
self::firstCall();
}
$num_try++;
$to_log = [
'deleted_sync' => 0,
'deleted_real' => 0,
'updated_sync' => 0,
'updated_real' => 0,
'inserted_sync' => 0,
'inserted_real' => 0,
'num_problems' => 0,
'problems' => []
];
$to_log['deleted_sync'] = self::deleteCompleted();
$retry = false;
// Selecting the entries inserted
$ds = self::$dbs->rselectAll(self::$dbs_table, ['id', 'tab', 'vals', 'chrono'], [
['db', '!=', self::$db->getCurrent()],
['state', '=', 0],
['action', 'LIKE', 'INSERT']
], [
'chrono' => 'ASC',
'id' => 'ASC'
]);
// They just have to be inserted
foreach ( $ds as $i => $d ){
if ( isset(self::$methods['cbf1']) ){
self::cbf1($d);
}
$vals = \bbn\X::jsonBase64Decode($d['vals']);
if ( !\is_array($vals) ){
$to_log['num_problems']++;
$to_log['problems'][] = "Hey, look urgently at the row $d[id]!";
}
else if ( self::$db->insert($d['tab'], $vals) ){
if ( isset(self::$methods['cbf2']) ){
self::cbf2($d);
}
$to_log['inserted_sync']++;
self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]);
}
else if ( self::$db->select($d['tab'], [], $vals) ){
self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]);
}
else{
if ( $num_try > self::$max_retry ){
$to_log['num_problems']++;
$to_log['problems'][] = "Problem while syncing (insert), check data with status 5 and ID ".$d['id'];
self::$dbs->update(self::$dbs_table, ["state" => 5], ["id" => $d['id']]);
}
$retry = 1;
}
}
// Selecting the entries modified and deleted in the twin DB,
// ordered by table and rows (so the same go together)
$ds = self::$dbs->rselectAll(self::$dbs_table, ['id', 'tab', 'action', 'rows', 'vals', 'chrono'], [
['db', '!=', self::$db->getCurrent()],
['state', '=', 0],
['rows', '!=', '[]'],
['action', '!=', 'insert']
], [
'tab' => 'ASC',
'rows' => 'ASC',
'chrono' => 'ASC',
'id' => 'ASC'
]);
foreach ( $ds as $i => $d ){
// Executing the first callback
$d['rows'] = bbn\X::jsonBase64Decode($d['rows']);
$d['vals'] = bbn\X::jsonBase64Decode($d['vals']);
if ( isset(self::$methods['cbf1']) ){
self::cbf1($d);
}
// Proceeding to the actions: delete is before
if ( strtolower($d['action']) === 'delete' ){
if ( self::$db->delete($d['tab'], $d['rows']) ){
self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]);
$to_log['deleted_real']++;
}
else if ( !self::$db->select($d['tab'], [], $d['rows']) ){
self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]);
}
else{
if ( $num_try > self::$max_retry ){
self::$dbs->update(self::$dbs_table, ["state" => 5], ["id" => $d['id']]);
$to_log['num_problems']++;
$to_log['problems'][] = "Problem while syncing (delete), check data with status 5 and ID ".$d['id'];
}
$retry = 1;
}
}
// Checking if there is another change done to this record and when in the twin DB
$next_time = (
isset($ds[$i+1]) &&
($ds[$i+1]['tab'] === $d['tab']) &&
($ds[$i+1]['rows'] === $d['rows'])
) ? $ds[$i+1]['chrono'] : microtime();
// Looking for the actions done on this specific record in our database
// between the twin change and the next (or now if there is no other change)
$each = self::$dbs->rselectAll(self::$dbs_table, ['id', 'chrono', 'action', 'vals'], [
['db', '=', self::$db->getCurrent()],
['tab', '=', $d['tab']],
['rows', '=', $d['rows']],
['chrono', '>=', $d['chrono']],
['chrono', '<', $next_time],
]);
if ( \count($each) > 0 ){
$to_log['num_problems']++;
$to_log['problems'][] = "Conflict!";
$to_log['problems'][] = $d;
foreach ( $each as $e ){
$e['vals'] = bbn\X::jsonBase64Decode($e['vals']);
// If it's deleted locally and updated on the twin we restore
if ( strtolower($e['action']) === 'delete' ){
if ( strtolower($d['action']) === 'update' ){
if ( !self::$db->insertUpdate(
$d['tab'],
bbn\X::mergeArrays(
$e['vals'],
$d['vals']
))
){
$to_log['num_problems']++;
$to_log['problems'][] = "insert_update number 1 had a problem";
}
}
}
// If it's updated locally and deleted in the twin we restore
else if ( strtolower($e['action']) === 'update' ){
if ( strtolower($d['action']) === 'delete' ){
if ( !self::$db->insertUpdate($d['tab'], bbn\X::mergeArrays($d['vals'], $e['vals'])) ){
$to_log['num_problems']++;
$to_log['problems'][] = "insert_update had a problem";
}
}
// If it's updated locally and in the twin we merge the values for the update
else if ( strtolower($d['action']) === 'update' ){
$d['vals'] = bbn\X::mergeArrays($d['vals'], $e['vals']);
}
}
}
}
// Proceeding to the actions update is after in case we needed to restore
if ( strtolower($d['action']) === 'update' ){
\bbn\X::log(bbn\X::mergeArrays($d['rows'], $d['vals']), 'synct');
if ( self::$db->update($d['tab'], $d['vals'], $d['rows']) ){
self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]);
$to_log['updated_real']++;
}
elseif ( self::$db->count($d['tab'], bbn\X::mergeArrays($d['rows'], $d['vals'])) ){
self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]);
}
else{
if ( $num_try > self::$max_retry ){
self::$dbs->update(self::$dbs_table, ["state" => 5], ["id" => $d['id']]);
$to_log['num_problems']++;
$to_log['problems'][] = "Problem while syncing (update), check data with status 5 and ID ".$d['id'];
}
$retry = 1;
}
}
// Callback number 2
if ( isset(self::$methods['cbf2']) ){
self::cbf2($d);
}
}
$res = [];
foreach ( $to_log as $k => $v ){
if ( !empty($v) ){
$res[$k] = $v;
}
}
self::$db->setErrorMode($mode_db);
self::$dbs->setErrorMode($mode_dbs);
self::enable();
if ( $retry && ( $num_try <= self::$max_retry ) ){
$res = bbn\X::mergeArrays($res, self::sync($db, $dbs, $dbs_table, $num_try));
}
return $res;
}
BBN is a suite of PHP and JS libraries and VueJS components - all open-source! bbn.io, build applications, the quick way
This website uses cookies to ensure you get the best experience on our website.
© 2011-2023
BBN Solutions