const e = require('express') const database = require('./database.js') const con = require('./console') const NO_VALUE = null const NO_CACHE = undefined const users = {} const email_links = {} const password_links = {} const session_links = {} var newest_user = database.getNewestUserId(); const getUserByEmail = (email) => { const fast = email_links[email] if (fast === NO_VALUE) { return undefined } if (fast === NO_CACHE) { const slow = database.getUserByEmail(email) if (slow === undefined) { email_links[email] = NO_VALUE } else { email_links[email] = slow.id if (users[slow.id] === NO_CACHE) { users[slow.id] = slow } } return slow } return users[fast] } const getUserByPassword = (password) => { const fast = password_links[password] if (fast === NO_VALUE) { return undefined } if (fast === NO_CACHE) { const slow = database.getUserByPassword(password) if (slow === undefined) { password_links[password] = NO_VALUE } else { password_links[password] = slow.id if (users[slow.id] === NO_CACHE) { users[slow.id] = slow } } return slow } return users[fast] } const getUsers = (ids) => { const fast = {} const batch = [] for (const id of ids) { if (users[id] === NO_CACHE) { batch.push(id) } else { fast[id] = users[id] } } if (batch.length > 0) { const slow = database.getUsers(batch) for(const [id, user] of Object.entries(slow)) { fast[id] = user } } return fast } const getUsersPage = (page) => { const COUNT = 10 const INDEX = newest_user - page * COUNT const batch = [] for (let i = INDEX; i > INDEX - COUNT && i >= 0; i--) { batch.push(i) } const users = getUsers(batch) return batch.map(i => users[i]).filter(u => u !== undefined) } const register = (first, last, email, password, gender, month, day, year) => { const data = database.register(first, last, email, password, gender, month, day, year) if (data === undefined) { return undefined } newest_user = data.user.id session_links[data.key] = data.user.id users[data.user.id] = data.user return data.key } const login = (email, pass) => { const data = database.login(email, pass) if (data === undefined) { return undefined } session_links[data.key] = data.user.id users[data.user.id] = data.user return data.key } const logout = (token) => { if (session_links[token] === NO_VALUE) { return false } if (!database.deleteSession(token)) { return false } delete session_links[token] return true } const auth = (token) => { const fast = session_links[token] if (fast === NO_VALUE) { return undefined } if (fast === NO_CACHE) { const slow = database.auth(token) if (slow === undefined) { session_links[token] = NO_VALUE } else { session_links[token] = slow.id if (users[slow.id] === NO_CACHE) { users[slow.id] = slow } } return slow } return users[fast] } const posts = {} const users_posts = {} const updated_posts = {} var newest_post = database.getNewestPostId(); const addPost = (user, content) => { const id = database.addPost(user, content) if (id === undefined) { return -1 } newest_post = id if (users_posts[user] === NO_VALUE) { users[posts] = [id] } else if (users_posts[user] === NO_CACHE) { getUsersPosts(user) } else { users_posts[user].unshift(id) } return id } const getPosts = (ids) => { const fast = {} const batch = [] for (const id of ids) { if (posts[id] === NO_CACHE) { batch.push(id) } else { fast[id] = posts[id] } } if (batch.length > 0) { const slow = database.getPosts(batch) for(const [id, post] of Object.entries(slow)) { fast[id] = post } } return fast } const getUsersPosts = (user) => { const fast = users_posts[user] if (fast === NO_CACHE) { const posts = database.getUsersPosts(user) if (posts === undefined) { users_posts[user] = NO_VALUE } else { const slow = [] for (const post in posts) { slow.push[post.id] if (posts[post.id] === NO_CACHE) { posts[post.id] = post } } users_posts[user] = slow } return posts } else { return getPosts(fast) } } const getPostsPage = (page) => { const COUNT = 10 const INDEX = newest_post - page * COUNT const batch = [] for (let i = INDEX; i > INDEX - COUNT && i >= 0; i--) { batch.push(i) } const posts = getPosts(batch) return batch.map(i => posts[i]).filter(p => p !== undefined) } const comment = (id, user, content) => { var fast = posts[id] if (fast === NO_VALUE) { return false } else if (fast === NO_CACHE) { const slow = getPosts([id]) if (slow[id] === undefined) { return false } else { fast = slow[id] } } fast.comments.push({user, content}) posts[id] = fast updated_posts[id] = true return true } const like = (id, user, state) => { var fast = posts[id] if (fast === NO_VALUE) { return false } else if (fast === NO_CACHE) { const slow = getPosts([id]) if (slow[id] === undefined) { return false } else { fast = slow[id] } } fast.likes[user] = state posts[id] = fast updated_posts[id] = true return true } const dump = () => { for (id in updated_posts) { const post = posts[id] if (post === NO_CACHE || post === NO_VALUE) continue; if (!database.updatePost(post.id, JSON.stringify(post.likes), JSON.stringify(post.comments))) { con.error(`Failed to saved cached post id ${id}`) } else { delete updated_posts.id } } con.msg('Saved cache successfully') } module.exports = { getUserByEmail, getUserByPassword, getUsers, getUsersPage, register, login, logout, auth, addPost, getPosts, getUsersPosts, getPostsPage, comment, like, dump }