remove food cache
This commit is contained in:
@@ -19,57 +19,36 @@ import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
|||||||
import { RestId, UserId } from 'src/common/decorators';
|
import { RestId, UserId } from 'src/common/decorators';
|
||||||
import { AuthGuard } from 'src/modules/auth/guards/auth.guard';
|
import { AuthGuard } from 'src/modules/auth/guards/auth.guard';
|
||||||
import { OptionalAuthGuard } from 'src/modules/auth/guards/optinalAuth.guard';
|
import { OptionalAuthGuard } from 'src/modules/auth/guards/optinalAuth.guard';
|
||||||
|
import { API_HEADER_SLUG } from 'src/common/constants';
|
||||||
|
|
||||||
@ApiTags('foods')
|
@ApiTags('foods')
|
||||||
@Controller()
|
@Controller()
|
||||||
export class FoodController {
|
export class FoodController {
|
||||||
constructor(private readonly foodsService: FoodService) { }
|
constructor(private readonly foodsService: FoodService) {}
|
||||||
|
|
||||||
@Get('public/foods/restaurant/:slug')
|
@Get('public/foods/restaurant/:slug')
|
||||||
@ApiOperation({ summary: 'Get all foods by restaurant slug' })
|
@ApiOperation({ summary: 'Get all foods by restaurant slug' })
|
||||||
@ApiHeader({
|
@ApiHeader(API_HEADER_SLUG)
|
||||||
name: 'X-Slug',
|
|
||||||
required: true,
|
|
||||||
schema: {
|
|
||||||
type: 'string',
|
|
||||||
default: 'zhivan',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@ApiParam({ name: 'slug', required: true, description: 'Restaurant Slug' })
|
@ApiParam({ name: 'slug', required: true, description: 'Restaurant Slug' })
|
||||||
@ApiOkResponse({ description: 'List of all foods for the restaurant' })
|
@ApiOkResponse({ description: 'List of all foods for the restaurant' })
|
||||||
findAllByRestaurant(@Param('slug') slug: string) {
|
findAllByRestaurant(@Param('slug') slug: string) {
|
||||||
return this.foodsService.findAllByRestaurant(slug);
|
return this.foodsService.findAllByRestaurant(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Get('public/foods/:foodId')
|
@Get('public/foods/:foodId')
|
||||||
@UseGuards(OptionalAuthGuard)
|
@UseGuards(OptionalAuthGuard)
|
||||||
@ApiHeader({
|
@ApiHeader(API_HEADER_SLUG)
|
||||||
name: 'X-Slug',
|
|
||||||
required: true,
|
|
||||||
schema: {
|
|
||||||
type: 'string',
|
|
||||||
default: 'zhivan',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@ApiOperation({ summary: 'Get a food by id' })
|
@ApiOperation({ summary: 'Get a food by id' })
|
||||||
@ApiParam({ name: 'foodId', required: true })
|
@ApiParam({ name: 'foodId', required: true })
|
||||||
findPublicFoodById(@Param('foodId') foodId: string, @UserId() userId?: string):Promise<any> {
|
findPublicFoodById(@Param('foodId') foodId: string, @UserId() userId?: string): Promise<any> {
|
||||||
const a= this.foodsService.findPublicById(foodId, userId);
|
const a = this.foodsService.findPublicById(foodId, userId);
|
||||||
return a
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('public/foods/favorite/:foodId')
|
@Post('public/foods/favorite/:foodId')
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard)
|
||||||
@ApiHeader({
|
@ApiHeader(API_HEADER_SLUG)
|
||||||
name: 'X-Slug',
|
|
||||||
required: true,
|
|
||||||
schema: {
|
|
||||||
type: 'string',
|
|
||||||
default: 'zhivan',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@ApiOperation({ summary: 'Set a food as favorite' })
|
@ApiOperation({ summary: 'Set a food as favorite' })
|
||||||
@ApiParam({ name: 'foodId', required: true })
|
@ApiParam({ name: 'foodId', required: true })
|
||||||
@@ -79,24 +58,17 @@ export class FoodController {
|
|||||||
|
|
||||||
@Delete('public/foods/favorite/:foodId')
|
@Delete('public/foods/favorite/:foodId')
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard)
|
||||||
@ApiHeader({
|
@ApiHeader(API_HEADER_SLUG)
|
||||||
name: 'X-Slug',
|
|
||||||
required: true,
|
|
||||||
schema: {
|
|
||||||
type: 'string',
|
|
||||||
default: 'zhivan',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@ApiOperation({ summary: 'Remove a food favorite' })
|
@ApiOperation({ summary: 'Remove a food favorite' })
|
||||||
@ApiParam({ name: 'foodId', required: true })
|
@ApiParam({ name: 'foodId', required: true })
|
||||||
removeFavorite(@Param('foodId') foodId: string, @UserId() userId: string) {
|
removeFavorite(@Param('foodId') foodId: string, @UserId() userId: string) {
|
||||||
return this.foodsService.removeFavorite(userId, foodId);
|
return this.foodsService.removeFavorite(userId, foodId);
|
||||||
}
|
}
|
||||||
|
/* ---------------------------------- Admin ---------------------------------- */
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Post('admin/foods')
|
@Post('admin/foods')
|
||||||
@ApiOperation({ summary: 'Create a new food' })
|
@ApiOperation({ summary: 'Create a new food' })
|
||||||
@ApiCreatedResponse({ description: 'The food has been successfully created.', type: CreateFoodDto })
|
@ApiCreatedResponse({ description: 'The food has been successfully created.', type: CreateFoodDto })
|
||||||
@ApiBody({ type: CreateFoodDto })
|
@ApiBody({ type: CreateFoodDto })
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class FoodService {
|
|||||||
private readonly restRepository: RestRepository,
|
private readonly restRepository: RestRepository,
|
||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
private readonly cacheService: CacheService,
|
private readonly cacheService: CacheService,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
async create(restId: string, createFoodDto: CreateFoodDto): Promise<Food> {
|
async create(restId: string, createFoodDto: CreateFoodDto): Promise<Food> {
|
||||||
const { categoryId, ...rest } = createFoodDto;
|
const { categoryId, ...rest } = createFoodDto;
|
||||||
@@ -65,7 +65,7 @@ export class FoodService {
|
|||||||
await this.em.persistAndFlush(food);
|
await this.em.persistAndFlush(food);
|
||||||
|
|
||||||
// Invalidate cache for the restaurant
|
// Invalidate cache for the restaurant
|
||||||
await this.invalidateRestaurantFoodsCache(restaurant.slug);
|
// await this.invalidateRestaurantFoodsCache(restaurant.slug);
|
||||||
|
|
||||||
return food;
|
return food;
|
||||||
}
|
}
|
||||||
@@ -77,17 +77,17 @@ export class FoodService {
|
|||||||
/**
|
/**
|
||||||
* Public food detail (only active foods are visible).
|
* Public food detail (only active foods are visible).
|
||||||
*/
|
*/
|
||||||
async findPublicById(foodId: string, userId?: string):Promise<any> {
|
async findPublicById(foodId: string, userId?: string): Promise<any> {
|
||||||
const food = await this.foodRepository.findOne({ id: foodId, isActive: true }, { populate: ['category'] });
|
const food = await this.foodRepository.findOne({ id: foodId, isActive: true }, { populate: ['category'] });
|
||||||
if (!food) throw new NotFoundException(FoodMessage.NOT_FOUND);
|
if (!food) throw new NotFoundException(FoodMessage.NOT_FOUND);
|
||||||
let isFavorite = false
|
let isFavorite = false;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
isFavorite = await this.em.count(Favorite, { user: { id: userId }, food: { id: foodId } }) > 0
|
isFavorite = (await this.em.count(Favorite, { user: { id: userId }, food: { id: foodId } })) > 0;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...food,
|
...food,
|
||||||
isFavorite,
|
isFavorite,
|
||||||
};;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,20 +101,20 @@ 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}`;
|
// const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`;
|
||||||
|
|
||||||
// Try to get from cache first
|
// Try to get from cache first
|
||||||
const cachedFoods = await this.cacheService.get<string>(cacheKey);
|
// const cachedFoods = await this.cacheService.get<string>(cacheKey);
|
||||||
if (cachedFoods) {
|
// if (cachedFoods) {
|
||||||
try {
|
// try {
|
||||||
const parsed: unknown = JSON.parse(cachedFoods);
|
// const parsed: unknown = JSON.parse(cachedFoods);
|
||||||
if (Array.isArray(parsed)) {
|
// if (Array.isArray(parsed)) {
|
||||||
return parsed as Food[];
|
// return parsed as Food[];
|
||||||
}
|
// }
|
||||||
} catch {
|
// } catch {
|
||||||
// If parsing fails, continue to fetch from DB
|
// // If parsing fails, continue to fetch from DB
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// If not in cache, fetch from database
|
// If not in cache, fetch from database
|
||||||
const restaurant = await this.restRepository.findOne({ slug });
|
const restaurant = await this.restRepository.findOne({ slug });
|
||||||
@@ -125,7 +125,7 @@ export class FoodService {
|
|||||||
const foods = await this.foodRepository.find({ restaurant: { slug }, isActive: true }, { populate: ['category'] });
|
const foods = await this.foodRepository.find({ restaurant: { slug }, isActive: true }, { populate: ['category'] });
|
||||||
|
|
||||||
// Cache the result
|
// Cache the result
|
||||||
await this.cacheService.set(cacheKey, JSON.stringify(foods), this.FOODS_CACHE_TTL);
|
// await this.cacheService.set(cacheKey, JSON.stringify(foods), this.FOODS_CACHE_TTL);
|
||||||
|
|
||||||
return foods;
|
return foods;
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ export class FoodService {
|
|||||||
await this.em.persistAndFlush(food);
|
await this.em.persistAndFlush(food);
|
||||||
|
|
||||||
// Invalidate cache for the restaurant
|
// Invalidate cache for the restaurant
|
||||||
await this.invalidateRestaurantFoodsCache(food.restaurant.slug);
|
// await this.invalidateRestaurantFoodsCache(food.restaurant.slug);
|
||||||
|
|
||||||
return food;
|
return food;
|
||||||
}
|
}
|
||||||
@@ -165,12 +165,12 @@ export class FoodService {
|
|||||||
throw new NotFoundException(FoodMessage.NOT_FOUND);
|
throw new NotFoundException(FoodMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const restaurantSlug = food.restaurant.slug;
|
// 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
|
// Invalidate cache for the restaurant
|
||||||
await this.invalidateRestaurantFoodsCache(restaurantSlug);
|
// await this.invalidateRestaurantFoodsCache(restaurantSlug);
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeFavorite(userId: string, foodId: string) {
|
async removeFavorite(userId: string, foodId: string) {
|
||||||
@@ -189,12 +189,11 @@ export class FoodService {
|
|||||||
await this.em.persistAndFlush(favorite);
|
await this.em.persistAndFlush(favorite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidate cache for restaurant foods
|
* Invalidate cache for restaurant foods
|
||||||
*/
|
*/
|
||||||
private async invalidateRestaurantFoodsCache(slug: string): Promise<void> {
|
// private async invalidateRestaurantFoodsCache(slug: string): Promise<void> {
|
||||||
const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`;
|
// const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`;
|
||||||
await this.cacheService.del(cacheKey);
|
// await this.cacheService.del(cacheKey);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user