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

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;
}
}