pinkmine/libs/event-emitter/src/users/users.service.ts

85 lines
2.7 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { Users } from '../couchdb-datasources/users';
import { RedmineDataLoader } from '../redmine-data-loader/redmine-data-loader';
import { RedmineUserCacheWriterService } from '../user-cache-writer/user-cache-writer.service';
import { RedmineTypes } from '../models/redmine-types';
import { MemoryCache } from '../utils/memory-cache';
export const USER_MEMORY_CACHE_LIFETIME = 24 * 60 * 60 * 1000;
const USER_MEMORY_CACHE_AUTOCLEAN_INTERVAL = 1000 * 60 * 5;
@Injectable()
export class UsersService {
private logger = new Logger(UsersService.name);
private memoryCache = new MemoryCache<number, RedmineTypes.User>(
USER_MEMORY_CACHE_LIFETIME,
USER_MEMORY_CACHE_AUTOCLEAN_INTERVAL,
);
constructor(
private users: Users,
private redmineDataLoader: RedmineDataLoader,
private redmineUserCacheWriterService: RedmineUserCacheWriterService,
) {}
async getUser(userId: number): Promise<RedmineTypes.PublicUser> {
const userFromMemoryCache = this.getUserFromMemoryCache(userId);
if (userFromMemoryCache) {
return RedmineTypes.CreatePublicUserFromUser(userFromMemoryCache);
}
const userFromCache = await this.getUserFromCache(userId);
if (userFromCache) {
this.memoryCache.set(userId, userFromCache);
return RedmineTypes.CreatePublicUserFromUser(userFromCache);
}
let userFromRedmine = await this.getUserFromRedmine(userId);
if (userFromRedmine) {
userFromRedmine = await this.redmineUserCacheWriterService.saveUser(
userFromRedmine,
);
}
return RedmineTypes.CreatePublicUserFromUser(
this.memoryCache.set(
userId,
userFromRedmine || RedmineTypes.Unknown.user,
),
);
}
private async getUserFromRedmine(
userId: number,
): Promise<RedmineTypes.User | null> {
const user = await this.redmineDataLoader.loadUser(userId);
if (user) {
this.logger.debug(
`Get user from redmine with userId = ${userId}, login = ${user.login}`,
);
}
return user;
}
private async getUserFromCache(
userId: number,
): Promise<RedmineTypes.User | null> {
const usersDb = await this.users.getDatasource();
try {
const user = (await usersDb.get(String(userId))) as any;
this.logger.debug(
`Get user from couchdb with userId = ${userId}, login = ${user.login}`,
);
return user;
} catch (ex) {
return null;
}
}
private getUserFromMemoryCache(userId: number): RedmineTypes.User | null {
const user = this.memoryCache.get(userId);
if (user) {
this.logger.debug(
`Get user from memory cache with userId = ${userId}, login = ${user.login}`,
);
}
return user;
}
}