Use a cache for published policies

This commit is contained in:
Travis Ralston 2019-07-10 18:34:21 -06:00
parent ae42d673d7
commit 852e737e33
2 changed files with 41 additions and 15 deletions

View File

@ -55,3 +55,4 @@ export const CACHE_WEBHOOKS_BRIDGE = "webhooks-bridge";
export const CACHE_GITTER_BRIDGE = "gitter-bridge"; export const CACHE_GITTER_BRIDGE = "gitter-bridge";
export const CACHE_SIMPLE_BOTS = "simple-bots"; export const CACHE_SIMPLE_BOTS = "simple-bots";
export const CACHE_SLACK_BRIDGE = "slack-bridge"; export const CACHE_SLACK_BRIDGE = "slack-bridge";
export const CACHE_TERMS = "terms";

View File

@ -4,6 +4,7 @@ import TermsRecord from "../../db/models/TermsRecord";
import TermsTextRecord from "../../db/models/TermsTextRecord"; import TermsTextRecord from "../../db/models/TermsTextRecord";
import TermsSignedRecord from "../../db/models/TermsSignedRecord"; import TermsSignedRecord from "../../db/models/TermsSignedRecord";
import { Op } from "sequelize"; import { Op } from "sequelize";
import { Cache, CACHE_TERMS } from "../../MemoryCache";
export interface ILanguagePolicy { export interface ILanguagePolicy {
name: string; name: string;
@ -33,6 +34,10 @@ export interface ITerms {
}; };
} }
export interface ICachedTerms extends ITerms {
id: number;
}
export const VERSION_DRAFT = "draft"; export const VERSION_DRAFT = "draft";
/** /**
@ -43,22 +48,19 @@ export default class TermsController {
constructor() { constructor() {
} }
public async doesUserNeedToSignTerms(user: IMSCUser): Promise<boolean> { private async getPublishedTerms(): Promise<ICachedTerms[]> {
return Object.keys((await this.getMissingTermsForUser(user)).policies).length > 0; const cache = Cache.for(CACHE_TERMS);
}
public async getMissingTermsForUser(user: IMSCUser): Promise<ITermsNotSignedResponse> { let terms = cache.get("published");
// TODO: Abuse a cache for non-draft policies if (terms) return terms;
// TODO: Upstream policies
const notDrafts = await TermsRecord.findAll({ terms = (await TermsRecord.findAll({
where: {version: {[Op.ne]: VERSION_DRAFT}}, where: {version: {[Op.ne]: VERSION_DRAFT}},
include: [TermsTextRecord], include: [TermsTextRecord],
}); }));
const signed = await TermsSignedRecord.findAll({where: {userId: user.userId}});
const latest: { [shortcode: string]: TermsRecord } = {}; const latest: { [shortcode: string]: TermsRecord } = {};
for (const record of notDrafts) { for (const record of terms) {
if (!latest[record.shortcode]) { if (!latest[record.shortcode]) {
latest[record.shortcode] = record; latest[record.shortcode] = record;
} }
@ -67,6 +69,27 @@ export default class TermsController {
} }
} }
terms = Object.values(latest).map(p => {
const mapped = this.mapPolicy(false, p);
return <ICachedTerms>Object.assign({}, mapped, {
id: p.id,
});
});
cache.put("published", terms);
return terms;
}
public async doesUserNeedToSignTerms(user: IMSCUser): Promise<boolean> {
return Object.keys((await this.getMissingTermsForUser(user)).policies).length > 0;
}
public async getMissingTermsForUser(user: IMSCUser): Promise<ITermsNotSignedResponse> {
// TODO: Upstream policies
const latest = await this.getPublishedTerms();
const signed = await TermsSignedRecord.findAll({where: {userId: user.userId}});
const missing = Object.values(latest).filter(d => !signed.find(s => s.termsId === d.id)); const missing = Object.values(latest).filter(d => !signed.find(s => s.termsId === d.id));
const policies: ITermsNotSignedResponse = {policies: {}}; const policies: ITermsNotSignedResponse = {policies: {}};
@ -75,10 +98,10 @@ export default class TermsController {
version: missingPolicy.version, version: missingPolicy.version,
}; };
for (const text of missingPolicy.texts) { for (const language in missingPolicy.languages) {
policies.policies[missingPolicy.shortcode][text.language] = { policies.policies[missingPolicy.shortcode][language] = {
name: text.name, name: missingPolicy.languages[language].name,
url: text.url, url: missingPolicy.languages[language].url,
}; };
} }
} }
@ -123,6 +146,7 @@ export default class TermsController {
termsText.name = name; termsText.name = name;
await termsText.save(); await termsText.save();
Cache.for(CACHE_TERMS).clear();
return this.mapPolicy(true, terms); return this.mapPolicy(true, terms);
} }
@ -136,6 +160,7 @@ export default class TermsController {
terms.version = targetVersion; terms.version = targetVersion;
await terms.save(); await terms.save();
Cache.for(CACHE_TERMS).clear();
return this.mapPolicy(true, terms); return this.mapPolicy(true, terms);
} }