-
Notifications
You must be signed in to change notification settings - Fork 0
/
syncService.js
130 lines (109 loc) · 4.36 KB
/
syncService.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
var Q = require('q');
var extend = require('util')._extend;
var SyncInfo = require('./syncInfo.js');
var uuid = require('node-uuid');
var SyncService = function (options) {
var _syncInfoRepository = options.syncInfoRepository,
_entityRepository = options.entityRepository,
_lastEntityResolver = options.lastEntityResolver,
_currentSync = null;
var NO_SYNC_IN_PROGRESS = 'no sync in progress';
function getSyncInfo (syncOptions) {
return _syncInfoRepository
.getById(syncOptions.target)
.then(function(syncInfo){
if(syncInfo){
// if the sync exists, we want to enrich it with meta data
return Q.all([
getLastEntity(syncInfo),
count(syncInfo)
])
.then(function(data){
syncInfo.data = data[0];
syncInfo.count = data[1];
return syncInfo;
});
}
})
.then(function (syncInfo) {
return syncInfo || _syncInfoRepository.add(syncOptions.target, new SyncInfo({
target: syncOptions.target,
// we use a UNIX timestamp as id. Strictly speaking it's not unique across
// space and time but it's unique enough for us to work with. The use
// of uuids did not work out so well with elasticsearch because it has
// dashes and then one needs to deactivate the anaylizer via a mapping.
// That's a bit of an unconvienice especially for testing. We can work around
// that if we limit ourself to numbers which we do by using a UNIX timestamp.
taskId: Date.now()
}));
})
.then(function (syncInfo) {
// this comes as JSON, we need to wrap it with the model class to be usable
return new SyncInfo(syncInfo);
});
}
function sync (syncOptions) {
if (!syncOptions) {
throw new Error('syncOptions parameter is mandatory');
}
return getSyncInfo(syncOptions)
.then(function(syncInfo){
_currentSync = syncInfo;
return _currentSync;
})
}
function hasEntity (id) {
validateSyncInProgress();
// this HAS to be scoped to the syncID because otherwise: where is the point?
// This would return true very often but also for very old entities.
// We need to know whether it exists *within the current sync* or not!
return _entityRepository
.getByIdAndTaskId(id, _currentSync.taskId)
.then(function(entity){
return entity !== undefined;
});
}
function getLastEntity (syncInfo) {
return _lastEntityResolver.get(getTaskId(syncInfo));
}
function count (syncInfo) {
return _entityRepository.countByTaskId(getTaskId(syncInfo));
}
function getTaskId (syncInfo) {
validateSyncInProgress(syncInfo);
return (syncInfo || _currentSync).taskId;
}
function validateSyncInProgress (syncInfo) {
if (!syncInfo && !_currentSync) {
throw new Error(NO_SYNC_IN_PROGRESS);
}
}
function updateEntity (id, entity) {
validateSyncInProgress();
entity._ninya_sync_task_id = _currentSync.taskId;
entity._ninya_sync_last_sync = Date.now();
return _entityRepository.add(id, entity)
.then(function(entity){
console.log('SyncService: Updated Entity');
return entity;
});
}
function remove (deleteOptions) {
var target = (deleteOptions || _currentSync).target;
return _syncInfoRepository
.remove(target)
.then(function(){
_currentSync = null;
return undefined;
});
}
return {
sync: sync,
updateEntity: updateEntity,
getLastEntity: getLastEntity,
remove: remove,
hasEntity: hasEntity,
count: count
}
};
module.exports = SyncService;