@cloudbase/database 1.4.3 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/ObjectId/index.d.ts +1 -1
- package/dist/commonjs/ObjectId/index.js +16 -9
- package/dist/commonjs/aggregate.js +126 -75
- package/dist/commonjs/collection.d.ts +3 -2
- package/dist/commonjs/collection.js +131 -58
- package/dist/commonjs/command.d.ts +5 -5
- package/dist/commonjs/command.js +181 -154
- package/dist/commonjs/commands/logic.js +30 -20
- package/dist/commonjs/commands/query.d.ts +1 -1
- package/dist/commonjs/commands/query.js +85 -65
- package/dist/commonjs/commands/update.js +9 -7
- package/dist/commonjs/config/error.config.js +1 -0
- package/dist/commonjs/const/code.js +1 -0
- package/dist/commonjs/constant.d.ts +7 -7
- package/dist/commonjs/constant.js +13 -11
- package/dist/commonjs/document.d.ts +10 -6
- package/dist/commonjs/document.js +305 -193
- package/dist/commonjs/geo/index.js +20 -9
- package/dist/commonjs/geo/lineString.d.ts +1 -1
- package/dist/commonjs/geo/lineString.js +62 -33
- package/dist/commonjs/geo/multiLineString.d.ts +1 -1
- package/dist/commonjs/geo/multiLineString.js +71 -32
- package/dist/commonjs/geo/multiPoint.d.ts +1 -1
- package/dist/commonjs/geo/multiPoint.js +58 -29
- package/dist/commonjs/geo/multiPolygon.d.ts +1 -1
- package/dist/commonjs/geo/multiPolygon.js +96 -36
- package/dist/commonjs/geo/point.d.ts +1 -1
- package/dist/commonjs/geo/point.js +30 -23
- package/dist/commonjs/geo/polygon.d.ts +1 -1
- package/dist/commonjs/geo/polygon.js +78 -39
- package/dist/commonjs/helper/symbol.js +17 -5
- package/dist/commonjs/index.d.ts +8 -2
- package/dist/commonjs/index.js +73 -20
- package/dist/commonjs/lib/util.d.ts +1 -0
- package/dist/commonjs/lib/util.js +26 -0
- package/dist/commonjs/operator-map.js +7 -6
- package/dist/commonjs/query.d.ts +9 -5
- package/dist/commonjs/query.js +330 -205
- package/dist/commonjs/regexp/index.d.ts +1 -1
- package/dist/commonjs/regexp/index.js +16 -9
- package/dist/commonjs/serializer/common.d.ts +2 -2
- package/dist/commonjs/serializer/common.js +59 -22
- package/dist/commonjs/serializer/datatype.d.ts +2 -2
- package/dist/commonjs/serializer/datatype.js +58 -21
- package/dist/commonjs/serializer/query.d.ts +1 -1
- package/dist/commonjs/serializer/query.js +137 -127
- package/dist/commonjs/serializer/update.d.ts +1 -1
- package/dist/commonjs/serializer/update.js +83 -78
- package/dist/commonjs/serverDate/index.d.ts +1 -1
- package/dist/commonjs/serverDate/index.js +16 -9
- package/dist/commonjs/transaction/collection.d.ts +7 -0
- package/dist/commonjs/transaction/collection.js +49 -0
- package/dist/commonjs/transaction/document.d.ts +27 -0
- package/dist/commonjs/transaction/document.js +205 -0
- package/dist/commonjs/transaction/index.js +196 -86
- package/dist/commonjs/transaction/query.d.ts +43 -0
- package/dist/commonjs/transaction/query.js +261 -0
- package/dist/commonjs/typings/index.d.ts +4 -4
- package/dist/commonjs/typings/realtime.d.ts +16 -16
- package/dist/commonjs/util.js +123 -92
- package/dist/commonjs/utils/error.d.ts +2 -1
- package/dist/commonjs/utils/error.js +74 -38
- package/dist/commonjs/utils/symbol.js +33 -14
- package/dist/commonjs/utils/type.d.ts +1 -1
- package/dist/commonjs/utils/type.js +25 -13
- package/dist/commonjs/utils/utils.d.ts +5 -1
- package/dist/commonjs/utils/utils.js +153 -22
- package/dist/commonjs/validate.js +79 -63
- package/dist/esm/ObjectId/index.d.ts +1 -1
- package/dist/esm/ObjectId/index.js +15 -8
- package/dist/esm/aggregate.js +118 -66
- package/dist/esm/collection.d.ts +3 -2
- package/dist/esm/collection.js +125 -52
- package/dist/esm/command.d.ts +5 -5
- package/dist/esm/command.js +175 -147
- package/dist/esm/commands/logic.js +30 -20
- package/dist/esm/commands/query.d.ts +1 -1
- package/dist/esm/commands/query.js +91 -71
- package/dist/esm/commands/update.js +8 -6
- package/dist/esm/config/error.config.js +1 -1
- package/dist/esm/const/code.js +1 -1
- package/dist/esm/constant.d.ts +7 -7
- package/dist/esm/constant.js +12 -11
- package/dist/esm/document.d.ts +10 -6
- package/dist/esm/document.js +297 -185
- package/dist/esm/geo/interface.js +1 -0
- package/dist/esm/geo/lineString.d.ts +1 -1
- package/dist/esm/geo/lineString.js +57 -28
- package/dist/esm/geo/multiLineString.d.ts +1 -1
- package/dist/esm/geo/multiLineString.js +66 -27
- package/dist/esm/geo/multiPoint.d.ts +1 -1
- package/dist/esm/geo/multiPoint.js +53 -24
- package/dist/esm/geo/multiPolygon.d.ts +1 -1
- package/dist/esm/geo/multiPolygon.js +91 -31
- package/dist/esm/geo/point.d.ts +1 -1
- package/dist/esm/geo/point.js +26 -19
- package/dist/esm/geo/polygon.d.ts +1 -1
- package/dist/esm/geo/polygon.js +73 -34
- package/dist/esm/helper/symbol.js +13 -13
- package/dist/esm/index.d.ts +8 -2
- package/dist/esm/index.js +62 -9
- package/dist/esm/lib/util.d.ts +1 -0
- package/dist/esm/lib/util.js +22 -0
- package/dist/esm/operator-map.js +4 -4
- package/dist/esm/query.d.ts +9 -5
- package/dist/esm/query.js +321 -196
- package/dist/esm/regexp/index.d.ts +1 -1
- package/dist/esm/regexp/index.js +15 -8
- package/dist/esm/serializer/common.d.ts +2 -2
- package/dist/esm/serializer/common.js +49 -13
- package/dist/esm/serializer/datatype.d.ts +2 -2
- package/dist/esm/serializer/datatype.js +44 -8
- package/dist/esm/serializer/query.d.ts +1 -1
- package/dist/esm/serializer/query.js +112 -102
- package/dist/esm/serializer/update.d.ts +1 -1
- package/dist/esm/serializer/update.js +69 -64
- package/dist/esm/serverDate/index.d.ts +1 -1
- package/dist/esm/serverDate/index.js +15 -8
- package/dist/esm/transaction/collection.d.ts +7 -0
- package/dist/esm/transaction/collection.js +46 -0
- package/dist/esm/transaction/document.d.ts +27 -0
- package/dist/esm/transaction/document.js +202 -0
- package/dist/esm/transaction/index.js +191 -81
- package/dist/esm/transaction/query.d.ts +43 -0
- package/dist/esm/transaction/query.js +258 -0
- package/dist/esm/typings/index.d.ts +4 -4
- package/dist/esm/typings/index.js +1 -0
- package/dist/esm/typings/realtime.d.ts +16 -16
- package/dist/esm/typings/realtime.js +1 -0
- package/dist/esm/util.js +121 -90
- package/dist/esm/utils/error.d.ts +2 -1
- package/dist/esm/utils/error.js +70 -35
- package/dist/esm/utils/symbol.js +33 -14
- package/dist/esm/utils/type.d.ts +1 -1
- package/dist/esm/utils/type.js +12 -12
- package/dist/esm/utils/utils.d.ts +5 -1
- package/dist/esm/utils/utils.js +137 -16
- package/dist/esm/validate.js +65 -49
- package/jest.config.js +14 -0
- package/package.json +14 -10
- package/src/aggregate.ts +1 -5
- package/src/collection.ts +15 -2
- package/src/document.ts +45 -34
- package/src/index.ts +51 -4
- package/src/query.ts +48 -38
- package/src/serializer/query.ts +18 -6
- package/src/transaction/index.ts +1 -1
- package/src/typings/index.ts +0 -4
- package/src/utils/utils.ts +105 -0
- package/src/validate.ts +3 -6
- package/tests/gateway-contract.test.ts +180 -0
- package/tests/index.test.ts +283 -0
- package/tests/transaction-query.test.ts +207 -0
- package/tests/watch-query.test.ts +144 -0
- package/tsconfig.esm.json +4 -2
- package/tsconfig.json +16 -6
- package/tsconfig.test.json +15 -0
- package/dist/commonjs/realtime/error.d.ts +0 -7
- package/dist/commonjs/realtime/error.js +0 -11
- package/dist/commonjs/realtime/listener.d.ts +0 -14
- package/dist/commonjs/realtime/listener.js +0 -17
- package/dist/commonjs/realtime/message.d.ts +0 -3
- package/dist/commonjs/realtime/message.js +0 -10
- package/dist/commonjs/realtime/snapshot.d.ts +0 -16
- package/dist/commonjs/realtime/snapshot.js +0 -42
- package/dist/commonjs/realtime/virtual-websocket-client.d.ts +0 -63
- package/dist/commonjs/realtime/virtual-websocket-client.js +0 -736
- package/dist/commonjs/realtime/websocket-client.d.ts +0 -78
- package/dist/commonjs/realtime/websocket-client.js +0 -567
- package/dist/commonjs/realtime/ws-event.d.ts +0 -126
- package/dist/commonjs/realtime/ws-event.js +0 -139
- package/dist/commonjs/transaction.d.ts +0 -42
- package/dist/commonjs/transaction.js +0 -126
- package/dist/esm/realtime/error.d.ts +0 -7
- package/dist/esm/realtime/error.js +0 -8
- package/dist/esm/realtime/listener.d.ts +0 -14
- package/dist/esm/realtime/listener.js +0 -14
- package/dist/esm/realtime/message.d.ts +0 -3
- package/dist/esm/realtime/message.js +0 -6
- package/dist/esm/realtime/snapshot.d.ts +0 -16
- package/dist/esm/realtime/snapshot.js +0 -39
- package/dist/esm/realtime/virtual-websocket-client.d.ts +0 -63
- package/dist/esm/realtime/virtual-websocket-client.js +0 -733
- package/dist/esm/realtime/websocket-client.d.ts +0 -78
- package/dist/esm/realtime/websocket-client.js +0 -564
- package/dist/esm/realtime/ws-event.d.ts +0 -126
- package/dist/esm/realtime/ws-event.js +0 -137
- package/dist/esm/transaction.d.ts +0 -42
- package/dist/esm/transaction.js +0 -121
- package/src/realtime/error.ts +0 -19
- package/src/realtime/listener.ts +0 -35
- package/src/realtime/message.ts +0 -14
- package/src/realtime/snapshot.ts +0 -60
- package/src/realtime/virtual-websocket-client.ts +0 -1195
- package/src/realtime/websocket-client.ts +0 -995
- package/src/realtime/ws-event.ts +0 -163
- package/src/transaction.ts +0 -190
|
@@ -1,733 +0,0 @@
|
|
|
1
|
-
import set from 'lodash.set';
|
|
2
|
-
import unset from 'lodash.unset';
|
|
3
|
-
import cloneDeep from 'lodash.clonedeep';
|
|
4
|
-
import { genRequestId } from './message';
|
|
5
|
-
import { CloudSDKError, isTimeoutError, CancelledError, isCancelledError } from '../utils/error';
|
|
6
|
-
import { ERR_CODE } from '../config/error.config';
|
|
7
|
-
import { sleep } from '../utils/utils';
|
|
8
|
-
import { RealtimeListener } from './listener';
|
|
9
|
-
import { Snapshot } from './snapshot';
|
|
10
|
-
import { isRealtimeErrorMessageError } from './error';
|
|
11
|
-
var WATCH_STATUS;
|
|
12
|
-
(function (WATCH_STATUS) {
|
|
13
|
-
WATCH_STATUS["LOGGINGIN"] = "LOGGINGIN";
|
|
14
|
-
WATCH_STATUS["INITING"] = "INITING";
|
|
15
|
-
WATCH_STATUS["REBUILDING"] = "REBUILDING";
|
|
16
|
-
WATCH_STATUS["ACTIVE"] = "ACTIVE";
|
|
17
|
-
WATCH_STATUS["ERRORED"] = "ERRORED";
|
|
18
|
-
WATCH_STATUS["CLOSING"] = "CLOSING";
|
|
19
|
-
WATCH_STATUS["CLOSED"] = "CLOSED";
|
|
20
|
-
WATCH_STATUS["PAUSED"] = "PAUSED";
|
|
21
|
-
WATCH_STATUS["RESUMING"] = "RESUMING";
|
|
22
|
-
})(WATCH_STATUS || (WATCH_STATUS = {}));
|
|
23
|
-
const DEFAULT_WAIT_TIME_ON_UNKNOWN_ERROR = 100;
|
|
24
|
-
const DEFAULT_MAX_AUTO_RETRY_ON_ERROR = 2;
|
|
25
|
-
const DEFAULT_MAX_SEND_ACK_AUTO_RETRY_ON_ERROR = 2;
|
|
26
|
-
const DEFAULT_SEND_ACK_DEBOUNCE_TIMEOUT = 10 * 1000;
|
|
27
|
-
const DEFAULT_INIT_WATCH_TIMEOUT = 10 * 1000;
|
|
28
|
-
const DEFAULT_REBUILD_WATCH_TIMEOUT = 10 * 1000;
|
|
29
|
-
export class VirtualWebSocketClient {
|
|
30
|
-
constructor(options) {
|
|
31
|
-
this.watchStatus = WATCH_STATUS.INITING;
|
|
32
|
-
this._login = async (envId, refresh) => {
|
|
33
|
-
this.watchStatus = WATCH_STATUS.LOGGINGIN;
|
|
34
|
-
const loginResult = await this.login(envId, refresh);
|
|
35
|
-
if (!this.envId) {
|
|
36
|
-
this.envId = loginResult.envId;
|
|
37
|
-
}
|
|
38
|
-
return loginResult;
|
|
39
|
-
};
|
|
40
|
-
this.initWatch = async (forceRefreshLogin) => {
|
|
41
|
-
if (this._initWatchPromise) {
|
|
42
|
-
return this._initWatchPromise;
|
|
43
|
-
}
|
|
44
|
-
this._initWatchPromise = new Promise(async (resolve, reject) => {
|
|
45
|
-
try {
|
|
46
|
-
if (this.watchStatus === WATCH_STATUS.PAUSED) {
|
|
47
|
-
console.log('[realtime] initWatch cancelled on pause');
|
|
48
|
-
return resolve();
|
|
49
|
-
}
|
|
50
|
-
const { envId } = await this._login(this.envId, forceRefreshLogin);
|
|
51
|
-
if (this.watchStatus === WATCH_STATUS.PAUSED) {
|
|
52
|
-
console.log('[realtime] initWatch cancelled on pause');
|
|
53
|
-
return resolve();
|
|
54
|
-
}
|
|
55
|
-
this.watchStatus = WATCH_STATUS.INITING;
|
|
56
|
-
const initWatchMsg = {
|
|
57
|
-
watchId: this.watchId,
|
|
58
|
-
requestId: genRequestId(),
|
|
59
|
-
msgType: 'INIT_WATCH',
|
|
60
|
-
msgData: {
|
|
61
|
-
envId,
|
|
62
|
-
collName: this.collectionName,
|
|
63
|
-
query: this.query,
|
|
64
|
-
limit: this.limit,
|
|
65
|
-
orderBy: this.orderBy
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
const initEventMsg = await this.send({
|
|
69
|
-
msg: initWatchMsg,
|
|
70
|
-
waitResponse: true,
|
|
71
|
-
skipOnMessage: true,
|
|
72
|
-
timeout: DEFAULT_INIT_WATCH_TIMEOUT
|
|
73
|
-
});
|
|
74
|
-
const { events, currEvent } = initEventMsg.msgData;
|
|
75
|
-
this.sessionInfo = {
|
|
76
|
-
queryID: initEventMsg.msgData.queryID,
|
|
77
|
-
currentEventId: currEvent - 1,
|
|
78
|
-
currentDocs: []
|
|
79
|
-
};
|
|
80
|
-
if (events.length > 0) {
|
|
81
|
-
for (const e of events) {
|
|
82
|
-
e.ID = currEvent;
|
|
83
|
-
}
|
|
84
|
-
this.handleServerEvents(initEventMsg);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
this.sessionInfo.currentEventId = currEvent;
|
|
88
|
-
const snapshot = new Snapshot({
|
|
89
|
-
id: currEvent,
|
|
90
|
-
docChanges: [],
|
|
91
|
-
docs: [],
|
|
92
|
-
type: 'init'
|
|
93
|
-
});
|
|
94
|
-
this.listener.onChange(snapshot);
|
|
95
|
-
this.scheduleSendACK();
|
|
96
|
-
}
|
|
97
|
-
this.onWatchStart(this, this.sessionInfo.queryID);
|
|
98
|
-
this.watchStatus = WATCH_STATUS.ACTIVE;
|
|
99
|
-
this._availableRetries.INIT_WATCH = DEFAULT_MAX_AUTO_RETRY_ON_ERROR;
|
|
100
|
-
resolve();
|
|
101
|
-
}
|
|
102
|
-
catch (e) {
|
|
103
|
-
this.handleWatchEstablishmentError(e, {
|
|
104
|
-
operationName: 'INIT_WATCH',
|
|
105
|
-
resolve,
|
|
106
|
-
reject
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
let success = false;
|
|
111
|
-
try {
|
|
112
|
-
await this._initWatchPromise;
|
|
113
|
-
success = true;
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
this._initWatchPromise = undefined;
|
|
117
|
-
}
|
|
118
|
-
console.log(`[realtime] initWatch ${success ? 'success' : 'fail'}`);
|
|
119
|
-
};
|
|
120
|
-
this.rebuildWatch = async (forceRefreshLogin) => {
|
|
121
|
-
if (this._rebuildWatchPromise) {
|
|
122
|
-
return this._rebuildWatchPromise;
|
|
123
|
-
}
|
|
124
|
-
this._rebuildWatchPromise = new Promise(async (resolve, reject) => {
|
|
125
|
-
try {
|
|
126
|
-
if (this.watchStatus === WATCH_STATUS.PAUSED) {
|
|
127
|
-
console.log('[realtime] rebuildWatch cancelled on pause');
|
|
128
|
-
return resolve();
|
|
129
|
-
}
|
|
130
|
-
const { envId } = await this._login(this.envId, forceRefreshLogin);
|
|
131
|
-
if (!this.sessionInfo) {
|
|
132
|
-
throw new Error('can not rebuildWatch without a successful initWatch (lack of sessionInfo)');
|
|
133
|
-
}
|
|
134
|
-
if (this.watchStatus === WATCH_STATUS.PAUSED) {
|
|
135
|
-
console.log('[realtime] rebuildWatch cancelled on pause');
|
|
136
|
-
return resolve();
|
|
137
|
-
}
|
|
138
|
-
this.watchStatus = WATCH_STATUS.REBUILDING;
|
|
139
|
-
const rebuildWatchMsg = {
|
|
140
|
-
watchId: this.watchId,
|
|
141
|
-
requestId: genRequestId(),
|
|
142
|
-
msgType: 'REBUILD_WATCH',
|
|
143
|
-
msgData: {
|
|
144
|
-
envId,
|
|
145
|
-
collName: this.collectionName,
|
|
146
|
-
queryID: this.sessionInfo.queryID,
|
|
147
|
-
eventID: this.sessionInfo.currentEventId
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
const nextEventMsg = await this.send({
|
|
151
|
-
msg: rebuildWatchMsg,
|
|
152
|
-
waitResponse: true,
|
|
153
|
-
skipOnMessage: false,
|
|
154
|
-
timeout: DEFAULT_REBUILD_WATCH_TIMEOUT
|
|
155
|
-
});
|
|
156
|
-
this.handleServerEvents(nextEventMsg);
|
|
157
|
-
this.watchStatus = WATCH_STATUS.ACTIVE;
|
|
158
|
-
this._availableRetries.REBUILD_WATCH = DEFAULT_MAX_AUTO_RETRY_ON_ERROR;
|
|
159
|
-
resolve();
|
|
160
|
-
}
|
|
161
|
-
catch (e) {
|
|
162
|
-
this.handleWatchEstablishmentError(e, {
|
|
163
|
-
operationName: 'REBUILD_WATCH',
|
|
164
|
-
resolve,
|
|
165
|
-
reject
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
let success = false;
|
|
170
|
-
try {
|
|
171
|
-
await this._rebuildWatchPromise;
|
|
172
|
-
success = true;
|
|
173
|
-
}
|
|
174
|
-
finally {
|
|
175
|
-
this._rebuildWatchPromise = undefined;
|
|
176
|
-
}
|
|
177
|
-
console.log(`[realtime] rebuildWatch ${success ? 'success' : 'fail'}`);
|
|
178
|
-
};
|
|
179
|
-
this.handleWatchEstablishmentError = async (e, options) => {
|
|
180
|
-
const isInitWatch = options.operationName === 'INIT_WATCH';
|
|
181
|
-
const abortWatch = () => {
|
|
182
|
-
this.closeWithError(new CloudSDKError({
|
|
183
|
-
errCode: isInitWatch
|
|
184
|
-
? ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_INIT_WATCH_FAIL
|
|
185
|
-
: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_REBUILD_WATCH_FAIL,
|
|
186
|
-
errMsg: e
|
|
187
|
-
}));
|
|
188
|
-
options.reject(e);
|
|
189
|
-
};
|
|
190
|
-
const retry = (refreshLogin) => {
|
|
191
|
-
if (this.useRetryTicket(options.operationName)) {
|
|
192
|
-
if (isInitWatch) {
|
|
193
|
-
this._initWatchPromise = undefined;
|
|
194
|
-
options.resolve(this.initWatch(refreshLogin));
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
this._rebuildWatchPromise = undefined;
|
|
198
|
-
options.resolve(this.rebuildWatch(refreshLogin));
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
abortWatch();
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
this.handleCommonError(e, {
|
|
206
|
-
onSignError: () => retry(true),
|
|
207
|
-
onTimeoutError: () => retry(false),
|
|
208
|
-
onNotRetryableError: abortWatch,
|
|
209
|
-
onCancelledError: options.reject,
|
|
210
|
-
onUnknownError: async () => {
|
|
211
|
-
try {
|
|
212
|
-
const onWSDisconnected = async () => {
|
|
213
|
-
this.pause();
|
|
214
|
-
await this.onceWSConnected();
|
|
215
|
-
retry(true);
|
|
216
|
-
};
|
|
217
|
-
if (!this.isWSConnected()) {
|
|
218
|
-
await onWSDisconnected();
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
await sleep(DEFAULT_WAIT_TIME_ON_UNKNOWN_ERROR);
|
|
222
|
-
if (this.watchStatus === WATCH_STATUS.PAUSED) {
|
|
223
|
-
options.reject(new CancelledError(`${options.operationName} cancelled due to pause after unknownError`));
|
|
224
|
-
}
|
|
225
|
-
else if (!this.isWSConnected()) {
|
|
226
|
-
await onWSDisconnected();
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
retry(false);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
catch (e) {
|
|
234
|
-
retry(true);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
};
|
|
239
|
-
this.closeWatch = async () => {
|
|
240
|
-
const queryId = this.sessionInfo ? this.sessionInfo.queryID : '';
|
|
241
|
-
if (this.watchStatus !== WATCH_STATUS.ACTIVE) {
|
|
242
|
-
this.watchStatus = WATCH_STATUS.CLOSED;
|
|
243
|
-
this.onWatchClose(this, queryId);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
try {
|
|
247
|
-
this.watchStatus = WATCH_STATUS.CLOSING;
|
|
248
|
-
const closeWatchMsg = {
|
|
249
|
-
watchId: this.watchId,
|
|
250
|
-
requestId: genRequestId(),
|
|
251
|
-
msgType: 'CLOSE_WATCH',
|
|
252
|
-
msgData: null
|
|
253
|
-
};
|
|
254
|
-
await this.send({
|
|
255
|
-
msg: closeWatchMsg
|
|
256
|
-
});
|
|
257
|
-
this.sessionInfo = undefined;
|
|
258
|
-
this.watchStatus = WATCH_STATUS.CLOSED;
|
|
259
|
-
}
|
|
260
|
-
catch (e) {
|
|
261
|
-
this.closeWithError(new CloudSDKError({
|
|
262
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_CLOSE_WATCH_FAIL,
|
|
263
|
-
errMsg: e
|
|
264
|
-
}));
|
|
265
|
-
}
|
|
266
|
-
finally {
|
|
267
|
-
this.onWatchClose(this, queryId);
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
this.scheduleSendACK = () => {
|
|
271
|
-
this.clearACKSchedule();
|
|
272
|
-
this._ackTimeoutId = setTimeout(() => {
|
|
273
|
-
if (this._waitExpectedTimeoutId) {
|
|
274
|
-
this.scheduleSendACK();
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
this.sendACK();
|
|
278
|
-
}
|
|
279
|
-
}, DEFAULT_SEND_ACK_DEBOUNCE_TIMEOUT);
|
|
280
|
-
};
|
|
281
|
-
this.clearACKSchedule = () => {
|
|
282
|
-
if (this._ackTimeoutId) {
|
|
283
|
-
clearTimeout(this._ackTimeoutId);
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
this.sendACK = async () => {
|
|
287
|
-
try {
|
|
288
|
-
if (this.watchStatus !== WATCH_STATUS.ACTIVE) {
|
|
289
|
-
this.scheduleSendACK();
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
if (!this.sessionInfo) {
|
|
293
|
-
console.warn('[realtime listener] can not send ack without a successful initWatch (lack of sessionInfo)');
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const ackMsg = {
|
|
297
|
-
watchId: this.watchId,
|
|
298
|
-
requestId: genRequestId(),
|
|
299
|
-
msgType: 'CHECK_LAST',
|
|
300
|
-
msgData: {
|
|
301
|
-
queryID: this.sessionInfo.queryID,
|
|
302
|
-
eventID: this.sessionInfo.currentEventId
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
await this.send({
|
|
306
|
-
msg: ackMsg
|
|
307
|
-
});
|
|
308
|
-
this.scheduleSendACK();
|
|
309
|
-
}
|
|
310
|
-
catch (e) {
|
|
311
|
-
if (isRealtimeErrorMessageError(e)) {
|
|
312
|
-
const msg = e.payload;
|
|
313
|
-
switch (msg.msgData.code) {
|
|
314
|
-
case 'CHECK_LOGIN_FAILED':
|
|
315
|
-
case 'SIGN_EXPIRED_ERROR':
|
|
316
|
-
case 'SIGN_INVALID_ERROR':
|
|
317
|
-
case 'SIGN_PARAM_INVALID': {
|
|
318
|
-
this.rebuildWatch();
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
case 'QUERYID_INVALID_ERROR':
|
|
322
|
-
case 'SYS_ERR':
|
|
323
|
-
case 'INVALIID_ENV':
|
|
324
|
-
case 'COLLECTION_PERMISSION_DENIED': {
|
|
325
|
-
this.closeWithError(new CloudSDKError({
|
|
326
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_CHECK_LAST_FAIL,
|
|
327
|
-
errMsg: msg.msgData.code
|
|
328
|
-
}));
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
default: {
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
if (this._availableRetries.CHECK_LAST &&
|
|
337
|
-
this._availableRetries.CHECK_LAST > 0) {
|
|
338
|
-
this._availableRetries.CHECK_LAST--;
|
|
339
|
-
this.scheduleSendACK();
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
this.closeWithError(new CloudSDKError({
|
|
343
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_CHECK_LAST_FAIL,
|
|
344
|
-
errMsg: e
|
|
345
|
-
}));
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
this.handleCommonError = (e, options) => {
|
|
350
|
-
if (isRealtimeErrorMessageError(e)) {
|
|
351
|
-
const msg = e.payload;
|
|
352
|
-
switch (msg.msgData.code) {
|
|
353
|
-
case 'CHECK_LOGIN_FAILED':
|
|
354
|
-
case 'SIGN_EXPIRED_ERROR':
|
|
355
|
-
case 'SIGN_INVALID_ERROR':
|
|
356
|
-
case 'SIGN_PARAM_INVALID': {
|
|
357
|
-
options.onSignError(e);
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
case 'QUERYID_INVALID_ERROR':
|
|
361
|
-
case 'SYS_ERR':
|
|
362
|
-
case 'INVALIID_ENV':
|
|
363
|
-
case 'COLLECTION_PERMISSION_DENIED': {
|
|
364
|
-
options.onNotRetryableError(e);
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
default: {
|
|
368
|
-
options.onNotRetryableError(e);
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
else if (isTimeoutError(e)) {
|
|
374
|
-
options.onTimeoutError(e);
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
else if (isCancelledError(e)) {
|
|
378
|
-
options.onCancelledError(e);
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
options.onUnknownError(e);
|
|
382
|
-
};
|
|
383
|
-
this.watchId = `watchid_${+new Date()}_${Math.random()}`;
|
|
384
|
-
this.envId = options.envId;
|
|
385
|
-
this.collectionName = options.collectionName;
|
|
386
|
-
this.query = options.query;
|
|
387
|
-
this.limit = options.limit;
|
|
388
|
-
this.orderBy = options.orderBy;
|
|
389
|
-
this.send = options.send;
|
|
390
|
-
this.login = options.login;
|
|
391
|
-
this.isWSConnected = options.isWSConnected;
|
|
392
|
-
this.onceWSConnected = options.onceWSConnected;
|
|
393
|
-
this.getWaitExpectedTimeoutLength = options.getWaitExpectedTimeoutLength;
|
|
394
|
-
this.onWatchStart = options.onWatchStart;
|
|
395
|
-
this.onWatchClose = options.onWatchClose;
|
|
396
|
-
this.debug = options.debug;
|
|
397
|
-
this._availableRetries = {
|
|
398
|
-
INIT_WATCH: DEFAULT_MAX_AUTO_RETRY_ON_ERROR,
|
|
399
|
-
REBUILD_WATCH: DEFAULT_MAX_AUTO_RETRY_ON_ERROR,
|
|
400
|
-
CHECK_LAST: DEFAULT_MAX_SEND_ACK_AUTO_RETRY_ON_ERROR
|
|
401
|
-
};
|
|
402
|
-
this.listener = new RealtimeListener({
|
|
403
|
-
close: this.closeWatch,
|
|
404
|
-
onChange: options.onChange,
|
|
405
|
-
onError: options.onError,
|
|
406
|
-
debug: this.debug,
|
|
407
|
-
virtualClient: this
|
|
408
|
-
});
|
|
409
|
-
this.initWatch();
|
|
410
|
-
}
|
|
411
|
-
useRetryTicket(operationName) {
|
|
412
|
-
if (this._availableRetries[operationName] &&
|
|
413
|
-
this._availableRetries[operationName] > 0) {
|
|
414
|
-
this._availableRetries[operationName]--;
|
|
415
|
-
console.log(`[realtime] ${operationName} use a retry ticket, now only ${this._availableRetries[operationName]} retry left`);
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
async handleServerEvents(msg) {
|
|
421
|
-
try {
|
|
422
|
-
this.scheduleSendACK();
|
|
423
|
-
await this._handleServerEvents(msg);
|
|
424
|
-
this._postHandleServerEventsValidityCheck(msg);
|
|
425
|
-
}
|
|
426
|
-
catch (e) {
|
|
427
|
-
console.error('[realtime listener] internal non-fatal error: handle server events failed with error: ', e);
|
|
428
|
-
throw e;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
async _handleServerEvents(msg) {
|
|
432
|
-
const { requestId } = msg;
|
|
433
|
-
const { events } = msg.msgData;
|
|
434
|
-
const { msgType } = msg;
|
|
435
|
-
if (!events.length || !this.sessionInfo) {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
const sessionInfo = this.sessionInfo;
|
|
439
|
-
let allChangeEvents;
|
|
440
|
-
try {
|
|
441
|
-
allChangeEvents = events.map(getPublicEvent);
|
|
442
|
-
}
|
|
443
|
-
catch (e) {
|
|
444
|
-
this.closeWithError(new CloudSDKError({
|
|
445
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_RECEIVE_INVALID_SERVER_DATA,
|
|
446
|
-
errMsg: e
|
|
447
|
-
}));
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
let docs = [...sessionInfo.currentDocs];
|
|
451
|
-
let initEncountered = false;
|
|
452
|
-
for (let i = 0, len = allChangeEvents.length; i < len; i++) {
|
|
453
|
-
const change = allChangeEvents[i];
|
|
454
|
-
if (sessionInfo.currentEventId >= change.id) {
|
|
455
|
-
if (!allChangeEvents[i - 1] || change.id > allChangeEvents[i - 1].id) {
|
|
456
|
-
console.warn(`[realtime] duplicate event received, cur ${sessionInfo.currentEventId} but got ${change.id}`);
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
console.error(`[realtime listener] server non-fatal error: events out of order (the latter event's id is smaller than that of the former) (requestId ${requestId})`);
|
|
460
|
-
}
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
else if (sessionInfo.currentEventId === change.id - 1) {
|
|
464
|
-
switch (change.dataType) {
|
|
465
|
-
case 'update': {
|
|
466
|
-
if (!change.doc) {
|
|
467
|
-
switch (change.queueType) {
|
|
468
|
-
case 'update':
|
|
469
|
-
case 'dequeue': {
|
|
470
|
-
const localDoc = docs.find(doc => doc._id === change.docId);
|
|
471
|
-
if (localDoc) {
|
|
472
|
-
const doc = cloneDeep(localDoc);
|
|
473
|
-
if (change.updatedFields) {
|
|
474
|
-
for (const fieldPath in change.updatedFields) {
|
|
475
|
-
set(doc, fieldPath, change.updatedFields[fieldPath]);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
if (change.removedFields) {
|
|
479
|
-
for (const fieldPath of change.removedFields) {
|
|
480
|
-
unset(doc, fieldPath);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
change.doc = doc;
|
|
484
|
-
}
|
|
485
|
-
else {
|
|
486
|
-
console.error('[realtime listener] internal non-fatal server error: unexpected update dataType event where no doc is associated.');
|
|
487
|
-
}
|
|
488
|
-
break;
|
|
489
|
-
}
|
|
490
|
-
case 'enqueue': {
|
|
491
|
-
const err = new CloudSDKError({
|
|
492
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_UNEXPECTED_FATAL_ERROR,
|
|
493
|
-
errMsg: `HandleServerEvents: full doc is not provided with dataType="update" and queueType="enqueue" (requestId ${msg.requestId})`
|
|
494
|
-
});
|
|
495
|
-
this.closeWithError(err);
|
|
496
|
-
throw err;
|
|
497
|
-
}
|
|
498
|
-
default: {
|
|
499
|
-
break;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
|
-
case 'replace': {
|
|
506
|
-
if (!change.doc) {
|
|
507
|
-
const err = new CloudSDKError({
|
|
508
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_UNEXPECTED_FATAL_ERROR,
|
|
509
|
-
errMsg: `HandleServerEvents: full doc is not provided with dataType="replace" (requestId ${msg.requestId})`
|
|
510
|
-
});
|
|
511
|
-
this.closeWithError(err);
|
|
512
|
-
throw err;
|
|
513
|
-
}
|
|
514
|
-
break;
|
|
515
|
-
}
|
|
516
|
-
case 'remove': {
|
|
517
|
-
const doc = docs.find(doc => doc._id === change.docId);
|
|
518
|
-
if (doc) {
|
|
519
|
-
change.doc = doc;
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
522
|
-
console.error('[realtime listener] internal non-fatal server error: unexpected remove event where no doc is associated.');
|
|
523
|
-
}
|
|
524
|
-
break;
|
|
525
|
-
}
|
|
526
|
-
case 'limit': {
|
|
527
|
-
if (!change.doc) {
|
|
528
|
-
switch (change.queueType) {
|
|
529
|
-
case 'dequeue': {
|
|
530
|
-
const doc = docs.find(doc => doc._id === change.docId);
|
|
531
|
-
if (doc) {
|
|
532
|
-
change.doc = doc;
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
console.error('[realtime listener] internal non-fatal server error: unexpected limit dataType event where no doc is associated.');
|
|
536
|
-
}
|
|
537
|
-
break;
|
|
538
|
-
}
|
|
539
|
-
case 'enqueue': {
|
|
540
|
-
const err = new CloudSDKError({
|
|
541
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_UNEXPECTED_FATAL_ERROR,
|
|
542
|
-
errMsg: `HandleServerEvents: full doc is not provided with dataType="limit" and queueType="enqueue" (requestId ${msg.requestId})`
|
|
543
|
-
});
|
|
544
|
-
this.closeWithError(err);
|
|
545
|
-
throw err;
|
|
546
|
-
}
|
|
547
|
-
default: {
|
|
548
|
-
break;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
break;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
switch (change.queueType) {
|
|
556
|
-
case 'init': {
|
|
557
|
-
if (!initEncountered) {
|
|
558
|
-
initEncountered = true;
|
|
559
|
-
docs = [change.doc];
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
562
|
-
docs.push(change.doc);
|
|
563
|
-
}
|
|
564
|
-
break;
|
|
565
|
-
}
|
|
566
|
-
case 'enqueue': {
|
|
567
|
-
docs.push(change.doc);
|
|
568
|
-
break;
|
|
569
|
-
}
|
|
570
|
-
case 'dequeue': {
|
|
571
|
-
const ind = docs.findIndex(doc => doc._id === change.docId);
|
|
572
|
-
if (ind > -1) {
|
|
573
|
-
docs.splice(ind, 1);
|
|
574
|
-
}
|
|
575
|
-
else {
|
|
576
|
-
console.error('[realtime listener] internal non-fatal server error: unexpected dequeue event where no doc is associated.');
|
|
577
|
-
}
|
|
578
|
-
break;
|
|
579
|
-
}
|
|
580
|
-
case 'update': {
|
|
581
|
-
const ind = docs.findIndex(doc => doc._id === change.docId);
|
|
582
|
-
if (ind > -1) {
|
|
583
|
-
docs[ind] = change.doc;
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
console.error('[realtime listener] internal non-fatal server error: unexpected queueType update event where no doc is associated.');
|
|
587
|
-
}
|
|
588
|
-
break;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
if (i === len - 1 ||
|
|
592
|
-
(allChangeEvents[i + 1] && allChangeEvents[i + 1].id !== change.id)) {
|
|
593
|
-
const docsSnapshot = [...docs];
|
|
594
|
-
const docChanges = allChangeEvents
|
|
595
|
-
.slice(0, i + 1)
|
|
596
|
-
.filter(c => c.id === change.id);
|
|
597
|
-
this.sessionInfo.currentEventId = change.id;
|
|
598
|
-
this.sessionInfo.currentDocs = docs;
|
|
599
|
-
const snapshot = new Snapshot({
|
|
600
|
-
id: change.id,
|
|
601
|
-
docChanges,
|
|
602
|
-
docs: docsSnapshot,
|
|
603
|
-
msgType
|
|
604
|
-
});
|
|
605
|
-
this.listener.onChange(snapshot);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
else {
|
|
609
|
-
console.warn(`[realtime listener] event received is out of order, cur ${this.sessionInfo.currentEventId} but got ${change.id}`);
|
|
610
|
-
await this.rebuildWatch();
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
_postHandleServerEventsValidityCheck(msg) {
|
|
616
|
-
if (!this.sessionInfo) {
|
|
617
|
-
console.error('[realtime listener] internal non-fatal error: sessionInfo lost after server event handling, this should never occur');
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
if (this.sessionInfo.expectEventId &&
|
|
621
|
-
this.sessionInfo.currentEventId >= this.sessionInfo.expectEventId) {
|
|
622
|
-
this.clearWaitExpectedEvent();
|
|
623
|
-
}
|
|
624
|
-
if (this.sessionInfo.currentEventId < msg.msgData.currEvent) {
|
|
625
|
-
console.warn('[realtime listener] internal non-fatal error: client eventId does not match with server event id after server event handling');
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
clearWaitExpectedEvent() {
|
|
630
|
-
if (this._waitExpectedTimeoutId) {
|
|
631
|
-
clearTimeout(this._waitExpectedTimeoutId);
|
|
632
|
-
this._waitExpectedTimeoutId = undefined;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
onMessage(msg) {
|
|
636
|
-
switch (this.watchStatus) {
|
|
637
|
-
case WATCH_STATUS.PAUSED: {
|
|
638
|
-
if (msg.msgType !== 'ERROR') {
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
break;
|
|
642
|
-
}
|
|
643
|
-
case WATCH_STATUS.LOGGINGIN:
|
|
644
|
-
case WATCH_STATUS.INITING:
|
|
645
|
-
case WATCH_STATUS.REBUILDING: {
|
|
646
|
-
console.warn(`[realtime listener] internal non-fatal error: unexpected message received while ${this.watchStatus}`);
|
|
647
|
-
return;
|
|
648
|
-
}
|
|
649
|
-
case WATCH_STATUS.CLOSED: {
|
|
650
|
-
console.warn('[realtime listener] internal non-fatal error: unexpected message received when the watch has closed');
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
case WATCH_STATUS.ERRORED: {
|
|
654
|
-
console.warn('[realtime listener] internal non-fatal error: unexpected message received when the watch has ended with error');
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
if (!this.sessionInfo) {
|
|
659
|
-
console.warn('[realtime listener] internal non-fatal error: sessionInfo not found while message is received.');
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
this.scheduleSendACK();
|
|
663
|
-
switch (msg.msgType) {
|
|
664
|
-
case 'NEXT_EVENT': {
|
|
665
|
-
console.warn(`nextevent ${msg.msgData.currEvent} ignored`, msg);
|
|
666
|
-
this.handleServerEvents(msg);
|
|
667
|
-
break;
|
|
668
|
-
}
|
|
669
|
-
case 'CHECK_EVENT': {
|
|
670
|
-
if (this.sessionInfo.currentEventId < msg.msgData.currEvent) {
|
|
671
|
-
this.sessionInfo.expectEventId = msg.msgData.currEvent;
|
|
672
|
-
this.clearWaitExpectedEvent();
|
|
673
|
-
this._waitExpectedTimeoutId = setTimeout(() => {
|
|
674
|
-
this.rebuildWatch();
|
|
675
|
-
}, this.getWaitExpectedTimeoutLength());
|
|
676
|
-
console.log(`[realtime] waitExpectedTimeoutLength ${this.getWaitExpectedTimeoutLength()}`);
|
|
677
|
-
}
|
|
678
|
-
break;
|
|
679
|
-
}
|
|
680
|
-
case 'ERROR': {
|
|
681
|
-
this.closeWithError(new CloudSDKError({
|
|
682
|
-
errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_SERVER_ERROR_MSG,
|
|
683
|
-
errMsg: `${msg.msgData.code} - ${msg.msgData.message}`
|
|
684
|
-
}));
|
|
685
|
-
break;
|
|
686
|
-
}
|
|
687
|
-
default: {
|
|
688
|
-
console.warn(`[realtime listener] virtual client receive unexpected msg ${msg.msgType}: `, msg);
|
|
689
|
-
break;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
closeWithError(error) {
|
|
694
|
-
this.watchStatus = WATCH_STATUS.ERRORED;
|
|
695
|
-
this.clearACKSchedule();
|
|
696
|
-
this.listener.onError(error);
|
|
697
|
-
this.onWatchClose(this, (this.sessionInfo && this.sessionInfo.queryID) || '');
|
|
698
|
-
console.log(`[realtime] client closed (${this.collectionName} ${this.query}) (watchId ${this.watchId})`);
|
|
699
|
-
}
|
|
700
|
-
pause() {
|
|
701
|
-
this.watchStatus = WATCH_STATUS.PAUSED;
|
|
702
|
-
console.log(`[realtime] client paused (${this.collectionName} ${this.query}) (watchId ${this.watchId})`);
|
|
703
|
-
}
|
|
704
|
-
async resume() {
|
|
705
|
-
this.watchStatus = WATCH_STATUS.RESUMING;
|
|
706
|
-
console.log(`[realtime] client resuming with ${this.sessionInfo ? 'REBUILD_WATCH' : 'INIT_WATCH'} (${this.collectionName} ${this.query}) (${this.watchId})`);
|
|
707
|
-
try {
|
|
708
|
-
await (this.sessionInfo ? this.rebuildWatch() : this.initWatch());
|
|
709
|
-
console.log(`[realtime] client successfully resumed (${this.collectionName} ${this.query}) (${this.watchId})`);
|
|
710
|
-
}
|
|
711
|
-
catch (e) {
|
|
712
|
-
console.error(`[realtime] client resume failed (${this.collectionName} ${this.query}) (${this.watchId})`, e);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
function getPublicEvent(event) {
|
|
717
|
-
const e = {
|
|
718
|
-
id: event.ID,
|
|
719
|
-
dataType: event.DataType,
|
|
720
|
-
queueType: event.QueueType,
|
|
721
|
-
docId: event.DocID,
|
|
722
|
-
doc: event.Doc && event.Doc !== '{}' ? JSON.parse(event.Doc) : undefined
|
|
723
|
-
};
|
|
724
|
-
if (event.DataType === 'update') {
|
|
725
|
-
if (event.UpdatedFields) {
|
|
726
|
-
e.updatedFields = JSON.parse(event.UpdatedFields);
|
|
727
|
-
}
|
|
728
|
-
if (event.removedFields || event.RemovedFields) {
|
|
729
|
-
e.removedFields = JSON.parse(event.removedFields);
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
return e;
|
|
733
|
-
}
|