-
Notifications
You must be signed in to change notification settings - Fork 79
/
Copy pathddp_update.js
119 lines (105 loc) · 4.38 KB
/
ddp_update.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
var reconnecting = false;
var originalLivedataData = Meteor.connection._livedata_data;
Meteor.connection._livedata_data = function(msg) {
if(FastRender._blockDDP && !msg.frGen) {
FastRender["debugger"].log('blocking incoming ddp', msg);
return;
};
// fast-render adds data manually while initializing
// But when the server sends actual data via DDP, it also tries to add
// Then we need to detect that and alter
//
// But we don't need to interfer with Meteor's simulation process
// That's why we are checking for serverDocs and ignore manual handling
//
// We don't need this logic after our special handling reverted back to
// original. But we can't detect when null publications completed or not
// That's why we need keep this logic
//
// It's okay to ignore this logic after sometime, but not sure when exactly
if(msg.msg == 'added') {
var id = IDTools.idParse(msg.id);
var serverDoc = this._getServerDoc(msg.collection, id);
if(!reconnecting && !serverDoc) {
var localCollection = this._mongo_livedata_collections[msg.collection];
var pendingStoreUpdates = this._updatesForUnknownStores[msg.collection];
if(localCollection) {
var existingDoc = localCollection.findOne(id);
if(existingDoc) {
FastRender["debugger"].log('re writing DDP for:', msg);
AddedToChanged(existingDoc, msg);
}
} else if(pendingStoreUpdates) {
var mergedDoc = null;
var existingDocs = _.filter(pendingStoreUpdates, function(doc) {
return doc.id == msg.id;
});
_.each(existingDocs, function(cachedMsg) {
mergedDoc = ApplyDDP(mergedDoc, cachedMsg);
});
if(mergedDoc) {
FastRender["debugger"].log('re writing DDP for:', msg);
AddedToChanged(mergedDoc, msg);
}
}
}
}
// if we've completed our tasks, no need of special handling
if(!FastRender._revertedBackToOriginal && FastRender._dataReceived) {
// This will take care of cleaning special subscription handling
// after the actual subscription comes out
if(msg.msg == 'ready' && !msg.frGen && FastRender._subscriptions) {
msg.subs.forEach(function(subId) {
var subscription = FastRender._subscriptionIdMap[subId];
if(subscription) {
FastRender["debugger"].log('actual subscription completed:', subscription, subId);
// we don't need to handle specially after this
var paramsKeyMap = FastRender._subscriptions[subscription.name] || {};
delete paramsKeyMap[subscription.paramsKey];
if(EJSON.equals(FastRender._subscriptions[subscription.name], {})) {
delete FastRender._subscriptions[subscription.name];
}
delete FastRender._subscriptionIdMap[subId];
}
});
}
// if all the subscriptions have been processed,
// there is no need to keep hijacking
if(EJSON.equals(FastRender._subscriptions, {})) {
FastRender["debugger"].log('fast rendering completed!');
FastRender._revertedBackToOriginal = true;
}
}
return originalLivedataData.call(this, msg);
};
var originalSend = Meteor.connection._send;
Meteor.connection._send = function(msg) {
// if looking for connect again to the server, we must need to revert back to
// original to prevent some weird DDP issues
// normally it is already reverted, but user may added subscriptions
// in server, which are not subscribed from the client
if(msg.msg == 'connect' && msg.session != undefined) {
FastRender._revertedBackToOriginal = true;
reconnecting = true;
}
var self = this;
// if we've completed our tasks, no need of special handling
if(!FastRender._revertedBackToOriginal && FastRender._dataReceived) {
var paramsKey = EJSON.stringify(msg.params);
var canSendFakeReady =
msg.msg == 'sub' &&
FastRender._subscriptions[msg.name] &&
FastRender._subscriptions[msg.name][paramsKey];
FastRender["debugger"].log('new subscription:', msg.name);
if(canSendFakeReady) {
FastRender["debugger"].log('sending fake ready for sub:', msg.name);
FastRender.injectDdpMessage(self, {msg:"ready",subs:[msg.id], frGen: true});
// add the messageId to be handled later
FastRender._subscriptionIdMap[msg.id] = {
name: msg.name,
paramsKey: paramsKey
};
}
}
return originalSend.call(this, msg);
};