import { Injectable } from '@nestjs/common'; import { RedmineTypes } from '@app/redmine-types/index'; import { Timestamped } from '../models/timestamped'; import { Users } from '../couchdb-datasources/users'; import { RedmineDataLoader } from '../redmine-data-loader/redmine-data-loader'; import { TimestampNowFill } from '../utils/timestamp-now-fill'; import { RedmineUserCacheWriterService } from '../user-cache-writer/user-cache-writer.service'; import { TimestampIsTimeouted } from '../utils/timestamp-is-timeouted'; export const USER_MEMORY_CACHE_LIFETIME = 24 * 60 * 60 * 1000; @Injectable() export class UsersService { private memoryCache: Record = {}; constructor( private users: Users, private redmineDataLoader: RedmineDataLoader, private redmineUserCacheWriterService: RedmineUserCacheWriterService, ) {} async getUser(userId: number): Promise { const userFromMemoryCache = this.getUserFromMemoryCache(userId); if (userFromMemoryCache) { return userFromMemoryCache; } const userFromCache = await this.getUserFromCache(userId); if (userFromCache) { this.memoryCache[userId] = TimestampNowFill({ ...userFromCache }); return this.memoryCache[userId]; } let userFromRedmine = await this.getUserFromRedmine(userId); if (userFromRedmine) { userFromRedmine = await this.redmineUserCacheWriterService.saveUser( userFromRedmine, ); } const unknownUser = TimestampNowFill({ ...RedmineTypes.Unknown.user }); this.memoryCache[userId] = (userFromRedmine || unknownUser) as any; return this.memoryCache[userId]; } async getUserFromRedmine(userId: number): Promise { return await this.redmineDataLoader.loadUser(userId); } async getUserFromCache( userId: number, ): Promise<(RedmineTypes.User & Timestamped) | null> { const usersDb = await this.users.getDatasource(); try { return (await usersDb.get(String(userId))) as any; } catch (ex) { return null; } } getUserFromMemoryCache(userId: number): RedmineTypes.User | null { if ( this.memoryCache[userId] && !TimestampIsTimeouted( this.memoryCache[userId], USER_MEMORY_CACHE_LIFETIME, ) ) { return this.memoryCache[userId]; } return null; } }