clean_sync.client library
A library for data subscription and synchronization in single page applications.
Functions
num handleDiff(List<Map> diff, Subscription subscription, String author) #
num handleDiff(List<Map> diff, Subscription subscription, String author) {
logger.fine('handleDiff: subscription: $subscription, author: $author,'
'diffSize: ${diff.length}, diff: $diff');
subscription.updateLock = true;
DataSet collection = subscription.collection;
var version = subscription._version;
num res = -1;
try {
diff.forEach((Map change) {
var _records = collection.findBy("_id", change["_id"]);
DataMap record = _records.isNotEmpty? _records.first : null;
String action = change["action"];
logger.finer('handling change $change');
// it can happen, that we get too old changes
if (!change.containsKey('version')){
logger.warning('change does not contain "version" field. If not testing, '
'this is probably bug. (change: $change)');
change['version'] = 0;
} else if (version == null) {
logger.warning('Subscription $subscription version is null. If not testing, '
'this is probably bug.');
} else if(change['version'] <= version) {
return;
}
if (action == "add") {
res = max(res, change['version']);
if (record == null) {
logger.finer('aplying changes (add)');
collection.add(change["data"]);
} else {
logger.finer('add discarded; same id already present');
assert(author == change['author']);
}
}
else if (action == "change" ) {
// 1. the change may be for item that is currently not present in the collection;
// 2. the field may be 'locked', because it was changed on user's machine, and
// this change was not yet confirmed from server
if (record != null) {
if(!subscription._sentItems.containsKey(record['_id'])
&& !subscription._modifiedItems.changedItems.containsKey('_id')) {
logger.finer('aplying changes (change)');
res = max(res, change['version']);
applyChange(change["data"], record);
} else {
logger.finer('discarding diff');
throw "stop";
}
}
}
else if (action == "remove" ) {
logger.finer('aplying changes (remove');
res = max(res, change['version']);
collection.remove(record);
}
logger.finest('applying finished: $subscription ${subscription.collection} ${subscription._version}');
});
} catch (e) {
if (e is Exception) {
throw e;
}
}
logger.fine('handleDiff ends');
// destroyStructure(diff);
subscription.updateLock = false;
return res;
}
void destroyStructure(s) #
void destroyStructure(s){
if (s is Map) {
destroyMap(s);
} else
if (s is Iterable) {
destroyIterable(s);
} else {}
}
void destroyIterable(l) #
void destroyIterable(var l) {
l.forEach((v){
destroyStructure(v);
});
for (var v in new List.from(l)) {
l.remove(v);
}
}
void destroyMap(Map m) #
void destroyMap(Map m) {
m.forEach((k,v){
destroyStructure(v);
});
for (var k in new List.from(m.keys)) {
m.remove(k);
}
}
bool applyChange(source, target) #
bool applyChange (source, target) {
if (source is Map && target is Map) {
_applyChangeMap(source, target);
return true;
}
if (source is List && target is List) {
_applyChangeList(source, target);
return true;
}
if(source == target) {
return true;
}
return false;
}
void handleData(List<Map> data, Subscription subscription, String author) #
void handleData(List<Map> data, Subscription subscription, String author) {
logger.fine('handleData: ${data}');
var collection = subscription.collection;
subscription.updateLock = true;
collection.clear();
collection.addAll(data);
subscription.updateLock = false;
}