👔 feat: support user collection check on hero banner
All checks were successful
Integration Tests / integration-tests (pull_request) Successful in 56s

This commit is contained in:
2026-03-30 19:03:37 +07:00
parent cef6da16cb
commit 5cebd200c4
4 changed files with 45 additions and 21 deletions

View File

@ -1,17 +1,16 @@
import { Context } from "elysia"; import { Context, Static } from "elysia";
import { mainErrorHandler } from "../../../helpers/error/handler"; import { mainErrorHandler } from "../../../helpers/error/handler";
import { returnReadResponse } from "../../../helpers/callback/httpResponse"; import { returnReadResponse } from "../../../helpers/callback/httpResponse";
import { getActiveHeroBannerService } from "../services/getActiveHeroBanner.service"; import { getActiveHeroBannerService } from "../services/getActiveHeroBanner.service";
import { getActiveHeroBannerSchema } from "../schemas/getActiveHeroBanner.schema";
export const getActiveHeroBannerController = async (ctx: Context) => { export const getActiveHeroBannerController = async (ctx: {
set: Context["set"];
header: Static<typeof getActiveHeroBannerSchema.headers>;
}) => {
try { try {
const response = await getActiveHeroBannerService(); const response = await getActiveHeroBannerService({ cookie: ctx.header?.cookie });
return returnReadResponse( return returnReadResponse(ctx.set, 200, "Active hero banners fetched successfully", response);
ctx.set,
200,
"Active hero banners fetched successfully",
response,
);
} catch (error) { } catch (error) {
return mainErrorHandler(ctx.set, error); return mainErrorHandler(ctx.set, error);
} }

View File

@ -1,7 +1,7 @@
import { AppError } from "../../../../helpers/error/instances/app"; import { AppError } from "../../../../helpers/error/instances/app";
import { prisma } from "../../../../utils/databases/prisma/connection"; import { prisma } from "../../../../utils/databases/prisma/connection";
export const findAllActiveHeroBannerRepository = async () => { export const findAllActiveHeroBannerRepository = async (userId?: string) => {
try { try {
return await prisma.heroBanner.findMany({ return await prisma.heroBanner.findMany({
where: { where: {
@ -36,6 +36,17 @@ export const findAllActiveHeroBannerRepository = async () => {
name: true, name: true,
}, },
}, },
_count: {
select: {
inCollections: {
where: {
collection: {
ownerId: userId,
},
},
},
},
},
}, },
}, },
}, },

View File

@ -0,0 +1,8 @@
import { t } from "elysia";
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
export const getActiveHeroBannerSchema = {
headers: t.Object({
cookie: t.Optional(t.String()),
}),
} satisfies AppRouteSchema;

View File

@ -1,22 +1,25 @@
import { redisKey } from "../../../config/redis/key";
import { AppError } from "../../../helpers/error/instances/app"; import { AppError } from "../../../helpers/error/instances/app";
import { ErrorForwarder } from "../../../helpers/error/instances/forwarder"; import { ErrorForwarder } from "../../../helpers/error/instances/forwarder";
import { redis } from "../../../utils/databases/redis/connection"; import { tokenValidationService } from "../../auth/services/http/tokenValidation.service";
import { findSystemPreferenceService } from "../../systemPreference/services/internal/findSystemPreference.service"; import { findSystemPreferenceService } from "../../systemPreference/services/internal/findSystemPreference.service";
import { findAllActiveHeroBannerRepository } from "../repositories/GET/findAllActiveHeroBanner.repository"; import { findAllActiveHeroBannerRepository } from "../repositories/GET/findAllActiveHeroBanner.repository";
export const getActiveHeroBannerService = async () => { export const getActiveHeroBannerService = async ({ cookie }: { cookie?: string }) => {
try { try {
const userId = cookie ? (await tokenValidationService(cookie)).user.id : undefined;
// Check if Hero Banner is enabled in system preferences // Check if Hero Banner is enabled in system preferences
const isHeroBannerEnabled = await findSystemPreferenceService("HERO_BANNER_ENABLED", "boolean"); const isHeroBannerEnabled = await findSystemPreferenceService("HERO_BANNER_ENABLED", "boolean");
if (!isHeroBannerEnabled) throw new AppError(403, "Hero Banner is disabled"); if (!isHeroBannerEnabled) throw new AppError(403, "Hero Banner is disabled");
// Try to get active banners from Redis cache // Dont implement caching just yet; implement collection caching first, then implement banner caching.
const cachedBanners = await redis.get(`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`); // Please note that currently, a database query is still required to check the collections.
if (cachedBanners) return JSON.parse(cachedBanners); // // Try to get active banners from Redis cache
// const cachedBanners = await redis.get(`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`);
// if (cachedBanners) return JSON.parse(cachedBanners);
// If not in cache, fetch from database and cache the result // If not in cache, fetch from database and cache the result
const activeBanners = await findAllActiveHeroBannerRepository(); const activeBanners = await findAllActiveHeroBannerRepository(userId);
const constructedBanners = activeBanners.map((banner) => ({ const constructedBanners = activeBanners.map((banner) => ({
id: banner.media.id, id: banner.media.id,
title: banner.media.title, title: banner.media.title,
@ -27,11 +30,14 @@ export const getActiveHeroBannerService = async () => {
slug: genre.slug, slug: genre.slug,
name: genre.name, name: genre.name,
})), })),
isInCollection: banner.media._count.inCollections > 0,
})); }));
await redis.set(
`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`, // await redis.set(
JSON.stringify(constructedBanners), // `${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`,
); // JSON.stringify(constructedBanners),
// );
return constructedBanners; return constructedBanners;
} catch (error) { } catch (error) {
ErrorForwarder(error); ErrorForwarder(error);