Skip to content

Commit 8084aa1

Browse files
committed
fix live query updates
1 parent eed2b33 commit 8084aa1

File tree

2 files changed

+61
-58
lines changed

2 files changed

+61
-58
lines changed

apps/events/src/components/users.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export const Users = () => {
1111
const createEntityNew = useCreateEntity(User);
1212
const [newUserName, setNewUserName] = useState('');
1313

14-
console.log(users);
15-
1614
if (!spaceReady) {
1715
return <div>Loading space...</div>;
1816
}
@@ -24,9 +22,7 @@ export const Users = () => {
2422
<Input type="text" value={newUserName} onChange={(e) => setNewUserName(e.target.value)} />
2523
<Button
2624
onClick={() => {
27-
// createEntity({ name: newUserName });
28-
const user = createEntityNew({ name: newUserName });
29-
console.log(user);
25+
createEntityNew({ name: newUserName });
3026
setNewUserName('');
3127
}}
3228
>

packages/hypergraph/src/entity/findMany.ts

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as SchemaAST from 'effect/SchemaAST';
55
import { TypeIdsSymbol } from '../constants.js';
66
import { deepMerge } from '../utils/internal/deep-merge.js';
77
import { canonicalize } from '../utils/jsc.js';
8-
import { type DecodedEntitiesCacheEntry, decodedEntitiesCache, type QueryEntry } from './decodedEntitiesCache.js';
8+
import { decodedEntitiesCache, type DecodedEntitiesCacheEntry, type QueryEntry } from './decodedEntitiesCache.js';
99
import { decodeFromGrc20Json } from './entity.js';
1010
import { entityRelationParentsMap } from './entityRelationParentsMap.js';
1111
import { getEntityRelations } from './getEntityRelations.js';
@@ -72,9 +72,11 @@ const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
7272
for (const entityId of changedEntities) {
7373
const entity = doc.entities?.[entityId];
7474
if (!hasValidTypesProperty(entity)) continue;
75-
for (const typeName of entity['@@types@@']) {
76-
if (typeof typeName !== 'string') continue;
77-
const cacheEntry = decodedEntitiesCache.get(typeName);
75+
for (const typeId of entity['@@types@@']) {
76+
console.log('typeId', typeId);
77+
if (typeof typeId !== 'string') continue;
78+
const cacheEntry = decodedEntitiesCache.get(typeId);
79+
console.log('cacheEntry', cacheEntry);
7880
if (!cacheEntry) continue;
7981

8082
let includeFromAllQueries = {};
@@ -101,6 +103,8 @@ const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
101103
console.error('error', error);
102104
}
103105

106+
console.log('decoded', decoded);
107+
104108
if (oldDecodedEntry) {
105109
// collect all the Ids for relation entries in the `oldDecodedEntry`
106110
const deletedRelationIds = new Set<string>();
@@ -144,11 +148,11 @@ const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
144148
}
145149

146150
for (const [queryKey, query] of cacheEntry.queries) {
147-
touchedQueries.add([typeName, queryKey]);
151+
touchedQueries.add([typeId, queryKey]);
148152
query.isInvalidated = true;
149153
}
150154

151-
entityTypes.add(typeName);
155+
entityTypes.add(typeId);
152156

153157
// gather all the decodedEntitiesCacheEntries that have a relation to this entity to
154158
// invoke their query listeners below
@@ -165,17 +169,17 @@ const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
165169

166170
// loop over all deleted entities and remove them from the cache
167171
for (const entityId of deletedEntities) {
168-
for (const [affectedTypeName, cacheEntry] of decodedEntitiesCache) {
172+
for (const [affectedTypeId, cacheEntry] of decodedEntitiesCache) {
169173
if (cacheEntry.entities.has(entityId)) {
170-
entityTypes.add(affectedTypeName);
174+
entityTypes.add(affectedTypeId);
171175
cacheEntry.entities.delete(entityId);
172176

173177
for (const [queryKey, query] of cacheEntry.queries) {
174178
// find the entity in the query and remove it using splice
175179
const index = query.data.findIndex((entity) => entity.id === entityId);
176180
if (index !== -1) {
177181
query.data.splice(index, 1);
178-
touchedQueries.add([affectedTypeName, queryKey]);
182+
touchedQueries.add([affectedTypeId, queryKey]);
179183
}
180184
}
181185
}
@@ -195,8 +199,8 @@ const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
195199
}
196200

197201
// update the queries affected queries
198-
for (const [typeName, queryKey] of touchedQueries) {
199-
const cacheEntry = decodedEntitiesCache.get(typeName);
202+
for (const [typeId, queryKey] of touchedQueries) {
203+
const cacheEntry = decodedEntitiesCache.get(typeId);
200204
if (!cacheEntry) continue;
201205

202206
const query = cacheEntry.queries.get(queryKey);
@@ -206,8 +210,8 @@ const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
206210
}
207211

208212
// invoke all the listeners per type
209-
for (const typeName of entityTypes) {
210-
const cacheEntry = decodedEntitiesCache.get(typeName);
213+
for (const typeId of entityTypes) {
214+
const cacheEntry = decodedEntitiesCache.get(typeId);
211215
if (!cacheEntry) continue;
212216

213217
for (const query of cacheEntry.queries.values()) {
@@ -246,7 +250,7 @@ export function findMany<const S extends Schema.Schema.AnyNoContext>(
246250
filter: EntityFilter<Schema.Schema.Type<S>> | undefined,
247251
include: { [K in keyof Schema.Schema.Type<S>]?: Record<string, Record<string, never>> } | undefined,
248252
): { entities: Readonly<Array<Entity<S>>>; corruptEntityIds: Readonly<Array<string>> } {
249-
const typeIds = SchemaAST.getAnnotation<string[]>(TypeIdsSymbol)(type.ast as SchemaAST.TypeLiteral).pipe(
253+
const typeId = SchemaAST.getAnnotation<string[]>(TypeIdsSymbol)(type.ast as SchemaAST.TypeLiteral).pipe(
250254
Option.getOrElse(() => []),
251255
);
252256

@@ -363,7 +367,7 @@ export function findMany<const S extends Schema.Schema.AnyNoContext>(
363367
const entity = entities[id];
364368
if (
365369
hasValidTypesProperty(entity) &&
366-
typeIds.every((typeId) => {
370+
typeId.every((typeId) => {
367371
return entity['@@types@@'].includes(typeId);
368372
})
369373
) {
@@ -421,7 +425,7 @@ export function subscribeToFindMany<const S extends Schema.Schema.AnyNoContext>(
421425
);
422426

423427
const getEntities = () => {
424-
const cacheEntry = decodedEntitiesCache.get(canonicalize(typeIds));
428+
const cacheEntry = decodedEntitiesCache.get(typeIds[0]);
425429
if (!cacheEntry) return stableEmptyArray;
426430

427431
const query = cacheEntry.queries.get(queryKey);
@@ -446,47 +450,50 @@ export function subscribeToFindMany<const S extends Schema.Schema.AnyNoContext>(
446450
};
447451

448452
const subscribe = (callback: () => void) => {
449-
let cacheEntry = decodedEntitiesCache.get(canonicalize(typeIds));
450-
451-
if (!cacheEntry) {
452-
const entitiesMap = new Map();
453-
const queries = new Map<string, QueryEntry>();
454-
455-
queries.set(queryKey, {
456-
data: [],
457-
listeners: [],
458-
isInvalidated: true,
459-
include: include ?? {},
460-
});
461-
462-
cacheEntry = {
463-
type,
464-
entities: entitiesMap,
465-
queries,
466-
isInvalidated: true,
467-
};
468-
469-
decodedEntitiesCache.set(canonicalize(typeIds), cacheEntry);
470-
}
453+
if (typeIds.length > 1) {
454+
console.error('Schema with multiple type ids is not supported', typeIds);
455+
} else {
456+
let cacheEntry = decodedEntitiesCache.get(typeIds[0]);
457+
if (!cacheEntry) {
458+
const entitiesMap = new Map();
459+
const queries = new Map<string, QueryEntry>();
460+
461+
queries.set(queryKey, {
462+
data: [],
463+
listeners: [],
464+
isInvalidated: true,
465+
include: include ?? {},
466+
});
467+
468+
cacheEntry = {
469+
type,
470+
entities: entitiesMap,
471+
queries,
472+
isInvalidated: true,
473+
};
471474

472-
let query = cacheEntry.queries.get(queryKey);
473-
if (!query) {
474-
query = {
475-
data: [],
476-
listeners: [],
477-
isInvalidated: true,
478-
include: include ?? {},
479-
};
480-
// we just set up the query and expect it to correctly set itself up in findMany
481-
cacheEntry.queries.set(queryKey, query);
482-
}
475+
decodedEntitiesCache.set(typeIds[0], cacheEntry);
476+
}
483477

484-
if (query?.listeners) {
485-
query.listeners.push(callback);
478+
let query = cacheEntry.queries.get(queryKey);
479+
if (!query) {
480+
query = {
481+
data: [],
482+
listeners: [],
483+
isInvalidated: true,
484+
include: include ?? {},
485+
};
486+
// we just set up the query and expect it to correctly set itself up in findMany
487+
cacheEntry.queries.set(queryKey, query);
488+
}
489+
490+
if (query?.listeners) {
491+
query.listeners.push(callback);
492+
}
486493
}
487494

488495
return () => {
489-
const cacheEntry = decodedEntitiesCache.get(canonicalize(typeIds));
496+
const cacheEntry = decodedEntitiesCache.get(typeIds[0]);
490497
if (cacheEntry) {
491498
// first cleanup the queries
492499
const query = cacheEntry.queries.get(queryKey);
@@ -508,7 +515,7 @@ export function subscribeToFindMany<const S extends Schema.Schema.AnyNoContext>(
508515
entityRelationParentsMap.delete(key);
509516
}
510517
});
511-
decodedEntitiesCache.delete(canonicalize(typeIds));
518+
decodedEntitiesCache.delete(typeIds[0]);
512519
}
513520
}
514521

0 commit comments

Comments
 (0)