3215 Fix 1n issue for products->designer and printProduct->interiors query (#140)
This commit is contained in:
@@ -3,10 +3,16 @@ import { Designer } from '../types/designer-types';
|
||||
import { DataSourceOptions, Maybe } from '../types/types';
|
||||
import { MINUTE } from './utils';
|
||||
import { ScopeAccess, Scopes } from '../cognito/access-control';
|
||||
import DataLoader from 'dataloader';
|
||||
|
||||
export class DesignerAPI extends BaseSQLDataSource {
|
||||
private loader: DataLoader<number, Designer>;
|
||||
|
||||
constructor(options: DataSourceOptions, config) {
|
||||
super(options, config);
|
||||
this.loader = new DataLoader((keys: number[]) =>
|
||||
this.getDesigners(undefined, keys),
|
||||
);
|
||||
}
|
||||
|
||||
async getDesignerById(id: number): Promise<Designer> {
|
||||
@@ -14,22 +20,7 @@ export class DesignerAPI extends BaseSQLDataSource {
|
||||
Scopes.DESIGNERS_READ,
|
||||
Scopes.DESIGNERS_PUBLIC_READ,
|
||||
]);
|
||||
return (
|
||||
this.knex
|
||||
.select('*')
|
||||
.from('designers')
|
||||
.where('designerid', id)
|
||||
.first()
|
||||
// @ts-ignore
|
||||
.cache(MINUTE)
|
||||
.then((row) => {
|
||||
return {
|
||||
...row,
|
||||
id: row.designerid,
|
||||
excludeFromSearch: !row.visibleSearch || !row.visibleDesignerpage,
|
||||
};
|
||||
})
|
||||
);
|
||||
return this.loader.load(id);
|
||||
}
|
||||
|
||||
async searchDesigners(name: string): Promise<Array<Designer>> {
|
||||
@@ -49,15 +40,28 @@ export class DesignerAPI extends BaseSQLDataSource {
|
||||
});
|
||||
}
|
||||
|
||||
async getDesigners(limit: Maybe<number>): Promise<Array<Designer>> {
|
||||
async getDesigners(
|
||||
limit: number = 5000,
|
||||
ids?: number[],
|
||||
): Promise<Array<Designer>> {
|
||||
ScopeAccess.validate(this.user).all([Scopes.DESIGNERS_READ]);
|
||||
limit = limit ?? 5000;
|
||||
return (
|
||||
this.knex
|
||||
.select('*')
|
||||
.select(
|
||||
'designerid',
|
||||
'name',
|
||||
'path',
|
||||
'visible_search',
|
||||
'visible_designerpage',
|
||||
)
|
||||
.from('designers')
|
||||
.limit(limit)
|
||||
.orderBy('name')
|
||||
.modify((queryBuilder) => {
|
||||
if (ids) {
|
||||
queryBuilder.whereIn('designerid', ids);
|
||||
}
|
||||
})
|
||||
// @ts-ignore
|
||||
.cache(MINUTE)
|
||||
.then((rows) => {
|
||||
|
||||
@@ -12,8 +12,13 @@ import { moveS3File } from '../aws/s3';
|
||||
import { BaseSQLDataSource } from './BaseSQLDataSource';
|
||||
import { GraphQLError } from 'graphql';
|
||||
import { ScopeAccess, Scopes } from '../cognito/access-control';
|
||||
import DataLoader from 'dataloader';
|
||||
|
||||
interface InteriorWithPrintId extends Interior {
|
||||
printId: number;
|
||||
}
|
||||
export class InteriorAPI extends BaseSQLDataSource {
|
||||
private printProductInteriorsLoader: DataLoader<number, Interior[]>;
|
||||
imageServerApi: ImageServerApi;
|
||||
|
||||
constructor(
|
||||
@@ -23,6 +28,19 @@ export class InteriorAPI extends BaseSQLDataSource {
|
||||
) {
|
||||
super(options, config);
|
||||
this.imageServerApi = imageServerApi;
|
||||
this.printProductInteriorsLoader = new DataLoader(async (ids: number[]) => {
|
||||
const results = await this.getPrintProductInteriorsBatch(ids);
|
||||
const indexed = {} as Record<string, InteriorWithPrintId[]>;
|
||||
results.forEach((interiorRow) => {
|
||||
if (!indexed[interiorRow.printId]) {
|
||||
indexed[interiorRow.printId] = [interiorRow];
|
||||
} else {
|
||||
indexed[interiorRow.printId].push(interiorRow);
|
||||
}
|
||||
});
|
||||
const output = ids.map((id) => indexed[id] ?? []);
|
||||
return output;
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
@@ -136,7 +154,13 @@ export class InteriorAPI extends BaseSQLDataSource {
|
||||
return allInteriors;
|
||||
}
|
||||
|
||||
async getPrintProductInteriors(printId: number): Promise<Array<Interior>> {
|
||||
async getPrintProductInteriors(printId: number): Promise<Interior[]> {
|
||||
return this.printProductInteriorsLoader.load(printId);
|
||||
}
|
||||
|
||||
async getPrintProductInteriorsBatch(
|
||||
printIds: number[],
|
||||
): Promise<InteriorWithPrintId[]> {
|
||||
ScopeAccess.validate(this.user).all([
|
||||
Scopes.INTERIORS_READ,
|
||||
Scopes.PRODUCTS_READ,
|
||||
@@ -145,7 +169,7 @@ export class InteriorAPI extends BaseSQLDataSource {
|
||||
.select('*')
|
||||
.from('v_interior_image_urls')
|
||||
.orderBy('position')
|
||||
.where('print_id', printId)
|
||||
.whereIn('print_id', printIds)
|
||||
.then((rows) => {
|
||||
return rows.map((row) => {
|
||||
const res = {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { moveS3File } from '../aws/s3';
|
||||
import { DesignerAPI } from '../datasources/designer-api';
|
||||
import { PrintProductDefaultsAPI } from '../datasources/printproduct-defaults-api';
|
||||
import { PrintProductDefaults } from '../types/printproduct-defaults-types';
|
||||
import { GraphQLError } from 'graphql';
|
||||
|
||||
const ProductBlacklist = {
|
||||
async market(parent, _args, { dataSources }) {
|
||||
@@ -68,6 +69,11 @@ async function getProductsResult(
|
||||
input: ProductsFilterInput,
|
||||
{ dataSources },
|
||||
): Promise<ProductListResult> {
|
||||
if (input.pagination.limit > 5000) {
|
||||
throw new GraphQLError('Pagination limit cannot exceed 5000', {
|
||||
extensions: { code: 'BAD_USER_INPUT' },
|
||||
});
|
||||
}
|
||||
const total = (<ProductAPI>dataSources.productApi).getProductsTotal(input);
|
||||
const items = (<ProductAPI>dataSources.productApi).getProducts(input);
|
||||
const offset = input.pagination?.offset ?? 0;
|
||||
|
||||
Reference in New Issue
Block a user