|
@@ -1,6 +1,7 @@
|
|
|
-import { Injectable } from '@nestjs/common';
|
|
|
|
|
|
|
+import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
|
|
|
import { ID } from '@vendure/common/lib/shared-types';
|
|
import { ID } from '@vendure/common/lib/shared-types';
|
|
|
import { assertNever } from '@vendure/common/lib/shared-utils';
|
|
import { assertNever } from '@vendure/common/lib/shared-utils';
|
|
|
|
|
+import { Observable } from 'rxjs';
|
|
|
|
|
|
|
|
import { RequestContext } from '../../../api/common/request-context';
|
|
import { RequestContext } from '../../../api/common/request-context';
|
|
|
import { Logger } from '../../../config/logger/vendure-logger';
|
|
import { Logger } from '../../../config/logger/vendure-logger';
|
|
@@ -10,65 +11,50 @@ import { Product } from '../../../entity/product/product.entity';
|
|
|
import { Job } from '../../../job-queue/job';
|
|
import { Job } from '../../../job-queue/job';
|
|
|
import { JobQueue } from '../../../job-queue/job-queue';
|
|
import { JobQueue } from '../../../job-queue/job-queue';
|
|
|
import { JobQueueService } from '../../../job-queue/job-queue.service';
|
|
import { JobQueueService } from '../../../job-queue/job-queue.service';
|
|
|
-import { WorkerMessage } from '../../../worker/types';
|
|
|
|
|
-import { WorkerService } from '../../../worker/worker.service';
|
|
|
|
|
-import {
|
|
|
|
|
- AssignProductToChannelMessage,
|
|
|
|
|
- AssignVariantToChannelMessage,
|
|
|
|
|
- DeleteAssetMessage,
|
|
|
|
|
- DeleteProductMessage,
|
|
|
|
|
- DeleteVariantMessage,
|
|
|
|
|
- ReindexMessage,
|
|
|
|
|
- ReindexMessageResponse,
|
|
|
|
|
- RemoveProductFromChannelMessage,
|
|
|
|
|
- RemoveVariantFromChannelMessage,
|
|
|
|
|
- UpdateAssetMessage,
|
|
|
|
|
- UpdateIndexQueueJobData,
|
|
|
|
|
- UpdateProductMessage,
|
|
|
|
|
- UpdateVariantMessage,
|
|
|
|
|
- UpdateVariantsByIdMessage,
|
|
|
|
|
-} from '../types';
|
|
|
|
|
-
|
|
|
|
|
-let updateIndexQueue: JobQueue<UpdateIndexQueueJobData> | undefined;
|
|
|
|
|
|
|
+import { ReindexMessageResponse, UpdateIndexQueueJobData } from '../types';
|
|
|
|
|
+
|
|
|
|
|
+import { IndexerController } from './indexer.controller';
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* This service is responsible for messaging the {@link IndexerController} with search index updates.
|
|
* This service is responsible for messaging the {@link IndexerController} with search index updates.
|
|
|
*/
|
|
*/
|
|
|
@Injectable()
|
|
@Injectable()
|
|
|
-export class SearchIndexService {
|
|
|
|
|
- constructor(private workerService: WorkerService, private jobService: JobQueueService) {}
|
|
|
|
|
|
|
+export class SearchIndexService implements OnApplicationBootstrap {
|
|
|
|
|
+ private updateIndexQueue: JobQueue<UpdateIndexQueueJobData>;
|
|
|
|
|
+
|
|
|
|
|
+ constructor(private jobService: JobQueueService, private indexerController: IndexerController) {}
|
|
|
|
|
|
|
|
- initJobQueue() {
|
|
|
|
|
- updateIndexQueue = this.jobService.createQueue({
|
|
|
|
|
|
|
+ onApplicationBootstrap() {
|
|
|
|
|
+ this.updateIndexQueue = this.jobService.createQueue({
|
|
|
name: 'update-search-index',
|
|
name: 'update-search-index',
|
|
|
process: job => {
|
|
process: job => {
|
|
|
const data = job.data;
|
|
const data = job.data;
|
|
|
switch (data.type) {
|
|
switch (data.type) {
|
|
|
case 'reindex':
|
|
case 'reindex':
|
|
|
Logger.verbose(`sending ReindexMessage`);
|
|
Logger.verbose(`sending ReindexMessage`);
|
|
|
- return this.sendMessageWithProgress(job, new ReindexMessage(data));
|
|
|
|
|
|
|
+ return this.jobWithProgress(job, this.indexerController.reindex(data));
|
|
|
case 'update-product':
|
|
case 'update-product':
|
|
|
- return this.sendMessage(job, new UpdateProductMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.updateProduct(data);
|
|
|
case 'update-variants':
|
|
case 'update-variants':
|
|
|
- return this.sendMessage(job, new UpdateVariantMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.updateVariants(data);
|
|
|
case 'delete-product':
|
|
case 'delete-product':
|
|
|
- return this.sendMessage(job, new DeleteProductMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.deleteProduct(data);
|
|
|
case 'delete-variant':
|
|
case 'delete-variant':
|
|
|
- return this.sendMessage(job, new DeleteVariantMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.deleteVariant(data);
|
|
|
case 'update-variants-by-id':
|
|
case 'update-variants-by-id':
|
|
|
- return this.sendMessageWithProgress(job, new UpdateVariantsByIdMessage(data));
|
|
|
|
|
|
|
+ return this.jobWithProgress(job, this.indexerController.updateVariantsById(data));
|
|
|
case 'update-asset':
|
|
case 'update-asset':
|
|
|
- return this.sendMessage(job, new UpdateAssetMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.updateAsset(data);
|
|
|
case 'delete-asset':
|
|
case 'delete-asset':
|
|
|
- return this.sendMessage(job, new DeleteAssetMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.deleteAsset(data);
|
|
|
case 'assign-product-to-channel':
|
|
case 'assign-product-to-channel':
|
|
|
- return this.sendMessage(job, new AssignProductToChannelMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.assignProductToChannel(data);
|
|
|
case 'remove-product-from-channel':
|
|
case 'remove-product-from-channel':
|
|
|
- return this.sendMessage(job, new RemoveProductFromChannelMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.removeProductFromChannel(data);
|
|
|
case 'assign-variant-to-channel':
|
|
case 'assign-variant-to-channel':
|
|
|
- return this.sendMessage(job, new AssignVariantToChannelMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.assignVariantToChannel(data);
|
|
|
case 'remove-variant-from-channel':
|
|
case 'remove-variant-from-channel':
|
|
|
- return this.sendMessage(job, new RemoveVariantFromChannelMessage(data));
|
|
|
|
|
|
|
+ return this.indexerController.removeVariantFromChannel(data);
|
|
|
default:
|
|
default:
|
|
|
assertNever(data);
|
|
assertNever(data);
|
|
|
return Promise.resolve();
|
|
return Promise.resolve();
|
|
@@ -78,41 +64,41 @@ export class SearchIndexService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
reindex(ctx: RequestContext) {
|
|
reindex(ctx: RequestContext) {
|
|
|
- return this.addJobToQueue({ type: 'reindex', ctx: ctx.serialize() });
|
|
|
|
|
|
|
+ return this.updateIndexQueue.add({ type: 'reindex', ctx: ctx.serialize() });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
updateProduct(ctx: RequestContext, product: Product) {
|
|
updateProduct(ctx: RequestContext, product: Product) {
|
|
|
- this.addJobToQueue({ type: 'update-product', ctx: ctx.serialize(), productId: product.id });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'update-product', ctx: ctx.serialize(), productId: product.id });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
updateVariants(ctx: RequestContext, variants: ProductVariant[]) {
|
|
updateVariants(ctx: RequestContext, variants: ProductVariant[]) {
|
|
|
const variantIds = variants.map(v => v.id);
|
|
const variantIds = variants.map(v => v.id);
|
|
|
- this.addJobToQueue({ type: 'update-variants', ctx: ctx.serialize(), variantIds });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'update-variants', ctx: ctx.serialize(), variantIds });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
deleteProduct(ctx: RequestContext, product: Product) {
|
|
deleteProduct(ctx: RequestContext, product: Product) {
|
|
|
- this.addJobToQueue({ type: 'delete-product', ctx: ctx.serialize(), productId: product.id });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'delete-product', ctx: ctx.serialize(), productId: product.id });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
deleteVariant(ctx: RequestContext, variants: ProductVariant[]) {
|
|
deleteVariant(ctx: RequestContext, variants: ProductVariant[]) {
|
|
|
const variantIds = variants.map(v => v.id);
|
|
const variantIds = variants.map(v => v.id);
|
|
|
- this.addJobToQueue({ type: 'delete-variant', ctx: ctx.serialize(), variantIds });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'delete-variant', ctx: ctx.serialize(), variantIds });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
updateVariantsById(ctx: RequestContext, ids: ID[]) {
|
|
updateVariantsById(ctx: RequestContext, ids: ID[]) {
|
|
|
- this.addJobToQueue({ type: 'update-variants-by-id', ctx: ctx.serialize(), ids });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'update-variants-by-id', ctx: ctx.serialize(), ids });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
updateAsset(ctx: RequestContext, asset: Asset) {
|
|
updateAsset(ctx: RequestContext, asset: Asset) {
|
|
|
- this.addJobToQueue({ type: 'update-asset', ctx: ctx.serialize(), asset: asset as any });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'update-asset', ctx: ctx.serialize(), asset: asset as any });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
deleteAsset(ctx: RequestContext, asset: Asset) {
|
|
deleteAsset(ctx: RequestContext, asset: Asset) {
|
|
|
- this.addJobToQueue({ type: 'delete-asset', ctx: ctx.serialize(), asset: asset as any });
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({ type: 'delete-asset', ctx: ctx.serialize(), asset: asset as any });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
assignProductToChannel(ctx: RequestContext, productId: ID, channelId: ID) {
|
|
assignProductToChannel(ctx: RequestContext, productId: ID, channelId: ID) {
|
|
|
- this.addJobToQueue({
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({
|
|
|
type: 'assign-product-to-channel',
|
|
type: 'assign-product-to-channel',
|
|
|
ctx: ctx.serialize(),
|
|
ctx: ctx.serialize(),
|
|
|
productId,
|
|
productId,
|
|
@@ -121,7 +107,7 @@ export class SearchIndexService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
removeProductFromChannel(ctx: RequestContext, productId: ID, channelId: ID) {
|
|
removeProductFromChannel(ctx: RequestContext, productId: ID, channelId: ID) {
|
|
|
- this.addJobToQueue({
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({
|
|
|
type: 'remove-product-from-channel',
|
|
type: 'remove-product-from-channel',
|
|
|
ctx: ctx.serialize(),
|
|
ctx: ctx.serialize(),
|
|
|
productId,
|
|
productId,
|
|
@@ -130,7 +116,7 @@ export class SearchIndexService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
assignVariantToChannel(ctx: RequestContext, productVariantId: ID, channelId: ID) {
|
|
assignVariantToChannel(ctx: RequestContext, productVariantId: ID, channelId: ID) {
|
|
|
- this.addJobToQueue({
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({
|
|
|
type: 'assign-variant-to-channel',
|
|
type: 'assign-variant-to-channel',
|
|
|
ctx: ctx.serialize(),
|
|
ctx: ctx.serialize(),
|
|
|
productVariantId,
|
|
productVariantId,
|
|
@@ -139,7 +125,7 @@ export class SearchIndexService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
removeVariantFromChannel(ctx: RequestContext, productVariantId: ID, channelId: ID) {
|
|
removeVariantFromChannel(ctx: RequestContext, productVariantId: ID, channelId: ID) {
|
|
|
- this.addJobToQueue({
|
|
|
|
|
|
|
+ this.updateIndexQueue.add({
|
|
|
type: 'remove-variant-from-channel',
|
|
type: 'remove-variant-from-channel',
|
|
|
ctx: ctx.serialize(),
|
|
ctx: ctx.serialize(),
|
|
|
productVariantId,
|
|
productVariantId,
|
|
@@ -147,30 +133,15 @@ export class SearchIndexService {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private addJobToQueue(data: UpdateIndexQueueJobData) {
|
|
|
|
|
- if (updateIndexQueue) {
|
|
|
|
|
- return updateIndexQueue.add(data);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private sendMessage(job: Job<any>, message: WorkerMessage<any, any>): Promise<any> {
|
|
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
|
|
- this.workerService.send(message).subscribe({
|
|
|
|
|
- complete: () => resolve(),
|
|
|
|
|
- error: err => {
|
|
|
|
|
- Logger.error(err);
|
|
|
|
|
- reject(err);
|
|
|
|
|
- },
|
|
|
|
|
- });
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private sendMessageWithProgress(job: Job<any>, message: ReindexMessage | UpdateVariantsByIdMessage): Promise<any> {
|
|
|
|
|
|
|
+ private jobWithProgress(
|
|
|
|
|
+ job: Job<UpdateIndexQueueJobData>,
|
|
|
|
|
+ ob: Observable<ReindexMessageResponse>,
|
|
|
|
|
+ ): Promise<any> {
|
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
let total: number | undefined;
|
|
let total: number | undefined;
|
|
|
let duration = 0;
|
|
let duration = 0;
|
|
|
let completed = 0;
|
|
let completed = 0;
|
|
|
- this.workerService.send(message).subscribe({
|
|
|
|
|
|
|
+ ob.subscribe({
|
|
|
next: (response: ReindexMessageResponse) => {
|
|
next: (response: ReindexMessageResponse) => {
|
|
|
if (!total) {
|
|
if (!total) {
|
|
|
total = response.total;
|
|
total = response.total;
|