add cache interceptor for hot endpoints
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-06-04 17:04:28 +03:30
parent 0d619f313d
commit 7995ae2948
16 changed files with 165 additions and 19 deletions
@@ -19,6 +19,8 @@ import { RestId } from 'src/common/decorators';
import { Permission } from 'src/common/enums/permission.enum';
import { Permissions } from 'src/common/decorators/permissions.decorator';
import { API_HEADER_SLUG } from 'src/common/constants';
import { CacheResponse } from 'src/common/decorators/cache-response.decorator';
import { CacheKeyPrefixes } from 'src/common/constants/cache-keys.constant';
@ApiTags('category')
@Controller()
@@ -26,6 +28,7 @@ export class CategoryController {
constructor(private readonly categoryService: CategoryService) { }
@Get('public/categories/restaurant/:slug')
@CacheResponse({ keyPrefix: CacheKeyPrefixes.CATEGORIES_BY_RESTAURANT, params: ['slug'] })
@ApiOperation({ summary: 'Get all categories by restaurant slug' })
@ApiHeader(API_HEADER_SLUG)
@ApiParam({ name: 'slug', required: true, description: 'Restaurant Slug' })
@@ -19,6 +19,8 @@ import { OptionalAuthGuard } from 'src/modules/auth/guards/optinalAuth.guard';
import { API_HEADER_SLUG } from 'src/common/constants';
import { Permission } from 'src/common/enums/permission.enum';
import { Permissions } from 'src/common/decorators/permissions.decorator';
import { CacheResponse } from 'src/common/decorators/cache-response.decorator';
import { CacheKeyPrefixes } from 'src/common/constants/cache-keys.constant';
@ApiTags('foods')
@Controller()
@@ -26,6 +28,7 @@ export class FoodController {
constructor(private readonly foodsService: FoodService) { }
@Get('public/foods/restaurant/:slug')
@CacheResponse({ keyPrefix: CacheKeyPrefixes.FOODS_BY_RESTAURANT, params: ['slug'] })
@ApiOperation({ summary: 'Get all foods by restaurant slug' })
@ApiHeader(API_HEADER_SLUG)
@ApiParam({ name: 'slug', required: true, description: 'Restaurant Slug' })
@@ -8,6 +8,8 @@ import { Category } from '../entities/category.entity';
import { CategoryMessage, RestMessage } from 'src/common/enums/message.enum';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
import { RestaurantsService } from 'src/modules/restaurants/providers/restaurants.service';
import { CacheService } from 'src/modules/utils/cache.service';
import { CacheKeys } from 'src/common/constants/cache-keys.constant';
@Injectable()
export class CategoryService {
@@ -15,6 +17,7 @@ export class CategoryService {
private readonly categoryRepository: CategoryRepository,
private readonly restaurantsService: RestaurantsService,
private readonly em: EntityManager,
private readonly cacheService: CacheService,
) { }
async create(restId: string, dto: CreateCategoryDto): Promise<Category> {
@@ -31,6 +34,7 @@ export class CategoryService {
const category = this.categoryRepository.create(data);
await this.em.persistAndFlush(category);
await this.invalidateCategoriesCache(restaurant.slug);
return category;
}
@@ -58,6 +62,8 @@ export class CategoryService {
const cat = await this.findOneOrFail(restId, id)
this.em.assign(cat, dto);
await this.em.persistAndFlush(cat);
const restaurant = await this.restaurantsService.findOneOrFail(restId);
await this.invalidateCategoriesCache(restaurant.slug);
return cat;
}
@@ -65,5 +71,12 @@ export class CategoryService {
const cat = await this.findOneOrFail(restId, id)
cat.deletedAt = new Date();
await this.em.persistAndFlush(cat);
const restaurant = await this.restaurantsService.findOneOrFail(restId);
await this.invalidateCategoriesCache(restaurant.slug);
}
private async invalidateCategoriesCache(slug?: string): Promise<void> {
if (!slug) return;
await this.cacheService.del(CacheKeys.categoriesByRestaurant(slug));
}
}
+13 -5
View File
@@ -12,6 +12,8 @@ import { MealType } from '../interface/food.interface';
import { Inventory } from 'src/modules/inventory/entities/inventory.entity';
import { RestaurantsService } from 'src/modules/restaurants/providers/restaurants.service';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
import { CacheService } from 'src/modules/utils/cache.service';
import { CacheKeys } from 'src/common/constants/cache-keys.constant';
@Injectable()
export class FoodService {
@@ -20,6 +22,7 @@ export class FoodService {
private readonly categoryRepository: CategoryRepository,
private readonly restService: RestaurantsService,
private readonly em: EntityManager,
private readonly cacheService: CacheService,
) { }
async create(restId: string, createFoodDto: CreateFoodDto) {
@@ -72,6 +75,8 @@ export class FoodService {
: null;
const savedInventory = inventory?.id ? await this.em.findOne(Inventory, { id: inventory.id }) : inventory;
await this.invalidateRestaurantFoodsCache(restaurant.slug);
return { food: savedFood ?? food, inventory: savedInventory ?? inventory };
}
@@ -233,8 +238,7 @@ export class FoodService {
// Re-load the food to ensure populated relations and stable instance
const savedFood = await this.foodRepository.findOne({ id: food.id }, { populate: ['category', 'restaurant'] });
// Invalidate cache for the restaurant if present (optional)
// await this.invalidateRestaurantFoodsCache(savedFood?.restaurant?.slug);
await this.invalidateRestaurantFoodsCache(savedFood?.restaurant?.slug ?? food.restaurant?.slug);
return savedFood ?? food;
}
@@ -245,12 +249,16 @@ export class FoodService {
throw new NotFoundException(FoodMessage.NOT_FOUND);
}
// const restaurantSlug = food.restaurant.slug;
const restaurantSlug = food.restaurant.slug;
food.deletedAt = new Date();
await this.em.persistAndFlush(food);
// Invalidate cache for the restaurant
// await this.invalidateRestaurantFoodsCache(restaurantSlug);
await this.invalidateRestaurantFoodsCache(restaurantSlug);
}
private async invalidateRestaurantFoodsCache(slug?: string): Promise<void> {
if (!slug) return;
await this.cacheService.del(CacheKeys.foodsByRestaurant(slug));
}