Browse Source

feat(core): Use batching when updating collection filters

Solves server becoming unresponsive when updating a collection affecting a large number of variants
Michael Bromley 6 years ago
parent
commit
325b807d56

+ 12 - 4
packages/core/src/plugin/default-search-plugin/fulltext-search.service.ts

@@ -174,12 +174,20 @@ export class FulltextSearchService implements SearchService {
 
     async updateVariantsById(ctx: RequestContext, ids: ID[]) {
         if (ids.length) {
-            this.taskQueue.push(async () => {
-                const updatedVariants = await this.connection.getRepository(ProductVariant).findByIds(ids, {
+            const BATCH_SIZE = 100;
+            const batches = Math.ceil(ids.length / BATCH_SIZE);
+            for (let i = 0; i < batches; i++) {
+                const begin = i * BATCH_SIZE;
+                const end = begin + BATCH_SIZE;
+                Logger.verbose(`Updating ids from index ${begin} to ${end}`);
+                const batch = ids.slice(begin, end);
+                const updatedVariants = await this.connection.getRepository(ProductVariant).findByIds(batch, {
                     relations: this.variantRelations,
                 });
-                await this.saveSearchIndexItems(ctx, updatedVariants);
-            });
+                this.taskQueue.push(async () => {
+                    await this.saveSearchIndexItems(ctx, updatedVariants);
+                });
+            }
         }
     }
 

+ 7 - 11
packages/core/src/service/services/collection.service.ts

@@ -1,12 +1,6 @@
 import { OnModuleInit } from '@nestjs/common';
 import { InjectConnection } from '@nestjs/typeorm';
-import {
-    CollectionBreadcrumb,
-    ConfigurableOperation,
-    CreateCollectionInput,
-    MoveCollectionInput,
-    UpdateCollectionInput,
-} from '@vendure/common/lib/generated-types';
+import { ConfigurableOperation, CreateCollectionInput, MoveCollectionInput, UpdateCollectionInput } from '@vendure/common/lib/generated-types';
 import { pick } from '@vendure/common/lib/pick';
 import { ROOT_COLLECTION_NAME } from '@vendure/common/lib/shared-constants';
 import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
@@ -58,9 +52,11 @@ export class CollectionService implements OnModuleInit {
             });
             for (const collection of collections) {
                 const affectedVariantIds = await this.applyCollectionFilters(collection);
-                this.eventBus.publish(
-                    new CollectionModificationEvent(event.ctx, collection, affectedVariantIds),
-                );
+                if (affectedVariantIds.length) {
+                    this.eventBus.publish(
+                        new CollectionModificationEvent(event.ctx, collection, affectedVariantIds),
+                    );
+                }
             }
         });
     }
@@ -349,8 +345,8 @@ export class CollectionService implements OnModuleInit {
             ...ancestorFilters,
             ...(collection.filters || []),
         ]);
-        await this.connection.getRepository(Collection).save(collection);
         const postIds = collection.productVariants.map(v => v.id);
+        await this.connection.getRepository(Collection).save(collection, { chunk: Math.ceil(collection.productVariants.length / 500) });
 
         const preIdsSet = new Set(preIds);
         const postIdsSet = new Set(postIds);