@yorkie-js/sdk 0.7.9 → 0.7.10-rc
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/yorkie-js-sdk.d.ts +58 -16
- package/dist/yorkie-js-sdk.es.js +147 -124
- package/dist/yorkie-js-sdk.es.js.map +1 -1
- package/dist/yorkie-js-sdk.js +147 -124
- package/dist/yorkie-js-sdk.js.map +1 -1
- package/package.json +2 -2
package/dist/yorkie-js-sdk.d.ts
CHANGED
|
@@ -106,9 +106,10 @@ export declare interface AttachChannelOptions {
|
|
|
106
106
|
*/
|
|
107
107
|
syncMode?: SyncMode;
|
|
108
108
|
/**
|
|
109
|
-
* `channelHeartbeatInterval` overrides the heartbeat interval (ms) for
|
|
110
|
-
* attachment. If unset,
|
|
111
|
-
*
|
|
109
|
+
* `channelHeartbeatInterval` overrides the heartbeat interval (ms) for
|
|
110
|
+
* this attachment. If unset, the client-level default
|
|
111
|
+
* (`ClientOptions.channelHeartbeatInterval`, default 5000 ms) applies
|
|
112
|
+
* to both Realtime and Polling modes.
|
|
112
113
|
*/
|
|
113
114
|
channelHeartbeatInterval?: number;
|
|
114
115
|
}
|
|
@@ -801,6 +802,12 @@ export declare class Channel implements Observable_2<ChannelEvent>, Attachable {
|
|
|
801
802
|
* The callback will be called when an authentication error occurs.
|
|
802
803
|
*/
|
|
803
804
|
subscribe(type: 'auth-error', next: ChannelEventCallbackMap['auth-error']): Unsubscribe;
|
|
805
|
+
/**
|
|
806
|
+
* `subscribe` registers a callback to subscribe to non-recoverable sync
|
|
807
|
+
* (RefreshChannel) errors. Subsequent successful events on the channel
|
|
808
|
+
* imply recovery — there is no separate "recovered" event.
|
|
809
|
+
*/
|
|
810
|
+
subscribe(type: 'sync-error', next: ChannelEventCallbackMap['sync-error']): Unsubscribe;
|
|
804
811
|
/**
|
|
805
812
|
* `subscribe` registers a callback to subscribe to presence events on the channel.
|
|
806
813
|
* The callback will be called when the presence count changes.
|
|
@@ -834,7 +841,7 @@ export declare class Channel implements Observable_2<ChannelEvent>, Attachable {
|
|
|
834
841
|
/**
|
|
835
842
|
* `ChannelEvent` represents an event that occurs in the channel.
|
|
836
843
|
*/
|
|
837
|
-
export declare type ChannelEvent = PresenceEvent_3 | BroadcastEvent | LocalBroadcastEvent | AuthErrorEvent_3;
|
|
844
|
+
export declare type ChannelEvent = PresenceEvent_3 | BroadcastEvent | LocalBroadcastEvent | AuthErrorEvent_3 | SyncErrorEvent;
|
|
838
845
|
|
|
839
846
|
/**
|
|
840
847
|
* `ChannelEventCallbackMap` represents a map of event types to callbacks.
|
|
@@ -843,6 +850,7 @@ declare type ChannelEventCallbackMap = {
|
|
|
843
850
|
broadcast: NextFn<BroadcastEvent>;
|
|
844
851
|
'local-broadcast': NextFn<LocalBroadcastEvent>;
|
|
845
852
|
'auth-error': NextFn<AuthErrorEvent_3>;
|
|
853
|
+
'sync-error': NextFn<SyncErrorEvent>;
|
|
846
854
|
presence: NextFn<PresenceEvent_3>;
|
|
847
855
|
all: NextFn<ChannelEvent>;
|
|
848
856
|
};
|
|
@@ -870,7 +878,15 @@ export declare enum ChannelEventType {
|
|
|
870
878
|
/**
|
|
871
879
|
* `AuthError` means that an authentication error has occurred.
|
|
872
880
|
*/
|
|
873
|
-
AuthError = "auth-error"
|
|
881
|
+
AuthError = "auth-error",
|
|
882
|
+
/**
|
|
883
|
+
* `SyncError` means that a non-recoverable sync (RefreshChannel) error
|
|
884
|
+
* occurred. Subscribers can use this to render an error state in the UI
|
|
885
|
+
* without polling internal SDK state. The SDK still retries via its sync
|
|
886
|
+
* loop, so subsequent successful events (PresenceChanged/Initialized) can
|
|
887
|
+
* be treated as recovery.
|
|
888
|
+
*/
|
|
889
|
+
SyncError = "sync-error"
|
|
874
890
|
}
|
|
875
891
|
|
|
876
892
|
/**
|
|
@@ -1010,8 +1026,9 @@ export declare class Client {
|
|
|
1010
1026
|
*/
|
|
1011
1027
|
attach<R, P extends Indexable>(resource: Document_2<R, P>, opts?: AttachOptions<R, P>): Promise<Document_2<R, P>>;
|
|
1012
1028
|
/**
|
|
1013
|
-
* `attach` attaches the given channel to this client.
|
|
1014
|
-
*
|
|
1029
|
+
* `attach` attaches the given channel to this client. The channel is
|
|
1030
|
+
* registered locally and the server is notified on the next RefreshChannel
|
|
1031
|
+
* heartbeat.
|
|
1015
1032
|
*/
|
|
1016
1033
|
attach(resource: Channel, opts?: AttachChannelOptions): Promise<Channel>;
|
|
1017
1034
|
/**
|
|
@@ -1027,8 +1044,9 @@ export declare class Client {
|
|
|
1027
1044
|
keepalive?: boolean;
|
|
1028
1045
|
}): Promise<Document_2<R, P>>;
|
|
1029
1046
|
/**
|
|
1030
|
-
* `detach` detaches the given channel from this client.
|
|
1031
|
-
*
|
|
1047
|
+
* `detach` detaches the given channel from this client. The detach is a
|
|
1048
|
+
* local cleanup; the server reclaims the session via TTL when heartbeats
|
|
1049
|
+
* stop.
|
|
1032
1050
|
*/
|
|
1033
1051
|
detach(resource: Channel): Promise<Channel>;
|
|
1034
1052
|
/**
|
|
@@ -1041,13 +1059,15 @@ export declare class Client {
|
|
|
1041
1059
|
*/
|
|
1042
1060
|
private detachDocument;
|
|
1043
1061
|
/**
|
|
1044
|
-
* `
|
|
1045
|
-
*
|
|
1062
|
+
* `attachChannel` attaches the given channel to this client. The channel is
|
|
1063
|
+
* registered locally and the server is notified on the next RefreshChannel
|
|
1064
|
+
* heartbeat.
|
|
1046
1065
|
*/
|
|
1047
1066
|
attachChannel(channel: Channel, opts?: AttachChannelOptions): Promise<Channel>;
|
|
1048
1067
|
/**
|
|
1049
|
-
* `detachChannel` detaches the given channel from this client.
|
|
1050
|
-
*
|
|
1068
|
+
* `detachChannel` detaches the given channel from this client. The detach
|
|
1069
|
+
* is a local cleanup; the server reclaims the session via TTL when
|
|
1070
|
+
* heartbeats stop.
|
|
1051
1071
|
*/
|
|
1052
1072
|
detachChannel(channel: Channel): Promise<Channel>;
|
|
1053
1073
|
/**
|
|
@@ -1241,9 +1261,11 @@ export declare interface ClientOptions {
|
|
|
1241
1261
|
*/
|
|
1242
1262
|
reconnectStreamDelay?: number;
|
|
1243
1263
|
/**
|
|
1244
|
-
* `channelHeartbeatInterval` is the interval of the channel heartbeat.
|
|
1245
|
-
* The client sends a heartbeat to
|
|
1246
|
-
* The default value is `
|
|
1264
|
+
* `channelHeartbeatInterval` is the interval of the channel heartbeat (ms).
|
|
1265
|
+
* The client sends a `RefreshChannel` heartbeat to refresh the channel
|
|
1266
|
+
* session TTL. The default value is `5000` (ms) — co-tuned to the server's
|
|
1267
|
+
* `ChannelSessionTTL` (15 s) at TTL/3. Values larger than the server TTL
|
|
1268
|
+
* risk premature session expiry.
|
|
1247
1269
|
*/
|
|
1248
1270
|
channelHeartbeatInterval?: number;
|
|
1249
1271
|
/**
|
|
@@ -6062,6 +6084,26 @@ declare interface SubscribeFn<T> {
|
|
|
6062
6084
|
(observer: Observer<T>): Unsubscribe;
|
|
6063
6085
|
}
|
|
6064
6086
|
|
|
6087
|
+
/**
|
|
6088
|
+
* `SyncErrorEvent` represents a non-recoverable sync (RefreshChannel) error.
|
|
6089
|
+
* It carries the underlying error object so subscribers can inspect codes
|
|
6090
|
+
* (e.g. via `isErrorCode`) without losing the original Error.
|
|
6091
|
+
*/
|
|
6092
|
+
declare interface SyncErrorEvent {
|
|
6093
|
+
/**
|
|
6094
|
+
* `type` is the type of the event.
|
|
6095
|
+
*/
|
|
6096
|
+
type: ChannelEventType.SyncError;
|
|
6097
|
+
/**
|
|
6098
|
+
* `error` is the underlying error thrown by the RPC call.
|
|
6099
|
+
*/
|
|
6100
|
+
error: unknown;
|
|
6101
|
+
/**
|
|
6102
|
+
* `method` is the RPC method that failed (e.g. `RefreshChannel`).
|
|
6103
|
+
*/
|
|
6104
|
+
method: string;
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6065
6107
|
/**
|
|
6066
6108
|
* `SyncMode` defines synchronization modes for the PushPullChanges API
|
|
6067
6109
|
* (documents) and the RefreshChannel heartbeat (channels).
|
package/dist/yorkie-js-sdk.es.js
CHANGED
|
@@ -5865,7 +5865,7 @@ var DocEventType$1 = /* @__PURE__ */ ((DocEventType2) => {
|
|
|
5865
5865
|
DocEventType2[DocEventType2["DOCUMENT_BROADCAST"] = 3] = "DOCUMENT_BROADCAST";
|
|
5866
5866
|
return DocEventType2;
|
|
5867
5867
|
})(DocEventType$1 || {});
|
|
5868
|
-
const file_yorkie_v1_yorkie = /* @__PURE__ */ fileDesc("
|
|
5868
|
+
const file_yorkie_v1_yorkie = /* @__PURE__ */ fileDesc("ChZ5b3JraWUvdjEveW9ya2llLnByb3RvEgl5b3JraWUudjEingEKFUFjdGl2YXRlQ2xpZW50UmVxdWVzdBISCgpjbGllbnRfa2V5GAEgASgJEkAKCG1ldGFkYXRhGAIgAygLMi4ueW9ya2llLnYxLkFjdGl2YXRlQ2xpZW50UmVxdWVzdC5NZXRhZGF0YUVudHJ5Gi8KDU1ldGFkYXRhRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASIrChZBY3RpdmF0ZUNsaWVudFJlc3BvbnNlEhEKCWNsaWVudF9pZBgBIAEoCSJBChdEZWFjdGl2YXRlQ2xpZW50UmVxdWVzdBIRCgljbGllbnRfaWQYASABKAkSEwoLc3luY2hyb25vdXMYAiABKAgiGgoYRGVhY3RpdmF0ZUNsaWVudFJlc3BvbnNlImoKFUF0dGFjaERvY3VtZW50UmVxdWVzdBIRCgljbGllbnRfaWQYASABKAkSKgoLY2hhbmdlX3BhY2sYAiABKAsyFS55b3JraWUudjEuQ2hhbmdlUGFjaxISCgpzY2hlbWFfa2V5GAMgASgJIp8BChZBdHRhY2hEb2N1bWVudFJlc3BvbnNlEhMKC2RvY3VtZW50X2lkGAEgASgJEioKC2NoYW5nZV9wYWNrGAIgASgLMhUueW9ya2llLnYxLkNoYW5nZVBhY2sSHQoVbWF4X3NpemVfcGVyX2RvY3VtZW50GAMgASgFEiUKDHNjaGVtYV9ydWxlcxgEIAMoCzIPLnlvcmtpZS52MS5SdWxlIosBChVEZXRhY2hEb2N1bWVudFJlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2RvY3VtZW50X2lkGAIgASgJEioKC2NoYW5nZV9wYWNrGAMgASgLMhUueW9ya2llLnYxLkNoYW5nZVBhY2sSHgoWcmVtb3ZlX2lmX25vdF9hdHRhY2hlZBgEIAEoCCJEChZEZXRhY2hEb2N1bWVudFJlc3BvbnNlEioKC2NoYW5nZV9wYWNrGAIgASgLMhUueW9ya2llLnYxLkNoYW5nZVBhY2siUwoMV2F0Y2hSZXF1ZXN0EhEKCWNsaWVudF9pZBgBIAEoCRIwCglyZXNvdXJjZXMYAiADKAsyHS55b3JraWUudjEuUmVzb3VyY2VEZXNjcmlwdG9yIoQBChJSZXNvdXJjZURlc2NyaXB0b3ISMQoIZG9jdW1lbnQYASABKAsyHS55b3JraWUudjEuRG9jdW1lbnREZXNjcmlwdG9ySAASLwoHY2hhbm5lbBgCIAEoCzIcLnlvcmtpZS52MS5DaGFubmVsRGVzY3JpcHRvckgAQgoKCHJlc291cmNlIikKEkRvY3VtZW50RGVzY3JpcHRvchITCgtkb2N1bWVudF9pZBgBIAEoCSIoChFDaGFubmVsRGVzY3JpcHRvchITCgtjaGFubmVsX2tleRgBIAEoCSJ5Cg1XYXRjaFJlc3BvbnNlEjgKDmluaXRpYWxpemF0aW9uGAEgASgLMh4ueW9ya2llLnYxLldhdGNoSW5pdGlhbGl6YXRpb25IABImCgVldmVudBgCIAEoCzIVLnlvcmtpZS52MS5XYXRjaEV2ZW50SABCBgoEYm9keSJGChNXYXRjaEluaXRpYWxpemF0aW9uEi8KDnJlc291cmNlX2luaXRzGAEgAygLMhcueW9ya2llLnYxLlJlc291cmNlSW5pdCJ4CgxSZXNvdXJjZUluaXQSMAoNZG9jdW1lbnRfaW5pdBgBIAEoCzIXLnlvcmtpZS52MS5Eb2N1bWVudEluaXRIABIuCgxjaGFubmVsX2luaXQYAiABKAsyFi55b3JraWUudjEuQ2hhbm5lbEluaXRIAEIGCgRpbml0IjcKDERvY3VtZW50SW5pdBITCgtkb2N1bWVudF9pZBgBIAEoCRISCgpjbGllbnRfaWRzGAIgAygJIkYKC0NoYW5uZWxJbml0EhMKC2NoYW5uZWxfa2V5GAEgASgJEhUKDXNlc3Npb25fY291bnQYAiABKAMSCwoDc2VxGAMgASgDInsKCldhdGNoRXZlbnQSLQoJZG9jX2V2ZW50GAEgASgLMhgueW9ya2llLnYxLkRvY1dhdGNoRXZlbnRIABI1Cg1jaGFubmVsX2V2ZW50GAIgASgLMhwueW9ya2llLnYxLkNoYW5uZWxXYXRjaEV2ZW50SABCBwoFZXZlbnQiSAoNRG9jV2F0Y2hFdmVudBITCgtkb2N1bWVudF9pZBgBIAEoCRIiCgVldmVudBgCIAEoCzITLnlvcmtpZS52MS5Eb2NFdmVudCJQChFDaGFubmVsV2F0Y2hFdmVudBITCgtjaGFubmVsX2tleRgBIAEoCRImCgVldmVudBgCIAEoCzIXLnlvcmtpZS52MS5DaGFubmVsRXZlbnQiPgoUV2F0Y2hEb2N1bWVudFJlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2RvY3VtZW50X2lkGAIgASgJIrYBChVXYXRjaERvY3VtZW50UmVzcG9uc2USSQoOaW5pdGlhbGl6YXRpb24YASABKAsyLy55b3JraWUudjEuV2F0Y2hEb2N1bWVudFJlc3BvbnNlLkluaXRpYWxpemF0aW9uSAASJAoFZXZlbnQYAiABKAsyEy55b3JraWUudjEuRG9jRXZlbnRIABokCg5Jbml0aWFsaXphdGlvbhISCgpjbGllbnRfaWRzGAEgAygJQgYKBGJvZHkiPQoTV2F0Y2hDaGFubmVsUmVxdWVzdBIRCgljbGllbnRfaWQYASABKAkSEwoLY2hhbm5lbF9rZXkYAiABKAkigwEKFFdhdGNoQ2hhbm5lbFJlc3BvbnNlEjkKC2luaXRpYWxpemVkGAEgASgLMiIueW9ya2llLnYxLldhdGNoQ2hhbm5lbEluaXRpYWxpemVkSAASKAoFZXZlbnQYAiABKAsyFy55b3JraWUudjEuQ2hhbm5lbEV2ZW50SABCBgoEYm9keSI9ChdXYXRjaENoYW5uZWxJbml0aWFsaXplZBIVCg1zZXNzaW9uX2NvdW50GAEgASgDEgsKA3NlcRgCIAEoAyJrChVSZW1vdmVEb2N1bWVudFJlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2RvY3VtZW50X2lkGAIgASgJEioKC2NoYW5nZV9wYWNrGAMgASgLMhUueW9ya2llLnYxLkNoYW5nZVBhY2siRAoWUmVtb3ZlRG9jdW1lbnRSZXNwb25zZRIqCgtjaGFuZ2VfcGFjaxgBIAEoCzIVLnlvcmtpZS52MS5DaGFuZ2VQYWNrIn8KFlB1c2hQdWxsQ2hhbmdlc1JlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2RvY3VtZW50X2lkGAIgASgJEioKC2NoYW5nZV9wYWNrGAMgASgLMhUueW9ya2llLnYxLkNoYW5nZVBhY2sSEQoJcHVzaF9vbmx5GAQgASgIIkUKF1B1c2hQdWxsQ2hhbmdlc1Jlc3BvbnNlEioKC2NoYW5nZV9wYWNrGAEgASgLMhUueW9ya2llLnYxLkNoYW5nZVBhY2siYwoVQ3JlYXRlUmV2aXNpb25SZXF1ZXN0EhEKCWNsaWVudF9pZBgBIAEoCRITCgtkb2N1bWVudF9pZBgCIAEoCRINCgVsYWJlbBgDIAEoCRITCgtkZXNjcmlwdGlvbhgEIAEoCSJGChZDcmVhdGVSZXZpc2lvblJlc3BvbnNlEiwKCHJldmlzaW9uGAEgASgLMhoueW9ya2llLnYxLlJldmlzaW9uU3VtbWFyeSJRChJHZXRSZXZpc2lvblJlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2RvY3VtZW50X2lkGAIgASgJEhMKC3JldmlzaW9uX2lkGAMgASgJIkMKE0dldFJldmlzaW9uUmVzcG9uc2USLAoIcmV2aXNpb24YASABKAsyGi55b3JraWUudjEuUmV2aXNpb25TdW1tYXJ5InUKFExpc3RSZXZpc2lvbnNSZXF1ZXN0EhEKCWNsaWVudF9pZBgBIAEoCRITCgtkb2N1bWVudF9pZBgCIAEoCRIRCglwYWdlX3NpemUYAyABKAUSDgoGb2Zmc2V0GAQgASgFEhIKCmlzX2ZvcndhcmQYBSABKAgiRgoVTGlzdFJldmlzaW9uc1Jlc3BvbnNlEi0KCXJldmlzaW9ucxgBIAMoCzIaLnlvcmtpZS52MS5SZXZpc2lvblN1bW1hcnkiVQoWUmVzdG9yZVJldmlzaW9uUmVxdWVzdBIRCgljbGllbnRfaWQYASABKAkSEwoLZG9jdW1lbnRfaWQYAiABKAkSEwoLcmV2aXNpb25faWQYBCABKAkiGQoXUmVzdG9yZVJldmlzaW9uUmVzcG9uc2UiPgoUQXR0YWNoQ2hhbm5lbFJlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2NoYW5uZWxfa2V5GAIgASgJIkIKFUF0dGFjaENoYW5uZWxSZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEhUKDXNlc3Npb25fY291bnQYAiABKAMiUgoURGV0YWNoQ2hhbm5lbFJlcXVlc3QSEQoJY2xpZW50X2lkGAEgASgJEhMKC2NoYW5uZWxfa2V5GAIgASgJEhIKCnNlc3Npb25faWQYAyABKAkiLgoVRGV0YWNoQ2hhbm5lbFJlc3BvbnNlEhUKDXNlc3Npb25fY291bnQYASABKAMi2gEKFVJlZnJlc2hDaGFubmVsUmVxdWVzdBIRCgljbGllbnRfaWQYASABKAkSEwoLY2hhbm5lbF9rZXkYAiABKAkSEgoKc2Vzc2lvbl9pZBgDIAEoCRISCgpjbGllbnRfa2V5GAQgASgJEkAKCG1ldGFkYXRhGAUgAygLMi4ueW9ya2llLnYxLlJlZnJlc2hDaGFubmVsUmVxdWVzdC5NZXRhZGF0YUVudHJ5Gi8KDU1ldGFkYXRhRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASJWChZSZWZyZXNoQ2hhbm5lbFJlc3BvbnNlEhUKDXNlc3Npb25fY291bnQYASABKAMSEQoJY2xpZW50X2lkGAIgASgJEhIKCnNlc3Npb25faWQYAyABKAkiKQoSUGVla0NoYW5uZWxSZXF1ZXN0EhMKC2NoYW5uZWxfa2V5GAEgASgJIiwKE1BlZWtDaGFubmVsUmVzcG9uc2USFQoNc2Vzc2lvbl9jb3VudBgBIAEoAyJaChBCcm9hZGNhc3RSZXF1ZXN0EhEKCWNsaWVudF9pZBgBIAEoCRITCgtjaGFubmVsX2tleRgCIAEoCRINCgV0b3BpYxgDIAEoCRIPCgdwYXlsb2FkGAQgASgMIhMKEUJyb2FkY2FzdFJlc3BvbnNlMpUMCg1Zb3JraWVTZXJ2aWNlElcKDkFjdGl2YXRlQ2xpZW50EiAueW9ya2llLnYxLkFjdGl2YXRlQ2xpZW50UmVxdWVzdBohLnlvcmtpZS52MS5BY3RpdmF0ZUNsaWVudFJlc3BvbnNlIgASXQoQRGVhY3RpdmF0ZUNsaWVudBIiLnlvcmtpZS52MS5EZWFjdGl2YXRlQ2xpZW50UmVxdWVzdBojLnlvcmtpZS52MS5EZWFjdGl2YXRlQ2xpZW50UmVzcG9uc2UiABJXCg5BdHRhY2hEb2N1bWVudBIgLnlvcmtpZS52MS5BdHRhY2hEb2N1bWVudFJlcXVlc3QaIS55b3JraWUudjEuQXR0YWNoRG9jdW1lbnRSZXNwb25zZSIAElcKDkRldGFjaERvY3VtZW50EiAueW9ya2llLnYxLkRldGFjaERvY3VtZW50UmVxdWVzdBohLnlvcmtpZS52MS5EZXRhY2hEb2N1bWVudFJlc3BvbnNlIgASVwoOUmVtb3ZlRG9jdW1lbnQSIC55b3JraWUudjEuUmVtb3ZlRG9jdW1lbnRSZXF1ZXN0GiEueW9ya2llLnYxLlJlbW92ZURvY3VtZW50UmVzcG9uc2UiABJaCg9QdXNoUHVsbENoYW5nZXMSIS55b3JraWUudjEuUHVzaFB1bGxDaGFuZ2VzUmVxdWVzdBoiLnlvcmtpZS52MS5QdXNoUHVsbENoYW5nZXNSZXNwb25zZSIAEj4KBVdhdGNoEhcueW9ya2llLnYxLldhdGNoUmVxdWVzdBoYLnlvcmtpZS52MS5XYXRjaFJlc3BvbnNlIgAwARJWCg1XYXRjaERvY3VtZW50Eh8ueW9ya2llLnYxLldhdGNoRG9jdW1lbnRSZXF1ZXN0GiAueW9ya2llLnYxLldhdGNoRG9jdW1lbnRSZXNwb25zZSIAMAESUwoMV2F0Y2hDaGFubmVsEh4ueW9ya2llLnYxLldhdGNoQ2hhbm5lbFJlcXVlc3QaHy55b3JraWUudjEuV2F0Y2hDaGFubmVsUmVzcG9uc2UiADABElcKDkNyZWF0ZVJldmlzaW9uEiAueW9ya2llLnYxLkNyZWF0ZVJldmlzaW9uUmVxdWVzdBohLnlvcmtpZS52MS5DcmVhdGVSZXZpc2lvblJlc3BvbnNlIgASTgoLR2V0UmV2aXNpb24SHS55b3JraWUudjEuR2V0UmV2aXNpb25SZXF1ZXN0Gh4ueW9ya2llLnYxLkdldFJldmlzaW9uUmVzcG9uc2UiABJUCg1MaXN0UmV2aXNpb25zEh8ueW9ya2llLnYxLkxpc3RSZXZpc2lvbnNSZXF1ZXN0GiAueW9ya2llLnYxLkxpc3RSZXZpc2lvbnNSZXNwb25zZSIAEloKD1Jlc3RvcmVSZXZpc2lvbhIhLnlvcmtpZS52MS5SZXN0b3JlUmV2aXNpb25SZXF1ZXN0GiIueW9ya2llLnYxLlJlc3RvcmVSZXZpc2lvblJlc3BvbnNlIgASVAoNQXR0YWNoQ2hhbm5lbBIfLnlvcmtpZS52MS5BdHRhY2hDaGFubmVsUmVxdWVzdBogLnlvcmtpZS52MS5BdHRhY2hDaGFubmVsUmVzcG9uc2UiABJUCg1EZXRhY2hDaGFubmVsEh8ueW9ya2llLnYxLkRldGFjaENoYW5uZWxSZXF1ZXN0GiAueW9ya2llLnYxLkRldGFjaENoYW5uZWxSZXNwb25zZSIAElcKDlJlZnJlc2hDaGFubmVsEiAueW9ya2llLnYxLlJlZnJlc2hDaGFubmVsUmVxdWVzdBohLnlvcmtpZS52MS5SZWZyZXNoQ2hhbm5lbFJlc3BvbnNlIgASTgoLUGVla0NoYW5uZWwSHS55b3JraWUudjEuUGVla0NoYW5uZWxSZXF1ZXN0Gh4ueW9ya2llLnYxLlBlZWtDaGFubmVsUmVzcG9uc2UiABJICglCcm9hZGNhc3QSGy55b3JraWUudjEuQnJvYWRjYXN0UmVxdWVzdBocLnlvcmtpZS52MS5Ccm9hZGNhc3RSZXNwb25zZSIAQkUKEWRldi55b3JraWUuYXBpLnYxUAFaLmdpdGh1Yi5jb20veW9ya2llLXRlYW0veW9ya2llL2FwaS95b3JraWUvdjE7djFiBnByb3RvMw", [file_yorkie_v1_resources]);
|
|
5869
5869
|
const YorkieService = /* @__PURE__ */ serviceDesc(file_yorkie_v1_yorkie, 0);
|
|
5870
5870
|
const file_google_rpc_error_details = /* @__PURE__ */ fileDesc("Ch5nb29nbGUvcnBjL2Vycm9yX2RldGFpbHMucHJvdG8SCmdvb2dsZS5ycGMikwEKCUVycm9ySW5mbxIOCgZyZWFzb24YASABKAkSDgoGZG9tYWluGAIgASgJEjUKCG1ldGFkYXRhGAMgAygLMiMuZ29vZ2xlLnJwYy5FcnJvckluZm8uTWV0YWRhdGFFbnRyeRovCg1NZXRhZGF0YUVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiOwoJUmV0cnlJbmZvEi4KC3JldHJ5X2RlbGF5GAEgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uIjIKCURlYnVnSW5mbxIVCg1zdGFja19lbnRyaWVzGAEgAygJEg4KBmRldGFpbBgCIAEoCSKPAwoMUXVvdGFGYWlsdXJlEjYKCnZpb2xhdGlvbnMYASADKAsyIi5nb29nbGUucnBjLlF1b3RhRmFpbHVyZS5WaW9sYXRpb24axgIKCVZpb2xhdGlvbhIPCgdzdWJqZWN0GAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEhMKC2FwaV9zZXJ2aWNlGAMgASgJEhQKDHF1b3RhX21ldHJpYxgEIAEoCRIQCghxdW90YV9pZBgFIAEoCRJRChBxdW90YV9kaW1lbnNpb25zGAYgAygLMjcuZ29vZ2xlLnJwYy5RdW90YUZhaWx1cmUuVmlvbGF0aW9uLlF1b3RhRGltZW5zaW9uc0VudHJ5EhMKC3F1b3RhX3ZhbHVlGAcgASgDEh8KEmZ1dHVyZV9xdW90YV92YWx1ZRgIIAEoA0gAiAEBGjYKFFF1b3RhRGltZW5zaW9uc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAFCFQoTX2Z1dHVyZV9xdW90YV92YWx1ZSKVAQoTUHJlY29uZGl0aW9uRmFpbHVyZRI9Cgp2aW9sYXRpb25zGAEgAygLMikuZ29vZ2xlLnJwYy5QcmVjb25kaXRpb25GYWlsdXJlLlZpb2xhdGlvbho/CglWaW9sYXRpb24SDAoEdHlwZRgBIAEoCRIPCgdzdWJqZWN0GAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJIswBCgpCYWRSZXF1ZXN0Ej8KEGZpZWxkX3Zpb2xhdGlvbnMYASADKAsyJS5nb29nbGUucnBjLkJhZFJlcXVlc3QuRmllbGRWaW9sYXRpb24afQoORmllbGRWaW9sYXRpb24SDQoFZmllbGQYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDgoGcmVhc29uGAMgASgJEjcKEWxvY2FsaXplZF9tZXNzYWdlGAQgASgLMhwuZ29vZ2xlLnJwYy5Mb2NhbGl6ZWRNZXNzYWdlIjcKC1JlcXVlc3RJbmZvEhIKCnJlcXVlc3RfaWQYASABKAkSFAoMc2VydmluZ19kYXRhGAIgASgJImAKDFJlc291cmNlSW5mbxIVCg1yZXNvdXJjZV90eXBlGAEgASgJEhUKDXJlc291cmNlX25hbWUYAiABKAkSDQoFb3duZXIYAyABKAkSEwoLZGVzY3JpcHRpb24YBCABKAkiVgoESGVscBIkCgVsaW5rcxgBIAMoCzIVLmdvb2dsZS5ycGMuSGVscC5MaW5rGigKBExpbmsSEwoLZGVzY3JpcHRpb24YASABKAkSCwoDdXJsGAIgASgJIjMKEExvY2FsaXplZE1lc3NhZ2USDgoGbG9jYWxlGAEgASgJEg8KB21lc3NhZ2UYAiABKAlCbAoOY29tLmdvb2dsZS5ycGNCEUVycm9yRGV0YWlsc1Byb3RvUAFaP2dvb2dsZS5nb2xhbmcub3JnL2dlbnByb3RvL2dvb2dsZWFwaXMvcnBjL2VycmRldGFpbHM7ZXJyZGV0YWlsc6ICA1JQQ2IGcHJvdG8z", [file_google_protobuf_duration]);
|
|
5871
5871
|
const ErrorInfoSchema = /* @__PURE__ */ messageDesc(file_google_rpc_error_details, 0);
|
|
@@ -5878,6 +5878,7 @@ var Code = /* @__PURE__ */ ((Code2) => {
|
|
|
5878
5878
|
Code2["ErrDummy"] = "ErrDummy";
|
|
5879
5879
|
Code2["ErrNotAttached"] = "ErrNotAttached";
|
|
5880
5880
|
Code2["ErrNotDetached"] = "ErrNotDetached";
|
|
5881
|
+
Code2["ErrSessionNotFound"] = "ErrSessionNotFound";
|
|
5881
5882
|
Code2["ErrDocumentRemoved"] = "ErrDocumentRemoved";
|
|
5882
5883
|
Code2["ErrDocumentSizeExceedsLimit"] = "ErrDocumentSizeExceedsLimit";
|
|
5883
5884
|
Code2["ErrDocumentSchemaValidationFailed"] = "ErrDocumentSchemaValidationFailed";
|
|
@@ -20781,12 +20782,25 @@ class Document {
|
|
|
20781
20782
|
}
|
|
20782
20783
|
class Attachment {
|
|
20783
20784
|
resource;
|
|
20785
|
+
/**
|
|
20786
|
+
* For Documents: the document's resourceID, available at attach time.
|
|
20787
|
+
* For Channels: the server-issued session_id. Starts empty and is
|
|
20788
|
+
* populated after the first `RefreshChannel` first-call response.
|
|
20789
|
+
*/
|
|
20784
20790
|
resourceID;
|
|
20785
20791
|
syncMode;
|
|
20786
20792
|
changeEventReceived;
|
|
20787
20793
|
lastHeartbeatTime;
|
|
20788
20794
|
pollInterval;
|
|
20789
20795
|
pollIntervalPinned;
|
|
20796
|
+
/**
|
|
20797
|
+
* `unsubscribeLocalBroadcast` is set by `attachChannel` when it forwards
|
|
20798
|
+
* a Channel's `local-broadcast` events to the RPC client, and consumed
|
|
20799
|
+
* by `detachInternal` so the subscription does not survive a detach.
|
|
20800
|
+
* Without this, re-attaching a channel accumulates duplicate handlers
|
|
20801
|
+
* on each attach cycle.
|
|
20802
|
+
*/
|
|
20803
|
+
unsubscribeLocalBroadcast;
|
|
20790
20804
|
reconnectStreamDelay;
|
|
20791
20805
|
cancelled;
|
|
20792
20806
|
watchStream;
|
|
@@ -20794,13 +20808,13 @@ class Attachment {
|
|
|
20794
20808
|
watchAbortController;
|
|
20795
20809
|
syncPromise;
|
|
20796
20810
|
_detaching = false;
|
|
20797
|
-
constructor(reconnectStreamDelay, resource, resourceID, syncMode, pollInterval = 0, pollIntervalPinned = false) {
|
|
20811
|
+
constructor(reconnectStreamDelay, resource, resourceID = "", syncMode, pollInterval = 0, pollIntervalPinned = false) {
|
|
20798
20812
|
this.reconnectStreamDelay = reconnectStreamDelay;
|
|
20799
20813
|
this.resource = resource;
|
|
20800
20814
|
this.resourceID = resourceID;
|
|
20801
20815
|
this.syncMode = syncMode;
|
|
20802
20816
|
this.changeEventReceived = syncMode !== void 0 ? false : void 0;
|
|
20803
|
-
this.lastHeartbeatTime =
|
|
20817
|
+
this.lastHeartbeatTime = 0;
|
|
20804
20818
|
this.pollInterval = pollInterval;
|
|
20805
20819
|
this.pollIntervalPinned = pollIntervalPinned;
|
|
20806
20820
|
this.cancelled = false;
|
|
@@ -20962,7 +20976,7 @@ function createAuthInterceptor(apiKey, token) {
|
|
|
20962
20976
|
};
|
|
20963
20977
|
}
|
|
20964
20978
|
const name = "@yorkie-js/sdk";
|
|
20965
|
-
const version = "0.7.
|
|
20979
|
+
const version = "0.7.10-rc";
|
|
20966
20980
|
const pkg = {
|
|
20967
20981
|
name,
|
|
20968
20982
|
version
|
|
@@ -21000,6 +21014,7 @@ var ChannelEventType = /* @__PURE__ */ ((ChannelEventType2) => {
|
|
|
21000
21014
|
ChannelEventType2["Broadcast"] = "broadcast";
|
|
21001
21015
|
ChannelEventType2["LocalBroadcast"] = "local-broadcast";
|
|
21002
21016
|
ChannelEventType2["AuthError"] = "auth-error";
|
|
21017
|
+
ChannelEventType2["SyncError"] = "sync-error";
|
|
21003
21018
|
return ChannelEventType2;
|
|
21004
21019
|
})(ChannelEventType || {});
|
|
21005
21020
|
const KeyPathSeparator = ".";
|
|
@@ -21139,6 +21154,13 @@ class Channel2 {
|
|
|
21139
21154
|
}
|
|
21140
21155
|
});
|
|
21141
21156
|
}
|
|
21157
|
+
if (typeOrTopic === "sync-error") {
|
|
21158
|
+
return this.eventStream.subscribe((event) => {
|
|
21159
|
+
if (event.type === "sync-error") {
|
|
21160
|
+
callback(event);
|
|
21161
|
+
}
|
|
21162
|
+
});
|
|
21163
|
+
}
|
|
21142
21164
|
if (typeOrTopic === "presence") {
|
|
21143
21165
|
return this.eventStream.subscribe((event) => {
|
|
21144
21166
|
if (event.type === "presence-changed" || event.type === "initialized") {
|
|
@@ -21258,13 +21280,14 @@ var ClientCondition = /* @__PURE__ */ ((ClientCondition2) => {
|
|
|
21258
21280
|
ClientCondition2["WatchLoop"] = "WatchLoop";
|
|
21259
21281
|
return ClientCondition2;
|
|
21260
21282
|
})(ClientCondition || {});
|
|
21261
|
-
const
|
|
21283
|
+
const DefaultDocumentPollIntervalMs = 3e3;
|
|
21284
|
+
const DefaultChannelHeartbeatMs = 5e3;
|
|
21262
21285
|
const DefaultClientOptions = {
|
|
21263
21286
|
rpcAddr: "https://api.yorkie.dev",
|
|
21264
21287
|
syncLoopDuration: 50,
|
|
21265
21288
|
retrySyncLoopDelay: 1e3,
|
|
21266
21289
|
reconnectStreamDelay: 1e3,
|
|
21267
|
-
channelHeartbeatInterval:
|
|
21290
|
+
channelHeartbeatInterval: DefaultChannelHeartbeatMs
|
|
21268
21291
|
};
|
|
21269
21292
|
const DefaultBroadcastOptions = {
|
|
21270
21293
|
maxRetries: Infinity,
|
|
@@ -21461,7 +21484,7 @@ class Client {
|
|
|
21461
21484
|
);
|
|
21462
21485
|
}
|
|
21463
21486
|
const pollIntervalPinned = opts.documentPollInterval !== void 0;
|
|
21464
|
-
const pollInterval = pollIntervalPinned ? opts.documentPollInterval : syncMode === "polling" ?
|
|
21487
|
+
const pollInterval = pollIntervalPinned ? opts.documentPollInterval : syncMode === "polling" ? DefaultDocumentPollIntervalMs : 0;
|
|
21465
21488
|
return this.enqueueTask(async () => {
|
|
21466
21489
|
try {
|
|
21467
21490
|
const res = await this.rpcClient.attachDocument(
|
|
@@ -21590,127 +21613,88 @@ class Client {
|
|
|
21590
21613
|
return this.enqueueTask(task);
|
|
21591
21614
|
}
|
|
21592
21615
|
/**
|
|
21593
|
-
* `
|
|
21594
|
-
*
|
|
21616
|
+
* `attachChannel` attaches the given channel to this client. The channel is
|
|
21617
|
+
* registered locally and the server is notified on the next RefreshChannel
|
|
21618
|
+
* heartbeat.
|
|
21595
21619
|
*/
|
|
21596
21620
|
async attachChannel(channel, opts = {}) {
|
|
21597
|
-
if (!this.isActive()) {
|
|
21598
|
-
throw new YorkieError(
|
|
21599
|
-
Code.ErrClientNotActivated,
|
|
21600
|
-
`${this.key} is not active`
|
|
21601
|
-
);
|
|
21602
|
-
}
|
|
21603
21621
|
if (channel.getStatus() !== ChannelStatus.Detached) {
|
|
21604
21622
|
throw new YorkieError(
|
|
21605
21623
|
Code.ErrNotDetached,
|
|
21606
21624
|
`${channel.getKey()} is not detached`
|
|
21607
21625
|
);
|
|
21608
21626
|
}
|
|
21609
|
-
|
|
21627
|
+
const syncMode = opts.syncMode ?? "realtime";
|
|
21628
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21629
|
+
if (opts.channelHeartbeatInterval !== void 0 && opts.channelHeartbeatInterval <= 0) {
|
|
21630
|
+
throw new YorkieError(
|
|
21631
|
+
Code.ErrInvalidArgument,
|
|
21632
|
+
"channelHeartbeatInterval must be greater than 0"
|
|
21633
|
+
);
|
|
21634
|
+
}
|
|
21635
|
+
const pollIntervalPinned = opts.channelHeartbeatInterval !== void 0;
|
|
21636
|
+
const pollInterval = opts.channelHeartbeatInterval ?? this.channelHeartbeatInterval;
|
|
21610
21637
|
const task = async () => {
|
|
21611
|
-
|
|
21612
|
-
|
|
21613
|
-
|
|
21614
|
-
|
|
21615
|
-
|
|
21616
|
-
|
|
21617
|
-
|
|
21618
|
-
|
|
21619
|
-
|
|
21620
|
-
|
|
21621
|
-
|
|
21622
|
-
|
|
21623
|
-
|
|
21624
|
-
|
|
21625
|
-
|
|
21626
|
-
const syncMode = opts.syncMode ?? "realtime";
|
|
21627
|
-
this.assertValidChannelSyncMode(syncMode);
|
|
21628
|
-
if (opts.channelHeartbeatInterval !== void 0 && opts.channelHeartbeatInterval <= 0) {
|
|
21629
|
-
throw new YorkieError(
|
|
21630
|
-
Code.ErrInvalidArgument,
|
|
21631
|
-
"channelHeartbeatInterval must be greater than 0"
|
|
21632
|
-
);
|
|
21633
|
-
}
|
|
21634
|
-
const pollIntervalPinned = opts.channelHeartbeatInterval !== void 0;
|
|
21635
|
-
const pollInterval = pollIntervalPinned ? opts.channelHeartbeatInterval : syncMode === "polling" ? DefaultPollingIntervalMs : this.channelHeartbeatInterval;
|
|
21636
|
-
const attachment = new Attachment(
|
|
21637
|
-
this.reconnectStreamDelay,
|
|
21638
|
-
channel,
|
|
21639
|
-
res.sessionId,
|
|
21640
|
-
syncMode,
|
|
21641
|
-
pollInterval,
|
|
21642
|
-
pollIntervalPinned
|
|
21643
|
-
);
|
|
21644
|
-
channel.subscribe("local-broadcast", (event) => {
|
|
21638
|
+
if (this.id) {
|
|
21639
|
+
channel.setActor(this.id);
|
|
21640
|
+
}
|
|
21641
|
+
const attachment = new Attachment(
|
|
21642
|
+
this.reconnectStreamDelay,
|
|
21643
|
+
channel,
|
|
21644
|
+
"",
|
|
21645
|
+
// sessionID populated on first refresh response
|
|
21646
|
+
syncMode,
|
|
21647
|
+
pollInterval,
|
|
21648
|
+
pollIntervalPinned
|
|
21649
|
+
);
|
|
21650
|
+
attachment.unsubscribeLocalBroadcast = channel.subscribe(
|
|
21651
|
+
"local-broadcast",
|
|
21652
|
+
(event) => {
|
|
21645
21653
|
const { topic, payload, options } = event;
|
|
21646
21654
|
this.broadcast(channel.getKey(), topic, payload, options).catch(
|
|
21647
21655
|
(error) => {
|
|
21648
|
-
if (options?.error)
|
|
21649
|
-
options.error(error);
|
|
21650
|
-
}
|
|
21656
|
+
if (options?.error) options.error(error);
|
|
21651
21657
|
logger.error(`[BC] c:"${this.getKey()}" failed: ${error}`);
|
|
21652
21658
|
}
|
|
21653
21659
|
);
|
|
21654
|
-
});
|
|
21655
|
-
this.attachmentMap.set(channel.getKey(), attachment);
|
|
21656
|
-
if (syncMode === "realtime") {
|
|
21657
|
-
await this.runWatchLoop(channel.getKey());
|
|
21658
21660
|
}
|
|
21659
|
-
|
|
21660
|
-
|
|
21661
|
-
|
|
21662
|
-
|
|
21663
|
-
|
|
21664
|
-
|
|
21665
|
-
|
|
21666
|
-
throw err;
|
|
21661
|
+
);
|
|
21662
|
+
this.attachmentMap.set(channel.getKey(), attachment);
|
|
21663
|
+
if (!this.conditions[
|
|
21664
|
+
"SyncLoop"
|
|
21665
|
+
/* SyncLoop */
|
|
21666
|
+
]) {
|
|
21667
|
+
this.runSyncLoop();
|
|
21667
21668
|
}
|
|
21669
|
+
logger.info(
|
|
21670
|
+
`[AP] c:"${this.getKey()}" attaches p:"${channel.getKey()}" mode:${syncMode}`
|
|
21671
|
+
);
|
|
21672
|
+
return channel;
|
|
21668
21673
|
};
|
|
21669
21674
|
return this.enqueueTask(task);
|
|
21670
21675
|
}
|
|
21671
21676
|
/**
|
|
21672
|
-
* `detachChannel` detaches the given channel from this client.
|
|
21673
|
-
*
|
|
21677
|
+
* `detachChannel` detaches the given channel from this client. The detach
|
|
21678
|
+
* is a local cleanup; the server reclaims the session via TTL when
|
|
21679
|
+
* heartbeats stop.
|
|
21674
21680
|
*/
|
|
21675
21681
|
async detachChannel(channel) {
|
|
21676
|
-
|
|
21677
|
-
|
|
21678
|
-
Code.ErrClientNotActivated,
|
|
21679
|
-
`${this.key} is not active`
|
|
21680
|
-
);
|
|
21681
|
-
}
|
|
21682
|
-
if (!this.attachmentMap.has(channel.getKey())) {
|
|
21682
|
+
const attachment = this.attachmentMap.get(channel.getKey());
|
|
21683
|
+
if (!attachment) {
|
|
21683
21684
|
throw new YorkieError(
|
|
21684
21685
|
Code.ErrNotAttached,
|
|
21685
21686
|
`${channel.getKey()} is not attached`
|
|
21686
21687
|
);
|
|
21687
21688
|
}
|
|
21689
|
+
attachment.markDetaching();
|
|
21690
|
+
await attachment.waitForSyncComplete();
|
|
21688
21691
|
const task = async () => {
|
|
21689
|
-
|
|
21690
|
-
|
|
21691
|
-
|
|
21692
|
-
|
|
21693
|
-
|
|
21694
|
-
|
|
21695
|
-
},
|
|
21696
|
-
{
|
|
21697
|
-
headers: {
|
|
21698
|
-
"x-shard-key": `${this.apiKey}/${channel.getFirstKeyPath()}`
|
|
21699
|
-
}
|
|
21700
|
-
}
|
|
21701
|
-
);
|
|
21702
|
-
channel.updateSessionCount(Number(res.sessionCount), 0);
|
|
21703
|
-
channel.applyStatus(ChannelStatus.Detached);
|
|
21704
|
-
this.detachInternal(channel.getKey());
|
|
21705
|
-
logger.info(
|
|
21706
|
-
`[DP] c:"${this.getKey()}" detaches p:"${channel.getKey()}" count:${channel.getSessionCount()}`
|
|
21707
|
-
);
|
|
21708
|
-
return channel;
|
|
21709
|
-
} catch (err) {
|
|
21710
|
-
logger.error(`[DP] c:"${this.getKey()}" err :`, err);
|
|
21711
|
-
await this.handleConnectError(err);
|
|
21712
|
-
throw err;
|
|
21713
|
-
}
|
|
21692
|
+
channel.applyStatus(ChannelStatus.Detached);
|
|
21693
|
+
this.detachInternal(channel.getKey());
|
|
21694
|
+
logger.info(
|
|
21695
|
+
`[DP] c:"${this.getKey()}" detaches p:"${channel.getKey()}" (local)`
|
|
21696
|
+
);
|
|
21697
|
+
return channel;
|
|
21714
21698
|
};
|
|
21715
21699
|
return this.enqueueTask(task);
|
|
21716
21700
|
}
|
|
@@ -21751,7 +21735,7 @@ class Client {
|
|
|
21751
21735
|
attachment.changeEventReceived = true;
|
|
21752
21736
|
}
|
|
21753
21737
|
if (!attachment.pollIntervalPinned) {
|
|
21754
|
-
attachment.pollInterval = syncMode === "polling" ?
|
|
21738
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultDocumentPollIntervalMs : 0;
|
|
21755
21739
|
}
|
|
21756
21740
|
if ((prevSyncMode === "manual" || prevSyncMode === "polling") && syncMode !== "manual" && syncMode !== "polling") {
|
|
21757
21741
|
attachment.resetCancelled();
|
|
@@ -21772,12 +21756,6 @@ class Client {
|
|
|
21772
21756
|
}
|
|
21773
21757
|
}
|
|
21774
21758
|
async changeChannelSyncMode(channel, syncMode) {
|
|
21775
|
-
if (!this.isActive()) {
|
|
21776
|
-
throw new YorkieError(
|
|
21777
|
-
Code.ErrClientNotActivated,
|
|
21778
|
-
`${this.key} is not active`
|
|
21779
|
-
);
|
|
21780
|
-
}
|
|
21781
21759
|
const attachment = this.attachmentMap.get(channel.getKey());
|
|
21782
21760
|
if (!attachment) {
|
|
21783
21761
|
throw new YorkieError(
|
|
@@ -21795,7 +21773,7 @@ class Client {
|
|
|
21795
21773
|
}
|
|
21796
21774
|
attachment.changeSyncMode(syncMode);
|
|
21797
21775
|
if (!attachment.pollIntervalPinned) {
|
|
21798
|
-
attachment.pollInterval = syncMode === "
|
|
21776
|
+
attachment.pollInterval = syncMode === "manual" ? 0 : this.channelHeartbeatInterval;
|
|
21799
21777
|
}
|
|
21800
21778
|
if (syncMode === "realtime") {
|
|
21801
21779
|
attachment.resetCancelled();
|
|
@@ -21807,7 +21785,7 @@ class Client {
|
|
|
21807
21785
|
* `sync` implementation that handles both Document and Channel.
|
|
21808
21786
|
*/
|
|
21809
21787
|
sync(resource) {
|
|
21810
|
-
if (!this.isActive()) {
|
|
21788
|
+
if (!(resource instanceof Channel2) && !this.isActive()) {
|
|
21811
21789
|
throw new YorkieError(
|
|
21812
21790
|
Code.ErrClientNotActivated,
|
|
21813
21791
|
`${this.key} is not active`
|
|
@@ -22134,12 +22112,6 @@ class Client {
|
|
|
22134
22112
|
* subscribe to channel events. Polling is the caller's responsibility.
|
|
22135
22113
|
*/
|
|
22136
22114
|
async peekChannel(channelKey) {
|
|
22137
|
-
if (!this.isActive()) {
|
|
22138
|
-
throw new YorkieError(
|
|
22139
|
-
Code.ErrClientNotActivated,
|
|
22140
|
-
`${this.key} is not active`
|
|
22141
|
-
);
|
|
22142
|
-
}
|
|
22143
22115
|
return this.enqueueTask(async () => {
|
|
22144
22116
|
const firstKeyPath = channelKey.split(".")[0];
|
|
22145
22117
|
const res = await this.rpcClient.peekChannel(
|
|
@@ -22157,12 +22129,6 @@ class Client {
|
|
|
22157
22129
|
* `broadcast` broadcasts the given payload to the given topic.
|
|
22158
22130
|
*/
|
|
22159
22131
|
async broadcast(key, topic, payload, options) {
|
|
22160
|
-
if (!this.isActive()) {
|
|
22161
|
-
throw new YorkieError(
|
|
22162
|
-
Code.ErrClientNotActivated,
|
|
22163
|
-
`${this.key} is not active`
|
|
22164
|
-
);
|
|
22165
|
-
}
|
|
22166
22132
|
const attachment = this.attachmentMap.get(key);
|
|
22167
22133
|
if (!attachment) {
|
|
22168
22134
|
throw new YorkieError(Code.ErrNotAttached, `${key} is not attached`);
|
|
@@ -22239,8 +22205,16 @@ class Client {
|
|
|
22239
22205
|
*/
|
|
22240
22206
|
runSyncLoop() {
|
|
22241
22207
|
const doLoop = async () => {
|
|
22242
|
-
if (
|
|
22243
|
-
logger.debug(`[SL] c:"${this.getKey()}" exit sync loop`);
|
|
22208
|
+
if (this.deactivating) {
|
|
22209
|
+
logger.debug(`[SL] c:"${this.getKey()}" exit sync loop (deactivating)`);
|
|
22210
|
+
this.conditions[
|
|
22211
|
+
"SyncLoop"
|
|
22212
|
+
/* SyncLoop */
|
|
22213
|
+
] = false;
|
|
22214
|
+
return;
|
|
22215
|
+
}
|
|
22216
|
+
if (!this.isActive() && this.attachmentMap.size === 0) {
|
|
22217
|
+
logger.debug(`[SL] c:"${this.getKey()}" exit sync loop (idle)`);
|
|
22244
22218
|
this.conditions[
|
|
22245
22219
|
"SyncLoop"
|
|
22246
22220
|
/* SyncLoop */
|
|
@@ -22626,6 +22600,10 @@ class Client {
|
|
|
22626
22600
|
return;
|
|
22627
22601
|
}
|
|
22628
22602
|
attachment.cancelWatchStream();
|
|
22603
|
+
if (attachment.unsubscribeLocalBroadcast) {
|
|
22604
|
+
attachment.unsubscribeLocalBroadcast();
|
|
22605
|
+
attachment.unsubscribeLocalBroadcast = void 0;
|
|
22606
|
+
}
|
|
22629
22607
|
if (attachment.resource instanceof Document) {
|
|
22630
22608
|
attachment.resource.resetOnlineClients();
|
|
22631
22609
|
}
|
|
@@ -22634,12 +22612,17 @@ class Client {
|
|
|
22634
22612
|
async syncInternal(attachment, syncMode) {
|
|
22635
22613
|
const { resource } = attachment;
|
|
22636
22614
|
if (resource instanceof Channel2) {
|
|
22615
|
+
const isFirstCall = !resource.getSessionID();
|
|
22637
22616
|
try {
|
|
22638
22617
|
const res = await this.rpcClient.refreshChannel(
|
|
22639
22618
|
{
|
|
22640
|
-
clientId: this.id,
|
|
22619
|
+
clientId: this.id ?? "",
|
|
22641
22620
|
channelKey: resource.getKey(),
|
|
22642
|
-
sessionId: resource.getSessionID()
|
|
22621
|
+
sessionId: resource.getSessionID() ?? "",
|
|
22622
|
+
// First-call only — these fields are ignored by the server
|
|
22623
|
+
// once a session_id is established.
|
|
22624
|
+
clientKey: isFirstCall ? this.key : "",
|
|
22625
|
+
metadata: isFirstCall ? this.metadata : {}
|
|
22643
22626
|
},
|
|
22644
22627
|
{
|
|
22645
22628
|
headers: {
|
|
@@ -22647,6 +22630,31 @@ class Client {
|
|
|
22647
22630
|
}
|
|
22648
22631
|
}
|
|
22649
22632
|
);
|
|
22633
|
+
if (isFirstCall) {
|
|
22634
|
+
if (this.deactivating || attachment.isDetaching()) {
|
|
22635
|
+
return resource;
|
|
22636
|
+
}
|
|
22637
|
+
if (res.clientId && !this.id) {
|
|
22638
|
+
this.id = res.clientId;
|
|
22639
|
+
this.status = "activated";
|
|
22640
|
+
resource.setActor(res.clientId);
|
|
22641
|
+
} else if (this.id) {
|
|
22642
|
+
resource.setActor(this.id);
|
|
22643
|
+
}
|
|
22644
|
+
if (res.sessionId) {
|
|
22645
|
+
resource.setSessionID(res.sessionId);
|
|
22646
|
+
attachment.resourceID = res.sessionId;
|
|
22647
|
+
resource.applyStatus(ChannelStatus.Attached);
|
|
22648
|
+
}
|
|
22649
|
+
if (attachment.syncMode === "realtime") {
|
|
22650
|
+
this.runWatchLoop(resource.getKey()).catch((err) => {
|
|
22651
|
+
logger.error(
|
|
22652
|
+
`[WP] c:"${this.getKey()}" failed to start watch for p:"${resource.getKey()}":`,
|
|
22653
|
+
err
|
|
22654
|
+
);
|
|
22655
|
+
});
|
|
22656
|
+
}
|
|
22657
|
+
}
|
|
22650
22658
|
const prevCount = resource.getSessionCount();
|
|
22651
22659
|
if (resource.updateSessionCount(Number(res.sessionCount), 0)) {
|
|
22652
22660
|
if (resource.getSessionCount() !== prevCount) {
|
|
@@ -22661,6 +22669,21 @@ class Client {
|
|
|
22661
22669
|
`[RP] c:"${this.getKey()}" refreshes p:"${resource.getKey()}" mode:${attachment.syncMode}`
|
|
22662
22670
|
);
|
|
22663
22671
|
} catch (err) {
|
|
22672
|
+
if (isErrorCode(err, Code.ErrSessionNotFound)) {
|
|
22673
|
+
logger.info(
|
|
22674
|
+
`[RP] c:"${this.getKey()}" session expired for p:"${resource.getKey()}", re-attaching`
|
|
22675
|
+
);
|
|
22676
|
+
resource.setSessionID("");
|
|
22677
|
+
attachment.resourceID = "";
|
|
22678
|
+
return resource;
|
|
22679
|
+
}
|
|
22680
|
+
if (!this.deactivating && !attachment.isDetaching()) {
|
|
22681
|
+
resource.publish({
|
|
22682
|
+
type: ChannelEventType.SyncError,
|
|
22683
|
+
error: err,
|
|
22684
|
+
method: "RefreshChannel"
|
|
22685
|
+
});
|
|
22686
|
+
}
|
|
22664
22687
|
logger.error(`[RP] c:"${this.getKey()}" err :`, err);
|
|
22665
22688
|
throw err;
|
|
22666
22689
|
}
|