Last active
April 29, 2020 01:12
-
-
Save decapo01/ac4ce01d68dc334108073ef6b38020dc to your computer and use it in GitHub Desktop.
Repository Service Pattern With Cache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//User | |
User { | |
id: UserId | |
username: String | |
} | |
//UserDetails | |
UserDetails { | |
otherDetails: String | |
} | |
//UserWithDetails | |
UserWithDetails { | |
id: UserId, | |
username: String, | |
otherDetails: String | |
} | |
//UserService | |
UserService { | |
userRepo: UserRepo // <- if you want to use oo injection | |
construct(userRepo: UserRepo){ | |
this.userRepo = userRepo | |
} | |
findUser(userId: UserId): Option<UserWithDetails> { | |
return userRepo.find(userId) | |
} | |
// Functional Style. Can be Static | |
static fetchUsers(repoFetchUser: () -> Array<User>): Array<User> { | |
return repoFetchUser() | |
} | |
} | |
//UserRepo OO | |
interface UserWithDetailsRepo { | |
find(userId: UserId): Option<UserWithDetails> | |
} | |
//UserArangoRepo | |
UserArangoRepo { | |
// Just gets user since that's all thats in arango | |
find(userId: UserId): Option<User> { | |
return fetchEntities<User>("users") |> find u -> u.userId == userId | |
} | |
} | |
//UserDetailsRepo | |
UserDetailsRepo { | |
find(userId: UserId): Option<UserDetail> { | |
return fetchEntities<Notification>("notification") | |
|> find u -> u.userId == userid | |
|> map | |
|> mapToUserDetail | |
} | |
} | |
//UserWithDetailsRedisRepo | |
UserWithDetailsRedisRepo { | |
find(userId: UserId): Option<UserWithDetail> { | |
return redis.get('userWithDetails', userId) | |
} | |
insert(userWithDetails: UserWithDetailsRepo): Void { | |
redis.insert(userWithDetails.id, userWithDetails) | |
} | |
} | |
//UserWithDetailsRepoImplementation | |
UserWithDetailsRepoImpl implements UserWithDetailsRepo { | |
// You can inject if you want here to make switching out components easier | |
// in the future but it's not necessary for the core logic of you application | |
find(userId: UserId): Option<UserWithDetail> { | |
userFromCache = UserWithDetailsRedisRepo.find(userId) | |
match(userFromCache){ | |
Some u -> return Some u | |
None -> | |
userFromArango = UserArangoRepo.find(userId) | |
userDetails = UserDetailsRepo.find(userId) | |
match ((userFromArango,userDetails)) { | |
(Some user, Some details) -> return Some(mapToUserWithDetails(user,details)) | |
_ -> return None | |
} | |
} | |
} | |
} | |
//Makes a lot more sense in this context | |
UserService { | |
userRepo: UserRepo // <- if you want to use oo injection | |
construct(userRepo: UserRepo){ | |
this.userRepo = userRepo | |
} | |
findUser(userId: UserId): Option<UserWithDetails> { | |
return userRepo.find(userId) | |
} | |
// Functional Style. Can be Static | |
static fetchUser(repoFetchUser: () -> Option<User>): Option<User> { | |
return repoFetchUser() | |
} | |
static registerUser(email : String, | |
password : String, | |
confirmPassword : String, | |
otherDetail : String | |
repoFindUserByEmail : (String) -> Option<User>, | |
repoInsertUser : (UserWithDetails) -> Either<Error,UserWithDetails>, | |
hashPassword : (String) -> String) : Either<Error,UserWithDetails>) { | |
userEither = validateUser(email,password,confirmPassword,otherDetails) | |
match userEither | |
Left e -> return Left(e) | |
Right userWithDetails -> | |
match findUserByEmail(userWithDetails.email) | |
Some u -> return Left(UserExists) | |
None -> | |
match hashPassword(userWithDetails.password) | |
Left e -> return Left(e) | |
Right hashedPassword -> | |
match insertUser(userWithDetails.copy(password = hashPassword)) | |
Left e -> return Left(e) | |
Right savedUserWithDetails -> return Right(savedUserWithDetails) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment