This commit is contained in:
2025-12-11 18:29:57 +03:30
parent 2cf554caa4
commit a54e8eb9f3
2 changed files with 53 additions and 4 deletions
+2 -1
View File
@@ -11,9 +11,10 @@ import { Food } from './entities/food.entity';
import { RestaurantsModule } from '../restaurants/restaurants.module'; import { RestaurantsModule } from '../restaurants/restaurants.module';
import { AuthModule } from '../auth/auth.module'; import { AuthModule } from '../auth/auth.module';
import { JwtModule } from '@nestjs/jwt'; import { JwtModule } from '@nestjs/jwt';
import { UtilsModule } from '../utils/utils.module';
@Module({ @Module({
imports: [MikroOrmModule.forFeature([Food, Category]), RestaurantsModule, AuthModule, JwtModule], imports: [MikroOrmModule.forFeature([Food, Category]), RestaurantsModule, AuthModule, JwtModule, UtilsModule],
controllers: [FoodController, CategoryController], controllers: [FoodController, CategoryController],
providers: [FoodService, CategoryService, FoodRepository, CategoryRepository], providers: [FoodService, CategoryService, FoodRepository, CategoryRepository],
exports: [FoodRepository, CategoryRepository], exports: [FoodRepository, CategoryRepository],
+51 -3
View File
@@ -8,14 +8,19 @@ import { RequiredEntityData } from '@mikro-orm/core';
import { Food } from '../entities/food.entity'; import { Food } from '../entities/food.entity';
import { CategoryMessage, FoodMessage, RestMessage } from 'src/common/enums/message.enum'; import { CategoryMessage, FoodMessage, RestMessage } from 'src/common/enums/message.enum';
import { RestRepository } from 'src/modules/restaurants/repositories/rest.repository'; import { RestRepository } from 'src/modules/restaurants/repositories/rest.repository';
import { CacheService } from '../../utils/cache.service';
@Injectable() @Injectable()
export class FoodService { export class FoodService {
private readonly FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX = 'foods:restaurant:';
private readonly FOODS_CACHE_TTL = 600; // 10 minutes in seconds
constructor( constructor(
private readonly foodRepository: FoodRepository, private readonly foodRepository: FoodRepository,
private readonly categoryRepository: CategoryRepository, private readonly categoryRepository: CategoryRepository,
private readonly restRepository: RestRepository, private readonly restRepository: RestRepository,
private readonly em: EntityManager, private readonly em: EntityManager,
private readonly cacheService: CacheService,
) {} ) {}
async create(restId: string, createFoodDto: CreateFoodDto): Promise<Food> { async create(restId: string, createFoodDto: CreateFoodDto): Promise<Food> {
@@ -65,6 +70,10 @@ export class FoodService {
} }
await this.em.persistAndFlush(food); await this.em.persistAndFlush(food);
// Invalidate cache for the restaurant
await this.invalidateRestaurantFoodsCache(restaurant.slug);
return food; return food;
} }
@@ -81,15 +90,37 @@ export class FoodService {
} }
async findAllByRestaurant(slug: string): Promise<Food[]> { async findAllByRestaurant(slug: string): Promise<Food[]> {
const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`;
// Try to get from cache first
const cachedFoods = await this.cacheService.get<string>(cacheKey);
if (cachedFoods) {
try {
const parsed: unknown = JSON.parse(cachedFoods);
if (Array.isArray(parsed)) {
return parsed as Food[];
}
} catch {
// If parsing fails, continue to fetch from DB
}
}
// If not in cache, fetch from database
const restaurant = await this.restRepository.findOne({ slug }); const restaurant = await this.restRepository.findOne({ slug });
if (!restaurant) { if (!restaurant) {
throw new NotFoundException(RestMessage.NOT_FOUND); throw new NotFoundException(RestMessage.NOT_FOUND);
} }
return this.foodRepository.find({ restaurant: { slug }, isActive: true }, { populate: ['category'] });
const foods = await this.foodRepository.find({ restaurant: { slug }, isActive: true }, { populate: ['category'] });
// Cache the result
await this.cacheService.set(cacheKey, JSON.stringify(foods), this.FOODS_CACHE_TTL);
return foods;
} }
async update(id: string, dto: Partial<CreateFoodDto>): Promise<Food> { async update(id: string, dto: Partial<CreateFoodDto>): Promise<Food> {
const food = await this.foodRepository.findOne({ id }); const food = await this.foodRepository.findOne({ id }, { populate: ['restaurant'] });
if (!food) { if (!food) {
throw new NotFoundException(FoodMessage.NOT_FOUND); throw new NotFoundException(FoodMessage.NOT_FOUND);
} }
@@ -109,15 +140,32 @@ export class FoodService {
this.em.assign(food, rest); this.em.assign(food, rest);
await this.em.persistAndFlush(food); await this.em.persistAndFlush(food);
// Invalidate cache for the restaurant
await this.invalidateRestaurantFoodsCache(food.restaurant.slug);
return food; return food;
} }
async remove(id: string) { async remove(id: string) {
const food = await this.foodRepository.findOne({ id }); const food = await this.foodRepository.findOne({ id }, { populate: ['restaurant'] });
if (!food) { if (!food) {
throw new NotFoundException(FoodMessage.NOT_FOUND); throw new NotFoundException(FoodMessage.NOT_FOUND);
} }
const restaurantSlug = food.restaurant.slug;
food.deletedAt = new Date(); food.deletedAt = new Date();
await this.em.persistAndFlush(food); await this.em.persistAndFlush(food);
// Invalidate cache for the restaurant
await this.invalidateRestaurantFoodsCache(restaurantSlug);
}
/**
* Invalidate cache for restaurant foods
*/
private async invalidateRestaurantFoodsCache(slug: string): Promise<void> {
const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`;
await this.cacheService.del(cacheKey);
} }
} }