|
@@ -4,151 +4,7 @@ import { generateUuid } from "@common/utils/generateUuid";
|
|
|
import { forEachIn } from "@common/utils/forEachIn";
|
|
|
import { useWebsocketStore } from "./websocket";
|
|
|
import Model from "@/Model";
|
|
|
-
|
|
|
-class DeferredPromise<T = any> {
|
|
|
- promise: Promise<T>;
|
|
|
-
|
|
|
- reject;
|
|
|
-
|
|
|
- resolve;
|
|
|
-
|
|
|
-
|
|
|
- constructor() {
|
|
|
- this.promise = new Promise<T>((resolve, reject) => {
|
|
|
- this.reject = reject;
|
|
|
- this.resolve = resolve;
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-interface ModelFetcherRequest {
|
|
|
- promise: DeferredPromise;
|
|
|
- payload: {
|
|
|
- modelName: string;
|
|
|
- modelIds: string[];
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Class used for fetching models in bulk, every 25ms max, per model type
|
|
|
- * So if we tried to fetch 100 different minifiedUser models separately, it would do only 1 request to fetch the models, not 100 separate ones
|
|
|
- */
|
|
|
-class ModelFetcher {
|
|
|
- private static requestsQueued: ModelFetcherRequest[] = [];
|
|
|
-
|
|
|
- private static timeoutActive = false;
|
|
|
-
|
|
|
- private static responseCache = {};
|
|
|
-
|
|
|
- private static fetch() {
|
|
|
-
|
|
|
- if (!this.timeoutActive) this.timeoutActive = true;
|
|
|
- else return;
|
|
|
-
|
|
|
- setTimeout(() => {
|
|
|
-
|
|
|
- this.timeoutActive = false;
|
|
|
-
|
|
|
- const requests = this.requestsQueued;
|
|
|
- this.requestsQueued = [];
|
|
|
-
|
|
|
-
|
|
|
- const requestsPerModel = {};
|
|
|
- requests.forEach(request => {
|
|
|
- const { modelName } = request.payload;
|
|
|
- if (!Array.isArray(requestsPerModel[modelName]))
|
|
|
- requestsPerModel[modelName] = [];
|
|
|
- requestsPerModel[modelName].push(request);
|
|
|
- });
|
|
|
-
|
|
|
- const modelNames = Object.keys(requestsPerModel);
|
|
|
-
|
|
|
- const { runJob } = useWebsocketStore();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- forEachIn(modelNames, async modelName => {
|
|
|
-
|
|
|
- let cachedModelIds = Object.keys(this.responseCache[modelName]);
|
|
|
-
|
|
|
-
|
|
|
- const modelIds = Array.from(
|
|
|
- new Set(
|
|
|
- requestsPerModel[modelName].flatMap(
|
|
|
- request => request.payload.modelIds
|
|
|
- )
|
|
|
- )
|
|
|
- ).filter((modelId: string) => !cachedModelIds.includes(modelId));
|
|
|
-
|
|
|
-
|
|
|
- if (modelIds.length > 0) {
|
|
|
- console.log(`Requesting model ids`, modelName, modelIds);
|
|
|
- const result = await runJob(`data.${modelName}.findManyById`, {
|
|
|
- _ids: modelIds
|
|
|
- }) as any[];
|
|
|
-
|
|
|
-
|
|
|
- modelIds.forEach(modelId => {
|
|
|
- const model = result.find(model => model._id === modelId);
|
|
|
- console.log(`Caching ${modelName}.${modelId}`, model);
|
|
|
- this.responseCache[modelName][modelId] = model;
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- const requests = requestsPerModel[modelName];
|
|
|
-
|
|
|
- requests.forEach(request => {
|
|
|
- const { payload, promise } = request;
|
|
|
- const { modelIds } = payload;
|
|
|
- const models = modelIds.map(modelId => this.responseCache[modelName][modelId]).filter(model => model);
|
|
|
- promise.resolve(models);
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- const queuedModelIds = Array.from(new Set(this.requestsQueued.filter(request => request.payload.modelName).flatMap(request => request.payload.modelIds)));
|
|
|
-
|
|
|
- cachedModelIds = Object.keys(this.responseCache[modelName]);
|
|
|
-
|
|
|
- const cachedModelIdsToDelete = cachedModelIds.filter(cachedModelId => !queuedModelIds.includes(cachedModelId));
|
|
|
- console.log(`Queued model ids`, modelName, queuedModelIds);
|
|
|
- console.log(`Cached model ids`, modelName, cachedModelIds);
|
|
|
- console.log(`Cached model ids to delete`, modelName, cachedModelIdsToDelete);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- cachedModelIdsToDelete.forEach(cachedModelIdToDelete => {
|
|
|
- delete this.responseCache[modelName][cachedModelIdToDelete];
|
|
|
- });
|
|
|
- });
|
|
|
- }, 25);
|
|
|
- }
|
|
|
-
|
|
|
- public static fetchModelsByIds(modelName: string, modelIds: string[]) {
|
|
|
- this.responseCache[modelName] ??= {};
|
|
|
-
|
|
|
- return new Promise(resolve => {
|
|
|
- const promise = new DeferredPromise();
|
|
|
-
|
|
|
-
|
|
|
- promise.promise.then(result => {
|
|
|
- resolve(result);
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- this.requestsQueued.push({
|
|
|
- payload: {
|
|
|
- modelName,
|
|
|
- modelIds
|
|
|
- },
|
|
|
- promise
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- this.fetch();
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
+import { ModelFetcher } from "@/ModelFetcher";
|
|
|
|
|
|
|
|
|
* Pinia store for managing models
|
|
@@ -337,7 +193,9 @@ export const useModelStore = defineStore("model", () => {
|
|
|
|
|
|
if (existingModel) return existingModel;
|
|
|
|
|
|
- const [model] = await ModelFetcher.fetchModelsByIds(modelName, [modelId]) as unknown[];
|
|
|
+ const [model] = (await ModelFetcher.fetchModelsByIds(modelName, [
|
|
|
+ modelId
|
|
|
+ ])) as unknown[];
|
|
|
|
|
|
return model;
|
|
|
};
|
|
@@ -360,7 +218,10 @@ export const useModelStore = defineStore("model", () => {
|
|
|
|
|
|
let fetchedModels = [];
|
|
|
if (missingModelIds.length > 0)
|
|
|
- fetchedModels = await ModelFetcher.fetchModelsByIds(modelName, missingModelIds) as unknown[];
|
|
|
+ fetchedModels = (await ModelFetcher.fetchModelsByIds(
|
|
|
+ modelName,
|
|
|
+ missingModelIds
|
|
|
+ )) as unknown[];
|
|
|
|
|
|
const allModels = existingModels.concat(fetchedModels);
|
|
|
|