@yorkie-js/sdk 0.7.7 → 0.7.8
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/README.md +1 -1
- package/dist/yorkie-js-sdk.d.ts +68 -12
- package/dist/yorkie-js-sdk.es.js +205 -37
- package/dist/yorkie-js-sdk.es.js.map +1 -1
- package/dist/yorkie-js-sdk.js +205 -37
- package/dist/yorkie-js-sdk.js.map +1 -1
- package/package.json +5 -5
package/dist/yorkie-js-sdk.js
CHANGED
|
@@ -362,7 +362,7 @@
|
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
364
|
const IMPLICIT$3 = 2;
|
|
365
|
-
const unsafeLocal = Symbol.for("reflect unsafe local");
|
|
365
|
+
const unsafeLocal = /* @__PURE__ */ Symbol.for("reflect unsafe local");
|
|
366
366
|
function unsafeOneofCase(target, oneof) {
|
|
367
367
|
const c = target[oneof.localName].case;
|
|
368
368
|
if (c === void 0) {
|
|
@@ -588,7 +588,7 @@
|
|
|
588
588
|
}
|
|
589
589
|
return ret;
|
|
590
590
|
}
|
|
591
|
-
const tokenZeroMessageField = Symbol();
|
|
591
|
+
const tokenZeroMessageField = /* @__PURE__ */ Symbol();
|
|
592
592
|
const messagePrototypes = /* @__PURE__ */ new WeakMap();
|
|
593
593
|
function createZeroMessage(desc) {
|
|
594
594
|
let msg;
|
|
@@ -690,7 +690,7 @@
|
|
|
690
690
|
function isFieldError(arg) {
|
|
691
691
|
return arg instanceof Error && errorNames.includes(arg.name) && "field" in arg && typeof arg.field == "function";
|
|
692
692
|
}
|
|
693
|
-
const symbol = Symbol.for("@bufbuild/protobuf/text-encoding");
|
|
693
|
+
const symbol = /* @__PURE__ */ Symbol.for("@bufbuild/protobuf/text-encoding");
|
|
694
694
|
function getTextEncoding() {
|
|
695
695
|
if (globalThis[symbol] == void 0) {
|
|
696
696
|
const te = new globalThis.TextEncoder();
|
|
@@ -4058,7 +4058,7 @@
|
|
|
4058
4058
|
msg.set(field, scalarValue);
|
|
4059
4059
|
}
|
|
4060
4060
|
}
|
|
4061
|
-
const tokenIgnoredUnknownEnum = Symbol();
|
|
4061
|
+
const tokenIgnoredUnknownEnum = /* @__PURE__ */ Symbol();
|
|
4062
4062
|
function readEnum(desc, json, ignoreUnknownFields, nullAsZeroValue) {
|
|
4063
4063
|
if (json === null) {
|
|
4064
4064
|
if (desc.typeName == "google.protobuf.NullValue") {
|
|
@@ -4084,7 +4084,7 @@
|
|
|
4084
4084
|
}
|
|
4085
4085
|
throw new Error(`cannot decode ${desc} from JSON: ${formatVal(json)}`);
|
|
4086
4086
|
}
|
|
4087
|
-
const tokenNull = Symbol();
|
|
4087
|
+
const tokenNull = /* @__PURE__ */ Symbol();
|
|
4088
4088
|
function scalarFromJson(field, json, nullAsZeroValue) {
|
|
4089
4089
|
if (json === null) {
|
|
4090
4090
|
if (nullAsZeroValue) {
|
|
@@ -5905,6 +5905,8 @@
|
|
|
5905
5905
|
this.message = message;
|
|
5906
5906
|
this.toString = () => `[code=${this.code}]: ${this.message}`;
|
|
5907
5907
|
}
|
|
5908
|
+
code;
|
|
5909
|
+
message;
|
|
5908
5910
|
name = "YorkieError";
|
|
5909
5911
|
stack;
|
|
5910
5912
|
}
|
|
@@ -12534,8 +12536,10 @@
|
|
|
12534
12536
|
break;
|
|
12535
12537
|
}
|
|
12536
12538
|
if (next.parent && next.parent === toParent) {
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
+
if (toLeft !== toParent) {
|
|
12540
|
+
collectFromLeft = next;
|
|
12541
|
+
collectFromParent = toParent;
|
|
12542
|
+
}
|
|
12539
12543
|
break;
|
|
12540
12544
|
}
|
|
12541
12545
|
current = next;
|
|
@@ -12598,6 +12602,7 @@
|
|
|
12598
12602
|
tokensToBeRemoved,
|
|
12599
12603
|
editedAt
|
|
12600
12604
|
);
|
|
12605
|
+
const mergeLevel = toBeMergedNodes.length;
|
|
12601
12606
|
const pairs = [];
|
|
12602
12607
|
for (const node of nodesToBeRemoved) {
|
|
12603
12608
|
if (node.remove(editedAt)) {
|
|
@@ -12724,7 +12729,15 @@
|
|
|
12724
12729
|
}
|
|
12725
12730
|
}
|
|
12726
12731
|
}
|
|
12727
|
-
return [
|
|
12732
|
+
return [
|
|
12733
|
+
changes,
|
|
12734
|
+
pairs,
|
|
12735
|
+
diff,
|
|
12736
|
+
nodesToBeRemoved,
|
|
12737
|
+
fromIdx,
|
|
12738
|
+
mergeLevel,
|
|
12739
|
+
preTombstoned
|
|
12740
|
+
];
|
|
12728
12741
|
}
|
|
12729
12742
|
/**
|
|
12730
12743
|
* `editT` edits the given range with the given value.
|
|
@@ -13165,11 +13178,35 @@
|
|
|
13165
13178
|
return [prev, prev.isText ? TokenType.Text : TokenType.End];
|
|
13166
13179
|
}
|
|
13167
13180
|
}
|
|
13168
|
-
function
|
|
13169
|
-
|
|
13181
|
+
function cloneAndDropPreTombstoned(node, preTombstoned) {
|
|
13182
|
+
const clone = node.deepcopy();
|
|
13183
|
+
filterChildren(clone, preTombstoned);
|
|
13184
|
+
traverseAll(clone, (n) => {
|
|
13170
13185
|
n.removedAt = void 0;
|
|
13171
|
-
n.
|
|
13186
|
+
if (n.isText) {
|
|
13187
|
+
n.visibleSize = n.value.length;
|
|
13188
|
+
n.totalSize = n.value.length;
|
|
13189
|
+
return;
|
|
13190
|
+
}
|
|
13191
|
+
let size = 0;
|
|
13192
|
+
for (const child of n._children) size += child.paddedSize();
|
|
13193
|
+
n.visibleSize = size;
|
|
13194
|
+
n.totalSize = size;
|
|
13172
13195
|
});
|
|
13196
|
+
return clone;
|
|
13197
|
+
}
|
|
13198
|
+
function filterChildren(node, preTombstoned) {
|
|
13199
|
+
const all = node._children;
|
|
13200
|
+
if (!all) return;
|
|
13201
|
+
const kept = [];
|
|
13202
|
+
for (const child of all) {
|
|
13203
|
+
if (preTombstoned.has(child.id.toIDString())) {
|
|
13204
|
+
continue;
|
|
13205
|
+
}
|
|
13206
|
+
filterChildren(child, preTombstoned);
|
|
13207
|
+
kept.push(child);
|
|
13208
|
+
}
|
|
13209
|
+
node._children = kept;
|
|
13173
13210
|
}
|
|
13174
13211
|
class TreeEditOperation extends Operation {
|
|
13175
13212
|
fromPos;
|
|
@@ -13241,7 +13278,15 @@
|
|
|
13241
13278
|
this.toPos = tree.findPos(this.toIdx);
|
|
13242
13279
|
}
|
|
13243
13280
|
}
|
|
13244
|
-
const [
|
|
13281
|
+
const [
|
|
13282
|
+
changes,
|
|
13283
|
+
pairs,
|
|
13284
|
+
diff,
|
|
13285
|
+
removedNodes,
|
|
13286
|
+
preEditFromIdx,
|
|
13287
|
+
mergeLevel,
|
|
13288
|
+
preTombstoned
|
|
13289
|
+
] = tree.edit(
|
|
13245
13290
|
[this.fromPos, this.toPos],
|
|
13246
13291
|
this.contents?.map((content) => content.deepcopy()),
|
|
13247
13292
|
this.splitLevel,
|
|
@@ -13276,7 +13321,13 @@
|
|
|
13276
13321
|
let reverseOp;
|
|
13277
13322
|
const isPureSplit = this.splitLevel > 0 && !this.contents?.length && removedNodes.length === 0;
|
|
13278
13323
|
if (this.splitLevel === 0) {
|
|
13279
|
-
reverseOp = this.toReverseOperation(
|
|
13324
|
+
reverseOp = this.toReverseOperation(
|
|
13325
|
+
tree,
|
|
13326
|
+
removedNodes,
|
|
13327
|
+
preEditFromIdx,
|
|
13328
|
+
preTombstoned,
|
|
13329
|
+
mergeLevel
|
|
13330
|
+
);
|
|
13280
13331
|
} else if (isPureSplit) {
|
|
13281
13332
|
reverseOp = this.toSplitReverseOperation(tree, preEditFromIdx);
|
|
13282
13333
|
}
|
|
@@ -13314,7 +13365,7 @@
|
|
|
13314
13365
|
* @param removedNodes - Nodes that were removed by this edit
|
|
13315
13366
|
* @param preEditFromIdx - The from index captured BEFORE the edit
|
|
13316
13367
|
*/
|
|
13317
|
-
toReverseOperation(tree, removedNodes, preEditFromIdx) {
|
|
13368
|
+
toReverseOperation(tree, removedNodes, preEditFromIdx, preTombstoned, mergeLevel) {
|
|
13318
13369
|
if (this.redoSplitLevel !== void 0 && this.redoSplitLevel > 0) {
|
|
13319
13370
|
const splitRedoFromPos = tree.findPos(preEditFromIdx);
|
|
13320
13371
|
const splitRedoOp = TreeEditOperation.create(
|
|
@@ -13333,19 +13384,36 @@
|
|
|
13333
13384
|
);
|
|
13334
13385
|
return splitRedoOp;
|
|
13335
13386
|
}
|
|
13387
|
+
if (mergeLevel && mergeLevel > 0) {
|
|
13388
|
+
const splitFromPos = tree.findPos(preEditFromIdx);
|
|
13389
|
+
const splitUndoOp = TreeEditOperation.create(
|
|
13390
|
+
this.getParentCreatedAt(),
|
|
13391
|
+
splitFromPos,
|
|
13392
|
+
splitFromPos,
|
|
13393
|
+
void 0,
|
|
13394
|
+
// no inserted content — split creates boundaries
|
|
13395
|
+
mergeLevel,
|
|
13396
|
+
// splitLevel = number of merged boundaries
|
|
13397
|
+
void 0,
|
|
13398
|
+
// executedAt assigned at undo time
|
|
13399
|
+
true,
|
|
13400
|
+
// isUndoOp
|
|
13401
|
+
preEditFromIdx,
|
|
13402
|
+
preEditFromIdx
|
|
13403
|
+
);
|
|
13404
|
+
return splitUndoOp;
|
|
13405
|
+
}
|
|
13336
13406
|
const insertedContentSize = this.contents ? this.contents.reduce((sum, node) => sum + node.paddedSize(), 0) : 0;
|
|
13337
13407
|
const maxNeededIdx = preEditFromIdx + insertedContentSize;
|
|
13338
13408
|
if (maxNeededIdx > tree.getSize()) {
|
|
13339
13409
|
return void 0;
|
|
13340
13410
|
}
|
|
13341
13411
|
const topLevelRemoved = removedNodes.filter(
|
|
13342
|
-
(node) => !node.parent || !removedNodes.includes(node.parent)
|
|
13412
|
+
(node) => !preTombstoned.has(node.id.toIDString()) && (!node.parent || !removedNodes.includes(node.parent))
|
|
13343
13413
|
);
|
|
13344
|
-
const reverseContents = topLevelRemoved.length > 0 ? topLevelRemoved.map(
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
return clone;
|
|
13348
|
-
}) : void 0;
|
|
13414
|
+
const reverseContents = topLevelRemoved.length > 0 ? topLevelRemoved.map(
|
|
13415
|
+
(n) => cloneAndDropPreTombstoned(n, preTombstoned)
|
|
13416
|
+
) : void 0;
|
|
13349
13417
|
const reverseFromPos = tree.findPos(preEditFromIdx);
|
|
13350
13418
|
let reverseToPos;
|
|
13351
13419
|
if (insertedContentSize > 0) {
|
|
@@ -20164,6 +20232,11 @@
|
|
|
20164
20232
|
}
|
|
20165
20233
|
]);
|
|
20166
20234
|
}
|
|
20235
|
+
/**
|
|
20236
|
+
* `clearHistory` flushes both undo and redo stacks. This is used
|
|
20237
|
+
* after applying a snapshot or initialRoot so that setup operations
|
|
20238
|
+
* are not reachable via undo.
|
|
20239
|
+
*/
|
|
20167
20240
|
clearHistory() {
|
|
20168
20241
|
this.internalHistory.clearRedo();
|
|
20169
20242
|
this.internalHistory.clearUndo();
|
|
@@ -20623,10 +20696,7 @@
|
|
|
20623
20696
|
}
|
|
20624
20697
|
const ops = isUndo ? this.internalHistory.popUndo() : this.internalHistory.popRedo();
|
|
20625
20698
|
if (!ops) {
|
|
20626
|
-
|
|
20627
|
-
Code.ErrRefused,
|
|
20628
|
-
`There is no operation to be ${isUndo ? "undone" : "redone"}`
|
|
20629
|
-
);
|
|
20699
|
+
return;
|
|
20630
20700
|
}
|
|
20631
20701
|
this.ensureClone();
|
|
20632
20702
|
const ctx = ChangeContext.create(
|
|
@@ -20719,6 +20789,8 @@
|
|
|
20719
20789
|
syncMode;
|
|
20720
20790
|
changeEventReceived;
|
|
20721
20791
|
lastHeartbeatTime;
|
|
20792
|
+
pollInterval;
|
|
20793
|
+
pollIntervalPinned;
|
|
20722
20794
|
reconnectStreamDelay;
|
|
20723
20795
|
cancelled;
|
|
20724
20796
|
watchStream;
|
|
@@ -20726,13 +20798,15 @@
|
|
|
20726
20798
|
watchAbortController;
|
|
20727
20799
|
syncPromise;
|
|
20728
20800
|
_detaching = false;
|
|
20729
|
-
constructor(reconnectStreamDelay, resource, resourceID, syncMode) {
|
|
20801
|
+
constructor(reconnectStreamDelay, resource, resourceID, syncMode, pollInterval = 0, pollIntervalPinned = false) {
|
|
20730
20802
|
this.reconnectStreamDelay = reconnectStreamDelay;
|
|
20731
20803
|
this.resource = resource;
|
|
20732
20804
|
this.resourceID = resourceID;
|
|
20733
20805
|
this.syncMode = syncMode;
|
|
20734
20806
|
this.changeEventReceived = syncMode !== void 0 ? false : void 0;
|
|
20735
20807
|
this.lastHeartbeatTime = Date.now();
|
|
20808
|
+
this.pollInterval = pollInterval;
|
|
20809
|
+
this.pollIntervalPinned = pollIntervalPinned;
|
|
20736
20810
|
this.cancelled = false;
|
|
20737
20811
|
}
|
|
20738
20812
|
/**
|
|
@@ -20752,6 +20826,9 @@
|
|
|
20752
20826
|
if (this.syncMode === SyncMode.RealtimePushOnly) {
|
|
20753
20827
|
return this.resource.hasLocalChanges();
|
|
20754
20828
|
}
|
|
20829
|
+
if (this.syncMode === SyncMode.Polling) {
|
|
20830
|
+
return Date.now() - this.lastHeartbeatTime >= this.pollInterval;
|
|
20831
|
+
}
|
|
20755
20832
|
return this.syncMode !== SyncMode.Manual && (this.resource.hasLocalChanges() || (this.changeEventReceived ?? false));
|
|
20756
20833
|
}
|
|
20757
20834
|
/**
|
|
@@ -20765,7 +20842,8 @@
|
|
|
20765
20842
|
if (this.syncMode === SyncMode.Manual) {
|
|
20766
20843
|
return false;
|
|
20767
20844
|
}
|
|
20768
|
-
|
|
20845
|
+
const interval = this.pollInterval > 0 ? this.pollInterval : heartbeatInterval;
|
|
20846
|
+
return Date.now() - this.lastHeartbeatTime >= interval;
|
|
20769
20847
|
}
|
|
20770
20848
|
/**
|
|
20771
20849
|
* `updateHeartbeatTime` updates the last heartbeat time.
|
|
@@ -20844,6 +20922,16 @@
|
|
|
20844
20922
|
}
|
|
20845
20923
|
}
|
|
20846
20924
|
}
|
|
20925
|
+
/**
|
|
20926
|
+
* `resetCancelled` clears the cancelled flag so the watch loop can run again
|
|
20927
|
+
* after a previous cancellation (e.g., after changeSyncMode back to Realtime).
|
|
20928
|
+
* Caller must invoke `runWatchLoop` immediately after to claim the stream slot;
|
|
20929
|
+
* `doLoop`'s `if (this.watchStream)` guard prevents double-stream creation if a
|
|
20930
|
+
* delayed `onDisconnect` callback from the previously-cancelled stream races.
|
|
20931
|
+
*/
|
|
20932
|
+
resetCancelled() {
|
|
20933
|
+
this.cancelled = false;
|
|
20934
|
+
}
|
|
20847
20935
|
/**
|
|
20848
20936
|
* `cancelWatchStream` cancels the watch stream.
|
|
20849
20937
|
*/
|
|
@@ -20878,7 +20966,7 @@
|
|
|
20878
20966
|
};
|
|
20879
20967
|
}
|
|
20880
20968
|
const name = "@yorkie-js/sdk";
|
|
20881
|
-
const version = "0.7.
|
|
20969
|
+
const version = "0.7.8";
|
|
20882
20970
|
const pkg = {
|
|
20883
20971
|
name,
|
|
20884
20972
|
version
|
|
@@ -21161,6 +21249,7 @@
|
|
|
21161
21249
|
SyncMode2["Realtime"] = "realtime";
|
|
21162
21250
|
SyncMode2["RealtimePushOnly"] = "realtime-pushonly";
|
|
21163
21251
|
SyncMode2["RealtimeSyncOff"] = "realtime-syncoff";
|
|
21252
|
+
SyncMode2["Polling"] = "polling";
|
|
21164
21253
|
return SyncMode2;
|
|
21165
21254
|
})(SyncMode || {});
|
|
21166
21255
|
var ClientStatus = /* @__PURE__ */ ((ClientStatus2) => {
|
|
@@ -21173,6 +21262,7 @@
|
|
|
21173
21262
|
ClientCondition2["WatchLoop"] = "WatchLoop";
|
|
21174
21263
|
return ClientCondition2;
|
|
21175
21264
|
})(ClientCondition || {});
|
|
21265
|
+
const DefaultPollingIntervalMs = 3e3;
|
|
21176
21266
|
const DefaultClientOptions = {
|
|
21177
21267
|
rpcAddr: "https://api.yorkie.dev",
|
|
21178
21268
|
syncLoopDuration: 50,
|
|
@@ -21368,6 +21458,14 @@
|
|
|
21368
21458
|
doc.setActor(this.id);
|
|
21369
21459
|
doc.update((_, p) => p.set(opts.initialPresence || {}));
|
|
21370
21460
|
const syncMode = opts.syncMode ?? "realtime";
|
|
21461
|
+
if (opts.documentPollInterval !== void 0 && opts.documentPollInterval <= 0) {
|
|
21462
|
+
throw new YorkieError(
|
|
21463
|
+
Code.ErrInvalidArgument,
|
|
21464
|
+
"documentPollInterval must be greater than 0"
|
|
21465
|
+
);
|
|
21466
|
+
}
|
|
21467
|
+
const pollIntervalPinned = opts.documentPollInterval !== void 0;
|
|
21468
|
+
const pollInterval = pollIntervalPinned ? opts.documentPollInterval : syncMode === "polling" ? DefaultPollingIntervalMs : 0;
|
|
21371
21469
|
return this.enqueueTask(async () => {
|
|
21372
21470
|
try {
|
|
21373
21471
|
const res = await this.rpcClient.attachDocument(
|
|
@@ -21397,10 +21495,12 @@
|
|
|
21397
21495
|
this.reconnectStreamDelay,
|
|
21398
21496
|
doc,
|
|
21399
21497
|
res.documentId,
|
|
21400
|
-
syncMode
|
|
21498
|
+
syncMode,
|
|
21499
|
+
pollInterval,
|
|
21500
|
+
pollIntervalPinned
|
|
21401
21501
|
)
|
|
21402
21502
|
);
|
|
21403
|
-
if (syncMode !== "manual") {
|
|
21503
|
+
if (syncMode !== "manual" && syncMode !== "polling") {
|
|
21404
21504
|
await this.runWatchLoop(doc.getKey());
|
|
21405
21505
|
}
|
|
21406
21506
|
logger.info(`[AD] c:"${this.getKey()}" attaches d:"${doc.getKey()}"`);
|
|
@@ -21416,6 +21516,7 @@
|
|
|
21416
21516
|
}
|
|
21417
21517
|
});
|
|
21418
21518
|
}
|
|
21519
|
+
doc.clearHistory();
|
|
21419
21520
|
return doc;
|
|
21420
21521
|
} catch (err) {
|
|
21421
21522
|
logger.error(`[AD] c:"${this.getKey()}" err :`, err);
|
|
@@ -21526,12 +21627,23 @@
|
|
|
21526
21627
|
channel.setSessionID(res.sessionId);
|
|
21527
21628
|
channel.updateSessionCount(Number(res.sessionCount), 0);
|
|
21528
21629
|
channel.applyStatus(ChannelStatus.Attached);
|
|
21529
|
-
const syncMode = opts.
|
|
21630
|
+
const syncMode = opts.syncMode ?? "realtime";
|
|
21631
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21632
|
+
if (opts.channelHeartbeatInterval !== void 0 && opts.channelHeartbeatInterval <= 0) {
|
|
21633
|
+
throw new YorkieError(
|
|
21634
|
+
Code.ErrInvalidArgument,
|
|
21635
|
+
"channelHeartbeatInterval must be greater than 0"
|
|
21636
|
+
);
|
|
21637
|
+
}
|
|
21638
|
+
const pollIntervalPinned = opts.channelHeartbeatInterval !== void 0;
|
|
21639
|
+
const pollInterval = pollIntervalPinned ? opts.channelHeartbeatInterval : syncMode === "polling" ? DefaultPollingIntervalMs : this.channelHeartbeatInterval;
|
|
21530
21640
|
const attachment = new Attachment(
|
|
21531
21641
|
this.reconnectStreamDelay,
|
|
21532
21642
|
channel,
|
|
21533
21643
|
res.sessionId,
|
|
21534
|
-
syncMode
|
|
21644
|
+
syncMode,
|
|
21645
|
+
pollInterval,
|
|
21646
|
+
pollIntervalPinned
|
|
21535
21647
|
);
|
|
21536
21648
|
channel.subscribe("local-broadcast", (event) => {
|
|
21537
21649
|
const { topic, payload, options } = event;
|
|
@@ -21607,9 +21719,17 @@
|
|
|
21607
21719
|
return this.enqueueTask(task);
|
|
21608
21720
|
}
|
|
21609
21721
|
/**
|
|
21610
|
-
* `changeSyncMode` changes the synchronization mode of the given
|
|
21722
|
+
* `changeSyncMode` changes the synchronization mode of the given resource.
|
|
21611
21723
|
*/
|
|
21612
|
-
async changeSyncMode(
|
|
21724
|
+
async changeSyncMode(resource, syncMode) {
|
|
21725
|
+
return this.enqueueTask(async () => {
|
|
21726
|
+
if (resource instanceof Channel) {
|
|
21727
|
+
return this.changeChannelSyncMode(resource, syncMode);
|
|
21728
|
+
}
|
|
21729
|
+
return this.changeDocumentSyncMode(resource, syncMode);
|
|
21730
|
+
});
|
|
21731
|
+
}
|
|
21732
|
+
async changeDocumentSyncMode(doc, syncMode) {
|
|
21613
21733
|
if (!this.isActive()) {
|
|
21614
21734
|
throw new YorkieError(
|
|
21615
21735
|
Code.ErrClientNotActivated,
|
|
@@ -21627,19 +21747,66 @@
|
|
|
21627
21747
|
if (prevSyncMode === syncMode) {
|
|
21628
21748
|
return doc;
|
|
21629
21749
|
}
|
|
21630
|
-
|
|
21631
|
-
if (syncMode === "manual") {
|
|
21750
|
+
if (syncMode === "manual" || syncMode === "polling") {
|
|
21632
21751
|
attachment.cancelWatchStream();
|
|
21633
|
-
return doc;
|
|
21634
21752
|
}
|
|
21753
|
+
attachment.changeSyncMode(syncMode);
|
|
21635
21754
|
if (syncMode === "realtime") {
|
|
21636
21755
|
attachment.changeEventReceived = true;
|
|
21637
21756
|
}
|
|
21638
|
-
if (
|
|
21757
|
+
if (!attachment.pollIntervalPinned) {
|
|
21758
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultPollingIntervalMs : 0;
|
|
21759
|
+
}
|
|
21760
|
+
if ((prevSyncMode === "manual" || prevSyncMode === "polling") && syncMode !== "manual" && syncMode !== "polling") {
|
|
21761
|
+
attachment.resetCancelled();
|
|
21639
21762
|
await this.runWatchLoop(doc.getKey());
|
|
21640
21763
|
}
|
|
21641
21764
|
return doc;
|
|
21642
21765
|
}
|
|
21766
|
+
/**
|
|
21767
|
+
* `assertValidChannelSyncMode` rejects sync modes that are not valid for
|
|
21768
|
+
* channels. `RealtimePushOnly` and `RealtimeSyncOff` are document-only.
|
|
21769
|
+
*/
|
|
21770
|
+
assertValidChannelSyncMode(syncMode) {
|
|
21771
|
+
if (syncMode !== "manual" && syncMode !== "realtime" && syncMode !== "polling") {
|
|
21772
|
+
throw new YorkieError(
|
|
21773
|
+
Code.ErrInvalidArgument,
|
|
21774
|
+
`invalid channel sync mode: ${syncMode}`
|
|
21775
|
+
);
|
|
21776
|
+
}
|
|
21777
|
+
}
|
|
21778
|
+
async changeChannelSyncMode(channel, syncMode) {
|
|
21779
|
+
if (!this.isActive()) {
|
|
21780
|
+
throw new YorkieError(
|
|
21781
|
+
Code.ErrClientNotActivated,
|
|
21782
|
+
`${this.key} is not active`
|
|
21783
|
+
);
|
|
21784
|
+
}
|
|
21785
|
+
const attachment = this.attachmentMap.get(channel.getKey());
|
|
21786
|
+
if (!attachment) {
|
|
21787
|
+
throw new YorkieError(
|
|
21788
|
+
Code.ErrNotAttached,
|
|
21789
|
+
`${channel.getKey()} is not attached`
|
|
21790
|
+
);
|
|
21791
|
+
}
|
|
21792
|
+
const prevSyncMode = attachment.syncMode;
|
|
21793
|
+
if (prevSyncMode === syncMode) {
|
|
21794
|
+
return channel;
|
|
21795
|
+
}
|
|
21796
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21797
|
+
if (prevSyncMode === "realtime") {
|
|
21798
|
+
attachment.cancelWatchStream();
|
|
21799
|
+
}
|
|
21800
|
+
attachment.changeSyncMode(syncMode);
|
|
21801
|
+
if (!attachment.pollIntervalPinned) {
|
|
21802
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultPollingIntervalMs : syncMode === "realtime" ? this.channelHeartbeatInterval : 0;
|
|
21803
|
+
}
|
|
21804
|
+
if (syncMode === "realtime") {
|
|
21805
|
+
attachment.resetCancelled();
|
|
21806
|
+
await this.runWatchLoop(channel.getKey());
|
|
21807
|
+
}
|
|
21808
|
+
return channel;
|
|
21809
|
+
}
|
|
21643
21810
|
/**
|
|
21644
21811
|
* `sync` implementation that handles both Document and Channel.
|
|
21645
21812
|
*/
|
|
@@ -22484,6 +22651,7 @@
|
|
|
22484
22651
|
return doc;
|
|
22485
22652
|
}
|
|
22486
22653
|
doc.applyChangePack(respPack);
|
|
22654
|
+
attachment.updateHeartbeatTime();
|
|
22487
22655
|
attachment.resource.publish([
|
|
22488
22656
|
{
|
|
22489
22657
|
type: DocEventType.SyncStatusChanged,
|