Skip to content

Commit

Permalink
feat(server): added caching to followers and following
Browse files Browse the repository at this point in the history
  • Loading branch information
AdwaithAthman committed Dec 27, 2023
1 parent b2962bf commit 14b0681
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 21 deletions.
2 changes: 1 addition & 1 deletion server/src/adapters/profileController/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AuthService } from "../../frameworks/services/authService";
import { AuthServiceInterface } from "../../application/services/authServiceInterface";
import { ProfileInterface } from "../../types/profileInterface";
import { RedisRepository } from "../../frameworks/database/redis/redisRepository";
import { RedisDbInterface } from "../../application/repositories/redisDbRepository";

//use-cases import
import {
Expand All @@ -23,7 +24,6 @@ import {
handleSearchUsers,
handleAddUsername,
} from "../../application/use-cases/profile/userProfile";
import { RedisDbInterface } from "../../application/repositories/redisDbRepository";

const profileController = (
cloudinaryServiceImpl: CloudinaryService,
Expand Down
17 changes: 11 additions & 6 deletions server/src/adapters/userController/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import asyncHandler from "express-async-handler";
//importing types
import { UserDbInterface } from "../../application/repositories/userDbRepository";
import { UserRepositoryMongoDB } from "../../frameworks/database/mongoDB/repositories/userRepositoryMongoDB";
import { RedisRepository } from "../../frameworks/database/redis/redisRepository";
import { RedisDbInterface } from "../../application/repositories/redisDbRepository";

//use-cases import
import {
Expand All @@ -20,13 +22,16 @@ import {

const userController = (
userDbRepositoryImpl: UserRepositoryMongoDB,
userDbRepositoryInterface: UserDbInterface
userDbRepositoryInterface: UserDbInterface,
redisRepositoryImpl: RedisRepository,
redisRepositoryInterface: RedisDbInterface,
) => {
const dbUserRepository = userDbRepositoryInterface(userDbRepositoryImpl());

const redisRepository = redisRepositoryInterface(redisRepositoryImpl());

const followUser = asyncHandler(async (req: Request, res: Response) => {
const { userId, friendId }: { userId: string; friendId: string } = req.body;
await handleFollowUser(userId, friendId, dbUserRepository);
await handleFollowUser(userId, friendId, dbUserRepository, redisRepository);
res.json({
status: "success",
message: "successfully followed user",
Expand All @@ -35,7 +40,7 @@ const userController = (

const unfollowUser = asyncHandler(async (req: Request, res: Response) => {
const { userId, friendId }: { userId: string; friendId: string } = req.body;
await handleUnfollowUser(userId, friendId, dbUserRepository);
await handleUnfollowUser(userId, friendId, dbUserRepository, redisRepository);
res.json({
status: "success",
message: "successfully unfollowed user",
Expand Down Expand Up @@ -66,7 +71,7 @@ const userController = (

const getFollowers = asyncHandler(async (req: Request, res: Response) => {
const { userId }: { userId: string } = req.params as unknown as { userId: string };
const followers = await handleGetFollowers(userId, dbUserRepository);
const followers = await handleGetFollowers(userId, dbUserRepository, redisRepository);
res.json({
status: "success",
message: "followers fetched",
Expand All @@ -76,7 +81,7 @@ const userController = (

const getFollowing = asyncHandler(async (req: Request, res: Response) => {
const { userId }: { userId: string } = req.params as unknown as { userId: string };
const following = await handleGetFollowing(userId, dbUserRepository);
const following = await handleGetFollowing(userId, dbUserRepository, redisRepository);
res.json({
status: "success",
message: "followers fetched",
Expand Down
55 changes: 41 additions & 14 deletions server/src/application/use-cases/user/user.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import AppError from "../../../utils/appError";
import { UserDbInterface } from "../../repositories/userDbRepository";
import { RedisDbInterface } from "../../repositories/redisDbRepository";

//importing from types
import { HttpStatus } from "../../../types/httpStatus";

export const handleFollowUser = async (
userId: string,
friendId: string,
dbUserRepository: ReturnType<UserDbInterface>
dbUserRepository: ReturnType<UserDbInterface>,
redisRepository: ReturnType<RedisDbInterface>
) => {
try {
await dbUserRepository.followUser(userId, friendId);
await redisRepository.deleteCache(`userInfo:${userId}`);
await redisRepository.deleteCache(`userInfo:${friendId}`);
await redisRepository.deleteCache(`following:${userId}`);
await redisRepository.deleteCache(`followers:${friendId}`);
} catch (err) {
throw new AppError(
"Error following user!",
Expand All @@ -22,10 +28,15 @@ export const handleFollowUser = async (
export const handleUnfollowUser = async (
userId: string,
friendId: string,
dbUserRepository: ReturnType<UserDbInterface>
dbUserRepository: ReturnType<UserDbInterface>,
redisRepository: ReturnType<RedisDbInterface>
) => {
try {
await dbUserRepository.unfollowUser(userId, friendId);
await redisRepository.deleteCache(`userInfo:${userId}`);
await redisRepository.deleteCache(`userInfo:${friendId}`);
await redisRepository.deleteCache(`following:${userId}`);
await redisRepository.deleteCache(`followers:${friendId}`);
} catch (err) {
throw new AppError(
"Error unfollowing user!",
Expand Down Expand Up @@ -66,11 +77,18 @@ export const handleRestOfAllUsers = async (

export const handleGetFollowers = async (
userId: string,
dbUserRepository: ReturnType<UserDbInterface>
dbUserRepository: ReturnType<UserDbInterface>,
redisRepository: ReturnType<RedisDbInterface>
) => {
try {
const followers = await dbUserRepository.getFollowers(userId);
return followers;
const followersList = await redisRepository.setCache(
`followers:${userId}`,
async () => {
const followers = await dbUserRepository.getFollowers(userId);
return followers;
}
);
return followersList;
} catch (error) {
throw new AppError(
"Error fetching followers!",
Expand All @@ -81,11 +99,18 @@ export const handleGetFollowers = async (

export const handleGetFollowing = async (
userId: string,
dbUserRepository: ReturnType<UserDbInterface>
dbUserRepository: ReturnType<UserDbInterface>,
redisRepository: ReturnType<RedisDbInterface>
) => {
try {
const following = await dbUserRepository.getFollowing(userId);
return following;
const followingList = await redisRepository.setCache(
`following:${userId}`,
async () => {
const following = await dbUserRepository.getFollowing(userId);
return following;
}
);
return followingList;
} catch (error) {
throw new AppError(
"Error fetching followers!",
Expand All @@ -98,18 +123,21 @@ export const handleGetSuggestions = async (
userId: string,
dbUserRepository: ReturnType<UserDbInterface>
) => {
try{
try {
const suggestions = await dbUserRepository.getSuggestions(userId);
const uniqueSuggestions = Array.from(suggestions.reduce((map, obj) => map.set(obj._id.toString(), obj), new Map()).values())
const uniqueSuggestions = Array.from(
suggestions
.reduce((map, obj) => map.set(obj._id.toString(), obj), new Map())
.values()
);
return uniqueSuggestions;
}
catch (error) {
} catch (error) {
throw new AppError(
"Error fetching suggestions!",
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
};

export const handleAddNotification = async (
userId: string,
Expand Down Expand Up @@ -140,4 +168,3 @@ export const handleDeleteNotification = async (
);
}
};

4 changes: 4 additions & 0 deletions server/src/frameworks/webserver/routes/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import express from "express";
import { userRepositoryMongoDB } from "../../database/mongoDB/repositories/userRepositoryMongoDB";
import { userDbRepository } from "../../../application/repositories/userDbRepository";
import userController from "../../../adapters/userController";
import { redisRepository } from "../../database/redis/redisRepository";
import { redisDbRepository } from "../../../application/repositories/redisDbRepository";

//Middleware
import authMiddleware from "../middlewares/authMiddleware";
Expand All @@ -12,6 +14,8 @@ const userRouter = () => {
const controller = userController(
userRepositoryMongoDB,
userDbRepository,
redisRepository,
redisDbRepository
)

//routes
Expand Down

0 comments on commit 14b0681

Please sign in to comment.