mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Add in-memory user cache
This commit is contained in:
		
							parent
							
								
									2e970cbb39
								
							
						
					
					
						commit
						a382482173
					
				| @ -990,28 +990,18 @@ class Auth { | |||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 |     try { | ||||||
|     Database.userModel |       await matchingUser.update({ pash: pw }) | ||||||
|       .update( |       Logger.info(`[Auth] User "${matchingUser.username}" changed password`) | ||||||
|         { |       res.json({ | ||||||
|           pash: pw |         success: true | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           where: { id: matchingUser.id } |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|       .then(() => { |  | ||||||
|         Logger.info(`[Auth] User "${matchingUser.username}" changed password`) |  | ||||||
|         res.json({ |  | ||||||
|           success: true |  | ||||||
|         }) |  | ||||||
|       }) |       }) | ||||||
|       .catch((error) => { |     } catch (error) { | ||||||
|         Logger.error(`[Auth] User "${matchingUser.username}" failed to change password`, error) |       Logger.error(`[Auth] User "${matchingUser.username}" failed to change password`, error) | ||||||
|         res.json({ |       res.json({ | ||||||
|           error: 'Unknown error' |         error: 'Unknown error' | ||||||
|         }) |  | ||||||
|       }) |       }) | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,6 +3,53 @@ const sequelize = require('sequelize') | |||||||
| const Logger = require('../Logger') | const Logger = require('../Logger') | ||||||
| const SocketAuthority = require('../SocketAuthority') | const SocketAuthority = require('../SocketAuthority') | ||||||
| const { isNullOrNaN } = require('../utils') | const { isNullOrNaN } = require('../utils') | ||||||
|  | const { LRUCache } = require('lru-cache') | ||||||
|  | 
 | ||||||
|  | class UserCache { | ||||||
|  |   constructor() { | ||||||
|  |     this.cache = new LRUCache({ max: 100 }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getById(id) { | ||||||
|  |     const user = this.cache.get(id) | ||||||
|  |     return user | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getByEmail(email) { | ||||||
|  |     const user = this.cache.find((u) => u.email === email) | ||||||
|  |     return user | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getByUsername(username) { | ||||||
|  |     const user = this.cache.find((u) => u.username === username) | ||||||
|  |     return user | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getByOldId(oldUserId) { | ||||||
|  |     const user = this.cache.find((u) => u.extraData?.oldUserId === oldUserId) | ||||||
|  |     return user | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getByOpenIDSub(sub) { | ||||||
|  |     const user = this.cache.find((u) => u.extraData?.authOpenIDSub === sub) | ||||||
|  |     return user | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   set(user) { | ||||||
|  |     user.fromCache = true | ||||||
|  |     this.cache.set(user.id, user) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   delete(userId) { | ||||||
|  |     this.cache.delete(userId) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   maybeInvalidate(user) { | ||||||
|  |     if (!user.fromCache) this.delete(user.id) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const userCache = new UserCache() | ||||||
| 
 | 
 | ||||||
| const { DataTypes, Model } = sequelize | const { DataTypes, Model } = sequelize | ||||||
| 
 | 
 | ||||||
| @ -206,7 +253,11 @@ class User extends Model { | |||||||
|    */ |    */ | ||||||
|   static async getUserByUsername(username) { |   static async getUserByUsername(username) { | ||||||
|     if (!username) return null |     if (!username) return null | ||||||
|     return this.findOne({ | 
 | ||||||
|  |     const cachedUser = userCache.getByUsername(username) | ||||||
|  |     if (cachedUser) return cachedUser | ||||||
|  | 
 | ||||||
|  |     const user = await this.findOne({ | ||||||
|       where: { |       where: { | ||||||
|         username: { |         username: { | ||||||
|           [sequelize.Op.like]: username |           [sequelize.Op.like]: username | ||||||
| @ -214,6 +265,10 @@ class User extends Model { | |||||||
|       }, |       }, | ||||||
|       include: this.sequelize.models.mediaProgress |       include: this.sequelize.models.mediaProgress | ||||||
|     }) |     }) | ||||||
|  | 
 | ||||||
|  |     if (user) userCache.set(user) | ||||||
|  | 
 | ||||||
|  |     return user | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -223,7 +278,11 @@ class User extends Model { | |||||||
|    */ |    */ | ||||||
|   static async getUserByEmail(email) { |   static async getUserByEmail(email) { | ||||||
|     if (!email) return null |     if (!email) return null | ||||||
|     return this.findOne({ | 
 | ||||||
|  |     const cachedUser = userCache.getByEmail(email) | ||||||
|  |     if (cachedUser) return cachedUser | ||||||
|  | 
 | ||||||
|  |     const user = await this.findOne({ | ||||||
|       where: { |       where: { | ||||||
|         email: { |         email: { | ||||||
|           [sequelize.Op.like]: email |           [sequelize.Op.like]: email | ||||||
| @ -231,6 +290,10 @@ class User extends Model { | |||||||
|       }, |       }, | ||||||
|       include: this.sequelize.models.mediaProgress |       include: this.sequelize.models.mediaProgress | ||||||
|     }) |     }) | ||||||
|  | 
 | ||||||
|  |     if (user) userCache.set(user) | ||||||
|  | 
 | ||||||
|  |     return user | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -240,9 +303,17 @@ class User extends Model { | |||||||
|    */ |    */ | ||||||
|   static async getUserById(userId) { |   static async getUserById(userId) { | ||||||
|     if (!userId) return null |     if (!userId) return null | ||||||
|     return this.findByPk(userId, { | 
 | ||||||
|  |     const cachedUser = userCache.getById(userId) | ||||||
|  |     if (cachedUser) return cachedUser | ||||||
|  | 
 | ||||||
|  |     const user = await this.findByPk(userId, { | ||||||
|       include: this.sequelize.models.mediaProgress |       include: this.sequelize.models.mediaProgress | ||||||
|     }) |     }) | ||||||
|  | 
 | ||||||
|  |     if (user) userCache.set(user) | ||||||
|  | 
 | ||||||
|  |     return user | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -254,12 +325,19 @@ class User extends Model { | |||||||
|    */ |    */ | ||||||
|   static async getUserByIdOrOldId(userId) { |   static async getUserByIdOrOldId(userId) { | ||||||
|     if (!userId) return null |     if (!userId) return null | ||||||
|     return this.findOne({ |     const cachedUser = userCache.getById(userId) || userCache.getByOldId(userId) | ||||||
|  |     if (cachedUser) return cachedUser | ||||||
|  | 
 | ||||||
|  |     const user = await this.findOne({ | ||||||
|       where: { |       where: { | ||||||
|         [sequelize.Op.or]: [{ id: userId }, { 'extraData.oldUserId': userId }] |         [sequelize.Op.or]: [{ id: userId }, { 'extraData.oldUserId': userId }] | ||||||
|       }, |       }, | ||||||
|       include: this.sequelize.models.mediaProgress |       include: this.sequelize.models.mediaProgress | ||||||
|     }) |     }) | ||||||
|  | 
 | ||||||
|  |     if (user) userCache.set(user) | ||||||
|  | 
 | ||||||
|  |     return user | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -269,10 +347,18 @@ class User extends Model { | |||||||
|    */ |    */ | ||||||
|   static async getUserByOpenIDSub(sub) { |   static async getUserByOpenIDSub(sub) { | ||||||
|     if (!sub) return null |     if (!sub) return null | ||||||
|     return this.findOne({ | 
 | ||||||
|  |     const cachedUser = userCache.getByOpenIDSub(sub) | ||||||
|  |     if (cachedUser) return cachedUser | ||||||
|  | 
 | ||||||
|  |     const user = await this.findOne({ | ||||||
|       where: sequelize.where(sequelize.literal(`extraData->>"authOpenIDSub"`), sub), |       where: sequelize.where(sequelize.literal(`extraData->>"authOpenIDSub"`), sub), | ||||||
|       include: this.sequelize.models.mediaProgress |       include: this.sequelize.models.mediaProgress | ||||||
|     }) |     }) | ||||||
|  | 
 | ||||||
|  |     if (user) userCache.set(user) | ||||||
|  | 
 | ||||||
|  |     return user | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -623,6 +709,7 @@ class User extends Model { | |||||||
|       mediaProgress = await this.sequelize.models.mediaProgress.create(newMediaProgressPayload) |       mediaProgress = await this.sequelize.models.mediaProgress.create(newMediaProgressPayload) | ||||||
|       this.mediaProgresses.push(mediaProgress) |       this.mediaProgresses.push(mediaProgress) | ||||||
|     } |     } | ||||||
|  |     userCache.maybeInvalidate(this) | ||||||
|     return { |     return { | ||||||
|       mediaProgress |       mediaProgress | ||||||
|     } |     } | ||||||
| @ -804,6 +891,21 @@ class User extends Model { | |||||||
| 
 | 
 | ||||||
|     return hasUpdates |     return hasUpdates | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   async update(values, options) { | ||||||
|  |     userCache.maybeInvalidate(this) | ||||||
|  |     return await super.update(values, options) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async save(options) { | ||||||
|  |     userCache.maybeInvalidate(this) | ||||||
|  |     return await super.save(options) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async destroy(options) { | ||||||
|  |     userCache.delete(this.id) | ||||||
|  |     await super.destroy(options) | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = User | module.exports = User | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user