|
@@ -11,6 +11,7 @@ import { ID } from '@vendure/common/lib/shared-types';
|
|
|
import { unique } from '@vendure/common/lib/unique';
|
|
import { unique } from '@vendure/common/lib/unique';
|
|
|
|
|
|
|
|
import { RequestContext } from '../../api/common/request-context';
|
|
import { RequestContext } from '../../api/common/request-context';
|
|
|
|
|
+import { createSelfRefreshingCache, SelfRefreshingCache } from '../../common/self-refreshing-cache';
|
|
|
import { assertFound } from '../../common/utils';
|
|
import { assertFound } from '../../common/utils';
|
|
|
import { Channel, TaxRate } from '../../entity';
|
|
import { Channel, TaxRate } from '../../entity';
|
|
|
import { Country } from '../../entity/country/country.entity';
|
|
import { Country } from '../../entity/country/country.entity';
|
|
@@ -24,15 +25,23 @@ export class ZoneService {
|
|
|
/**
|
|
/**
|
|
|
* We cache all Zones to avoid hitting the DB many times per request.
|
|
* We cache all Zones to avoid hitting the DB many times per request.
|
|
|
*/
|
|
*/
|
|
|
- private zones: Zone[] = [];
|
|
|
|
|
|
|
+ private zones: SelfRefreshingCache<Zone[]>;
|
|
|
constructor(private connection: TransactionalConnection) {}
|
|
constructor(private connection: TransactionalConnection) {}
|
|
|
|
|
|
|
|
- initZones() {
|
|
|
|
|
- return this.updateZonesCache();
|
|
|
|
|
|
|
+ async initZones() {
|
|
|
|
|
+ this.zones = await createSelfRefreshingCache({
|
|
|
|
|
+ name: 'ZoneService.zones',
|
|
|
|
|
+ ttl: 10000,
|
|
|
|
|
+ refreshFn: () =>
|
|
|
|
|
+ this.connection.getRepository(Zone).find({
|
|
|
|
|
+ relations: ['members'],
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- findAll(ctx: RequestContext): Zone[] {
|
|
|
|
|
- return this.zones.map(zone => {
|
|
|
|
|
|
|
+ async findAll(ctx: RequestContext): Promise<Zone[]> {
|
|
|
|
|
+ const zones = await this.zones.value();
|
|
|
|
|
+ return zones.map(zone => {
|
|
|
zone.members = zone.members.map(country => translateDeep(country, ctx.languageCode));
|
|
zone.members = zone.members.map(country => translateDeep(country, ctx.languageCode));
|
|
|
return zone;
|
|
return zone;
|
|
|
});
|
|
});
|
|
@@ -58,7 +67,7 @@ export class ZoneService {
|
|
|
zone.members = await this.getCountriesFromIds(ctx, input.memberIds);
|
|
zone.members = await this.getCountriesFromIds(ctx, input.memberIds);
|
|
|
}
|
|
}
|
|
|
const newZone = await this.connection.getRepository(ctx, Zone).save(zone);
|
|
const newZone = await this.connection.getRepository(ctx, Zone).save(zone);
|
|
|
- await this.updateZonesCache(ctx);
|
|
|
|
|
|
|
+ await this.zones.refresh();
|
|
|
return assertFound(this.findOne(ctx, newZone.id));
|
|
return assertFound(this.findOne(ctx, newZone.id));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -66,7 +75,7 @@ export class ZoneService {
|
|
|
const zone = await this.connection.getEntityOrThrow(ctx, Zone, input.id);
|
|
const zone = await this.connection.getEntityOrThrow(ctx, Zone, input.id);
|
|
|
const updatedZone = patchEntity(zone, input);
|
|
const updatedZone = patchEntity(zone, input);
|
|
|
await this.connection.getRepository(ctx, Zone).save(updatedZone, { reload: false });
|
|
await this.connection.getRepository(ctx, Zone).save(updatedZone, { reload: false });
|
|
|
- await this.updateZonesCache(ctx);
|
|
|
|
|
|
|
+ await this.zones.refresh();
|
|
|
return assertFound(this.findOne(ctx, zone.id));
|
|
return assertFound(this.findOne(ctx, zone.id));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -104,7 +113,7 @@ export class ZoneService {
|
|
|
};
|
|
};
|
|
|
} else {
|
|
} else {
|
|
|
await this.connection.getRepository(ctx, Zone).remove(zone);
|
|
await this.connection.getRepository(ctx, Zone).remove(zone);
|
|
|
- await this.updateZonesCache(ctx);
|
|
|
|
|
|
|
+ await this.zones.refresh();
|
|
|
return {
|
|
return {
|
|
|
result: DeletionResult.DELETED,
|
|
result: DeletionResult.DELETED,
|
|
|
message: '',
|
|
message: '',
|
|
@@ -120,7 +129,7 @@ export class ZoneService {
|
|
|
const members = unique(zone.members.concat(countries), 'id');
|
|
const members = unique(zone.members.concat(countries), 'id');
|
|
|
zone.members = members;
|
|
zone.members = members;
|
|
|
await this.connection.getRepository(ctx, Zone).save(zone, { reload: false });
|
|
await this.connection.getRepository(ctx, Zone).save(zone, { reload: false });
|
|
|
- await this.updateZonesCache(ctx);
|
|
|
|
|
|
|
+ await this.zones.refresh();
|
|
|
return assertFound(this.findOne(ctx, zone.id));
|
|
return assertFound(this.findOne(ctx, zone.id));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -133,21 +142,11 @@ export class ZoneService {
|
|
|
});
|
|
});
|
|
|
zone.members = zone.members.filter(country => !input.memberIds.includes(country.id));
|
|
zone.members = zone.members.filter(country => !input.memberIds.includes(country.id));
|
|
|
await this.connection.getRepository(ctx, Zone).save(zone, { reload: false });
|
|
await this.connection.getRepository(ctx, Zone).save(zone, { reload: false });
|
|
|
- await this.updateZonesCache(ctx);
|
|
|
|
|
|
|
+ await this.zones.refresh();
|
|
|
return assertFound(this.findOne(ctx, zone.id));
|
|
return assertFound(this.findOne(ctx, zone.id));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private getCountriesFromIds(ctx: RequestContext, ids: ID[]): Promise<Country[]> {
|
|
private getCountriesFromIds(ctx: RequestContext, ids: ID[]): Promise<Country[]> {
|
|
|
return this.connection.getRepository(ctx, Country).findByIds(ids);
|
|
return this.connection.getRepository(ctx, Country).findByIds(ids);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * TODO: This is not good for multi-instance deployments. A better solution will
|
|
|
|
|
- * need to be found without adversely affecting performance.
|
|
|
|
|
- */
|
|
|
|
|
- async updateZonesCache(ctx?: RequestContext) {
|
|
|
|
|
- this.zones = await this.connection.getRepository(ctx, Zone).find({
|
|
|
|
|
- relations: ['members'],
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|