Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/sync/client/sync-client.ts
1447 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
/*
7
Functionality related to Sync.
8
*/
9
10
import { once } from "@cocalc/util/async-utils";
11
import { defaults, required } from "@cocalc/util/misc";
12
import { SyncDoc, SyncOpts0 } from "@cocalc/sync/editor/generic/sync-doc";
13
import { SyncDB, SyncDBOpts0 } from "@cocalc/sync/editor/db";
14
import { SyncString } from "@cocalc/sync/editor/string/sync";
15
import {
16
synctable,
17
SyncTable,
18
Query,
19
QueryOptions,
20
synctable_no_changefeed,
21
} from "@cocalc/sync/table";
22
import type { AppClient } from "./types";
23
import { getSyncDocType } from "@cocalc/conat/sync/syncdoc-info";
24
25
interface SyncOpts extends Omit<SyncOpts0, "client"> {
26
noCache?: boolean;
27
client?: AppClient;
28
}
29
30
interface SyncDBOpts extends Omit<SyncDBOpts0, "client" | "string_cols"> {
31
string_cols?: string[];
32
noCache?: boolean;
33
client?: AppClient;
34
}
35
36
export class SyncClient {
37
private client: AppClient;
38
39
constructor(client: AppClient) {
40
this.client = client;
41
}
42
43
public sync_table(
44
query: Query,
45
options?: QueryOptions,
46
throttle_changes?: number,
47
): SyncTable {
48
return synctable(query, options ?? [], this.client, throttle_changes);
49
}
50
51
public async synctable_database(
52
query: Query,
53
options?: QueryOptions,
54
throttle_changes?: number,
55
): Promise<SyncTable> {
56
const s = this.sync_table(query, options ?? [], throttle_changes);
57
await once(s, "connected");
58
return s;
59
}
60
61
public synctable_no_changefeed(
62
query: Query,
63
options?: QueryOptions,
64
throttle_changes?: number,
65
): SyncTable {
66
return synctable_no_changefeed(
67
query,
68
options ?? [],
69
this.client,
70
throttle_changes,
71
);
72
}
73
74
// These are not working properly, e.g., if you close and open
75
// a LARGE jupyter notebook quickly (so save to disk takes a while),
76
// then it gets broken until browser refresh. The problem is that
77
// the doc is still closing right when a new one starts being created.
78
// So for now we just revert to the non-cached-here approach.
79
// There is other caching elsewhere.
80
81
// public sync_string(opts: SyncOpts): SyncString {
82
// return syncstringCache({ ...opts, client: this.client });
83
// }
84
85
// public sync_db(opts: SyncDBOpts): SyncDB {
86
// return syncdbCache({ ...opts, client: this.client });
87
// }
88
89
public sync_string(opts: SyncOpts): SyncString {
90
const opts0: SyncOpts0 = defaults(opts, {
91
id: undefined,
92
project_id: required,
93
path: required,
94
file_use_interval: "default",
95
cursors: false,
96
patch_interval: 1000,
97
save_interval: 2000,
98
persistent: false,
99
data_server: undefined,
100
client: this.client,
101
ephemeral: false,
102
});
103
return new SyncString(opts0);
104
}
105
106
public sync_db(opts: SyncDBOpts): SyncDoc {
107
const opts0: SyncDBOpts0 = defaults(opts, {
108
id: undefined,
109
project_id: required,
110
path: required,
111
file_use_interval: "default",
112
cursors: false,
113
patch_interval: 1000,
114
save_interval: 2000,
115
change_throttle: undefined,
116
persistent: false,
117
data_server: undefined,
118
119
primary_keys: required,
120
string_cols: [],
121
122
client: this.client,
123
124
ephemeral: false,
125
});
126
return new SyncDB(opts0);
127
}
128
129
public async open_existing_sync_document({
130
project_id,
131
path,
132
data_server,
133
persistent,
134
}: {
135
project_id: string;
136
path: string;
137
data_server?: string;
138
persistent?: boolean;
139
}): Promise<SyncDoc | undefined> {
140
const doctype = await getSyncDocType({
141
project_id,
142
path,
143
client: this.client,
144
});
145
const { type } = doctype;
146
const f = `sync_${type}`;
147
return (this as any)[f]({
148
project_id,
149
path,
150
data_server,
151
persistent,
152
...doctype.opts,
153
});
154
}
155
}
156
157
/*
158
const syncdbCache = refCacheSync<SyncDBOpts, SyncDB>({
159
name: "syncdb",
160
161
createKey: ({ project_id, path }: SyncDBOpts) => {
162
return JSON.stringify({ project_id, path });
163
},
164
165
createObject: (opts: SyncDBOpts) => {
166
const opts0: SyncDBOpts0 = defaults(opts, {
167
id: undefined,
168
project_id: required,
169
path: required,
170
file_use_interval: "default",
171
cursors: false,
172
patch_interval: 1000,
173
save_interval: 2000,
174
change_throttle: undefined,
175
persistent: false,
176
data_server: undefined,
177
178
primary_keys: required,
179
string_cols: [],
180
181
client: required,
182
183
ephemeral: false,
184
});
185
return new SyncDB(opts0);
186
},
187
});
188
189
const syncstringCache = refCacheSync<SyncOpts, SyncString>({
190
name: "syncstring",
191
createKey: ({ project_id, path }: SyncOpts) => {
192
const key = JSON.stringify({ project_id, path });
193
return key;
194
},
195
196
createObject: (opts: SyncOpts) => {
197
const opts0: SyncOpts0 = defaults(opts, {
198
id: undefined,
199
project_id: required,
200
path: required,
201
file_use_interval: "default",
202
cursors: false,
203
patch_interval: 1000,
204
save_interval: 2000,
205
persistent: false,
206
data_server: undefined,
207
client: required,
208
ephemeral: false,
209
});
210
return new SyncString(opts0);
211
},
212
});
213
*/
214
215