70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
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<number, RedmineTypes.User & Timestamped> = {};
|
|
|
|
constructor(
|
|
private users: Users,
|
|
private redmineDataLoader: RedmineDataLoader,
|
|
private redmineUserCacheWriterService: RedmineUserCacheWriterService,
|
|
) {}
|
|
|
|
async getUser(userId: number): Promise<RedmineTypes.User> {
|
|
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<RedmineTypes.User | null> {
|
|
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;
|
|
}
|
|
}
|