Skip to content

Commit 0e87644

Browse files
authored
Merge pull request #134 from makeflow/7382
7382
2 parents 9652e10 + c5ad901 commit 0e87644

File tree

14 files changed

+161
-26
lines changed

14 files changed

+161
-26
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
"files.insertFinalNewline": true,
1010
"files.trimTrailingWhitespace": true,
1111
"typescript.tsdk": "node_modules/typescript/lib",
12-
"cSpell.words": ["jsondiffpatch", "mobx", "syncable", "syncables"]
12+
"cSpell.words": ["jsondiffpatch", "mobx", "syncable", "syncables", "tslang"]
1313
}

client/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@syncable/client",
3-
"version": "3.0.0-wip.54",
3+
"version": "3.0.0-wip.60",
44
"publishConfig": {
55
"access": "public"
66
},
@@ -37,7 +37,7 @@
3737
"dependencies": {
3838
"jsondiffpatch": "^0.3.11",
3939
"lodash": "^4.17.14",
40-
"tslang": "^0.1.22",
40+
"tslang": "^0.1.23",
4141
"villa": "^0.3.1"
4242
},
4343
"devDependencies": {

client/src/library/client.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,19 @@ export class Client<TGenericParams extends IClientGenericParams>
203203

204204
async query(
205205
update: ViewQueryUpdateObject<TGenericParams['viewQueryDict']>,
206+
forceUpdate?: boolean,
206207
): Promise<void>;
207-
async query(update: ViewQueryUpdateObject): Promise<void> {
208+
async query(
209+
update: ViewQueryUpdateObject,
210+
forceUpdate?: boolean,
211+
): Promise<void> {
208212
runInAction(() => {
209213
this.pendingQueryingNumber++;
210214
});
211215

212216
try {
213217
await this.ready;
214-
await this._query(update);
218+
await this._query(update, forceUpdate);
215219
} finally {
216220
runInAction(() => {
217221
this.pendingQueryingNumber--;
@@ -260,6 +264,7 @@ export class Client<TGenericParams extends IClientGenericParams>
260264
syncables: [],
261265
removals: [],
262266
updates: [],
267+
queryMetadata: {},
263268
},
264269
{
265270
id,
@@ -338,9 +343,13 @@ export class Client<TGenericParams extends IClientGenericParams>
338343
@RPCMethod()
339344
@action
340345
sync(
341-
{syncables, removals, updates}: SyncData,
346+
{syncables, removals, updates, queryMetadata}: SyncData,
342347
source?: SyncUpdateSource,
343348
): void {
349+
for (let [viewQueryName, metadata] of Object.entries(queryMetadata)) {
350+
this.context.setQueryMetadata(viewQueryName, metadata);
351+
}
352+
344353
let container = this.container;
345354

346355
let pendingChangeInfos = this.pendingChangeInfos;
@@ -444,7 +453,10 @@ export class Client<TGenericParams extends IClientGenericParams>
444453
this.container.addSyncable(snapshot, clock);
445454
}
446455

447-
private async _query(update: ViewQueryUpdateObject): Promise<void> {
456+
private async _query(
457+
update: ViewQueryUpdateObject,
458+
forceUpdate = false,
459+
): Promise<void> {
448460
update = _.cloneDeep(update);
449461

450462
let viewQueryInfoMap = this.nameToViewQueryInfoMap;
@@ -454,7 +466,7 @@ export class Client<TGenericParams extends IClientGenericParams>
454466
).filter(([name, query]) => {
455467
let info = viewQueryInfoMap.get(name);
456468

457-
if (info && _.isEqual(toJS(info.query), query)) {
469+
if (info && _.isEqual(toJS(info.query), query) && !forceUpdate) {
458470
delete (update as any)[name];
459471
return false;
460472
} else {

core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@syncable/core",
3-
"version": "3.0.0-wip.58",
3+
"version": "3.0.0-wip.61",
44
"publishConfig": {
55
"access": "public"
66
},
@@ -38,7 +38,7 @@
3838
"jsondiffpatch": "^0.3.11",
3939
"lodash": "^4.17.14",
4040
"replace-object": "^0.2.1",
41-
"tslang": "^0.1.22",
41+
"tslang": "^0.1.23",
4242
"uuid": "^3.3.2",
4343
"villa": "^0.3.1"
4444
},

core/src/library/connection-client/sync.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ export interface SyncDataUpdateEntry {
88
delta: Delta;
99
}
1010

11-
export interface SyncData {
11+
export interface SyncData<TQueryMetadata = object> {
1212
syncables: ISyncable[];
1313
removals: SyncableRef[];
1414
updates: SyncDataUpdateEntry[];
15+
queryMetadata: TQueryMetadata;
1516
}
1617

1718
export interface SyncUpdateSource {

core/src/library/context.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {observable} from 'mobx';
2+
import {Dict} from 'tslang';
23

34
import {ISyncableObject, SyncableRef} from './syncable';
45

@@ -14,13 +15,19 @@ export type ContextType = 'server' | 'user';
1415

1516
export type ContextEnvironment = 'server' | 'client';
1617

17-
abstract class Context<TSyncableObject extends ISyncableObject> {
18+
abstract class Context<
19+
TSyncableObject extends ISyncableObject,
20+
TViewQueryMetadataDict extends object
21+
> {
1822
@observable
1923
ref!: SyncableRef<TSyncableObject>;
2024

2125
@observable
2226
object!: TSyncableObject;
2327

28+
@observable
29+
queryMetadataDict: Partial<TViewQueryMetadataDict> = {};
30+
2431
constructor(
2532
readonly type: ContextType,
2633
readonly environment: ContextEnvironment,
@@ -41,10 +48,15 @@ abstract class Context<TSyncableObject extends ISyncableObject> {
4148
this.ref = object.ref;
4249
this.object = object;
4350
}
51+
52+
setQueryMetadata(name: string, metadata: unknown): void {
53+
(this.queryMetadataDict as Dict<unknown>)[name] = metadata;
54+
}
4455
}
4556

4657
export interface IContext<
47-
TSyncableObject extends ISyncableObject = ISyncableObject
48-
> extends Context<TSyncableObject> {}
58+
TSyncableObject extends ISyncableObject = ISyncableObject,
59+
TViewQueryMetadataDict extends object = Dict<unknown>
60+
> extends Context<TSyncableObject, TViewQueryMetadataDict> {}
4961

5062
export const AbstractContext = Context;

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "3.0.0-wip.59",
2+
"version": "3.0.0-wip.62",
33
"npmClient": "yarn",
44
"command": {
55
"publish": {

server/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@syncable/server",
3-
"version": "3.0.0-wip.59",
3+
"version": "3.0.0-wip.62",
44
"publishConfig": {
55
"access": "public"
66
},
@@ -36,7 +36,7 @@
3636
"extendable-error": "^0.1.5",
3737
"lodash": "^4.17.14",
3838
"rxjs": "^6.5.2",
39-
"tslang": "^0.1.22",
39+
"tslang": "^0.1.23",
4040
"villa": "^0.3.1"
4141
},
4242
"devDependencies": {

server/src/library/connection/connection.ts

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ export class Connection<
8282

8383
private nameToViewQueryInfoMap = new Map<string, ViewQueryInfo>();
8484

85+
private nameToContextDependencyRefsMap = new Map<string, SyncableRef[]>();
86+
8587
private loadedKeySet = new Set<string>();
8688
private sanitizedFieldNamesMap = new Map<string, string[]>();
8789

@@ -275,7 +277,27 @@ export class Connection<
275277
let nameToViewQueryInfoMap = this.nameToViewQueryInfoMap;
276278

277279
if (contextObjectChanged) {
278-
relevantViewQueryNames = Array.from(nameToViewQueryInfoMap.keys());
280+
let contextDependencyRefsEntries = Object.entries(
281+
await this.server.resolveQueryToContextDependencyRefsDict(context),
282+
);
283+
284+
relevantViewQueryNames = _.union(
285+
Array.from(nameToViewQueryInfoMap.keys()),
286+
_.compact(
287+
contextDependencyRefsEntries.map(([viewQueryName, refs]) =>
288+
_.isEqual(
289+
this.nameToContextDependencyRefsMap.get(viewQueryName),
290+
refs,
291+
)
292+
? undefined
293+
: viewQueryName,
294+
),
295+
),
296+
);
297+
298+
this.nameToContextDependencyRefsMap = new Map(
299+
contextDependencyRefsEntries,
300+
);
279301
} else {
280302
let keyToViewQueryNameSet = new Map<string, Set<string>>();
281303

@@ -285,7 +307,10 @@ export class Connection<
285307
query: {refs: refDict},
286308
},
287309
] of nameToViewQueryInfoMap) {
288-
for (let ref of Object.values(refDict)) {
310+
for (let ref of _.union(
311+
Object.values(refDict).flat(),
312+
this.nameToContextDependencyRefsMap.get(name) || [],
313+
)) {
289314
let key = getSyncableKey(ref);
290315

291316
let nameSet = keyToViewQueryNameSet.get(key);
@@ -467,10 +492,13 @@ export class Connection<
467492

468493
syncables.push(...sanitizedDependentSyncables);
469494

495+
let queryMetadata = context.queryMetadataDict;
496+
470497
let data: SyncData = {
471498
syncables,
472499
removals,
473500
updates,
501+
queryMetadata,
474502
};
475503

476504
if (
@@ -542,8 +570,18 @@ export class Connection<
542570
if (context.disabled) {
543571
throw new RPCError('CONTEXT_DISABLED');
544572
}
573+
574+
let contextDependencyRefsDict = await this.server.resolveQueryToContextDependencyRefsDict(
575+
context,
576+
);
577+
578+
this.nameToContextDependencyRefsMap = new Map(
579+
Object.entries(contextDependencyRefsDict),
580+
);
545581
}
546582

583+
let previousQueryMetadataDict = _.cloneDeep(context.queryMetadataDict);
584+
547585
let {
548586
syncables,
549587
nameToViewQueryMapToAdd,
@@ -575,10 +613,13 @@ export class Connection<
575613
loadedKeySet.add(getSyncableKey(syncable));
576614
}
577615

616+
let queryMetadataDict = context.queryMetadataDict;
617+
578618
let data: SyncData = {
579619
syncables,
580620
removals: [],
581621
updates: [],
622+
queryMetadata: queryMetadataDict,
582623
};
583624

584625
if (toInitialize) {
@@ -588,26 +629,31 @@ export class Connection<
588629
contextRef,
589630
this.connectionAdapter.viewQueryDict as ViewQueryUpdateObject,
590631
);
591-
} else if (syncables.length || source) {
632+
} else if (
633+
syncables.length ||
634+
source ||
635+
!_.isEqual(previousQueryMetadataDict, queryMetadataDict)
636+
) {
592637
await (this as RPCPeer<ClientRPCDefinition>).call('sync', data, source);
593638
}
594639
}
595640

596641
private async request(refs: SyncableRef[]): Promise<void> {
597642
let loadedKeySet = this.loadedKeySet;
598643
let sanitizedFieldNamesMap = this.sanitizedFieldNamesMap;
644+
let context = this.context;
599645

600646
let syncables = await this.server.loadSyncablesByRefs(
601647
this.group,
602-
this.context,
648+
context,
603649
refs,
604650
{
605651
loadedKeySet,
606652
},
607653
);
608654

609655
syncables = filterReadableSyncables(
610-
this.context,
656+
context,
611657
this.syncableAdapter,
612658
syncables,
613659
true,
@@ -627,6 +673,7 @@ export class Connection<
627673
syncables,
628674
removals: [],
629675
updates: [],
676+
queryMetadata: context.queryMetadataDict,
630677
});
631678
}
632679
}

server/src/library/server/server-adapter.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ViewQueryDictToResolvedViewQueryDict,
77
} from '@syncable/core';
88
import {Observable} from 'rxjs';
9+
import {Dict} from 'tslang';
910

1011
import {Connection} from '../connection';
1112

@@ -40,6 +41,18 @@ export interface IServerAdapter<
4041
processor: QueuedChangeProcessor,
4142
): Promise<void>;
4243

44+
resolveQueryToContextDependencyRefsDict(
45+
context: TGenericParams['context'],
46+
): Promise<Dict<SyncableRef[]>>;
47+
48+
preloadQueryMetadata<
49+
TViewQueryName extends keyof TGenericParams['context']['queryMetadataDict']
50+
>(
51+
group: string,
52+
context: TGenericParams['context'],
53+
viewQueryName: TViewQueryName,
54+
): Promise<TGenericParams['context']['queryMetadataDict'][TViewQueryName]>;
55+
4356
loadSyncablesByQuery(
4457
group: string,
4558
context: TGenericParams['context'],

0 commit comments

Comments
 (0)