Browse Source

refactor: Use subscribeMany when registering models

Owen Diffey 1 year ago
parent
commit
8bbbbce1f5
1 changed files with 58 additions and 21 deletions
  1. 58 21
      frontend/src/stores/model.ts

+ 58 - 21
frontend/src/stores/model.ts

@@ -6,7 +6,8 @@ import { useWebsocketStore } from "./websocket";
 import Model from "@/Model";
 
 export const useModelStore = defineStore("model", () => {
-	const { runJob, subscribe, unsubscribe } = useWebsocketStore();
+	const { runJob, subscribe, subscribeMany, unsubscribe } =
+		useWebsocketStore();
 
 	const models = ref([]);
 	const permissions = ref({});
@@ -178,38 +179,74 @@ export const useModelStore = defineStore("model", () => {
 	const registerModels = async (
 		docs,
 		relations?: Record<string, string | string[]>
-	) =>
-		forEachIn(Array.isArray(docs) ? docs : [docs], async _doc => {
-			const existingRef = models.value.find(
-				model => model._id === _doc._id
-			);
+	) => {
+		const documents = Array.isArray(docs) ? docs : [docs];
 
-			const docRef = existingRef ?? reactive(new Model(_doc));
+		const existingsRefs = documents.filter(document =>
+			models.value.find(
+				model =>
+					model._id === document._id && model._name === document._name
+			)
+		);
 
-			docRef.addUse();
+		await forEachIn(existingsRefs, async model => {
+			model.addUse();
 
-			if (existingRef) return docRef;
+			if (relations && relations[model._name])
+				await model.loadRelations(relations[model._name]);
+		});
 
-			if (relations && relations[docRef._name])
-				await docRef.loadRelations(relations[docRef._name]);
+		if (documents.length === existingsRefs.length) return existingsRefs;
 
-			models.value.push(docRef);
+		const missingDocuments = documents.filter(
+			document =>
+				!loadedModelIds.value.includes(
+					`${document._name}.${document._id}`
+				)
+		);
 
-			const updatedUuid = await subscribe(
-				`model.${docRef._name}.updated.${_doc._id}`,
-				data => onUpdatedCallback(docRef._name, data)
-			);
+		const channels = Object.fromEntries(
+			missingDocuments.flatMap(document => [
+				[
+					`model.${document._name}.updated.${document._id}`,
+					data => onUpdatedCallback(document._name, data)
+				],
+				[
+					`model.${document._name}.deleted.${document._id}`,
+					data => onDeletedCallback(document._name, data)
+				]
+			])
+		);
+		const subscriptions = Object.entries(await subscribeMany(channels));
 
-			const deletedUuid = await subscribe(
-				`model.${docRef._name}.deleted.${_doc._id}`,
-				data => onDeletedCallback(docRef._name, data)
+		const newRefs = await forEachIn(missingDocuments, async document => {
+			const refSubscriptions = subscriptions.filter(([, { channel }]) =>
+				channel.endsWith(document._id)
 			);
+			const [updated] = refSubscriptions.find(([, { channel }]) =>
+				channel.includes("updated")
+			);
+			const [deleted] = refSubscriptions.find(([, { channel }]) =>
+				channel.includes("deleted")
+			);
+
+			if (!updated || !deleted) return null;
+
+			const model = reactive(new Model(document));
+			model.setSubscriptions(updated, deleted);
+			model.addUse();
 
-			docRef.setSubscriptions(updatedUuid, deletedUuid);
+			if (relations && relations[model._name])
+				await model.loadRelations(relations[model._name]);
 
-			return docRef;
+			return model;
 		});
 
+		models.value.push(...newRefs);
+
+		return existingsRefs.concat(newRefs);
+	};
+
 	const findById = async (modelName: string, _id) => {
 		const existingModel = models.value.find(model => model._id === _id);