Skip to content

Commit 5c94cea

Browse files
committed
properly cleanup the entity cache and entityRelationParentsMap
1 parent db8ef62 commit 5c94cea

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

packages/hypergraph/src/entity/findMany.ts

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -281,39 +281,41 @@ export function subscribeToFindMany<const S extends AnyNoContext>(
281281
}
282282
}
283283

284-
for (const type of allTypes) {
285-
// TODO: what's the right way to get the name of the type?
286-
// @ts-expect-error name is defined
287-
const typeName = type.name;
288-
const entities = findMany(handle, type);
289-
290-
if (!decodedEntitiesCache.has(typeName)) {
291-
const entitiesMap = new Map();
292-
const relationParent = new Map();
293-
for (const entity of entities) {
294-
entitiesMap.set(entity.id, entity);
295-
relationParent.set(entity.id, new Map());
296-
}
297-
298-
decodedEntitiesCache.set(typeName, {
299-
decoder: decode,
300-
type,
301-
entities: entitiesMap,
302-
queries: new Map(),
303-
isInvalidated: false,
304-
});
305-
}
306-
}
307-
308284
const subscribe = (callback: () => void) => {
309285
const query = decodedEntitiesCache.get(typeName)?.queries.get(queryKey);
310286
if (query?.listeners) {
311287
query.listeners.push(callback);
312288
}
289+
313290
return () => {
314-
const query = decodedEntitiesCache.get(typeName)?.queries.get(queryKey);
315-
if (query?.listeners) {
316-
query.listeners = query?.listeners?.filter((cachedListener) => cachedListener !== callback);
291+
const cacheEntry = decodedEntitiesCache.get(typeName);
292+
if (cacheEntry) {
293+
// first cleanup the queries
294+
const query = cacheEntry.queries.get(queryKey);
295+
if (query) {
296+
query.listeners = query?.listeners?.filter((cachedListener) => cachedListener !== callback);
297+
if (query.listeners.length === 0) {
298+
cacheEntry.queries.delete(queryKey);
299+
}
300+
}
301+
// if the last query is removed, cleanup the entityRelationParentsMap and remove the decodedEntitiesCacheEntry
302+
if (cacheEntry.queries.size === 0) {
303+
entityRelationParentsMap.forEach((relationCacheEntries, key) => {
304+
for (const relationCacheEntry of relationCacheEntries) {
305+
if (relationCacheEntry === cacheEntry) {
306+
entityRelationParentsMap.set(
307+
key,
308+
relationCacheEntries.filter((entry) => entry !== cacheEntry),
309+
);
310+
}
311+
}
312+
const updatedRelationCacheEntries = entityRelationParentsMap.get(key);
313+
if (updatedRelationCacheEntries && updatedRelationCacheEntries.length === 0) {
314+
entityRelationParentsMap.delete(key);
315+
}
316+
});
317+
decodedEntitiesCache.delete(typeName);
318+
}
317319
}
318320

319321
documentChangeListener.subscribedQueriesCount--;

0 commit comments

Comments
 (0)