1
1
mirror of https://github.com/kokonect-link/cherrypick synced 2024-12-02 16:58:43 +09:00

Bug fix and some refactoring

This commit is contained in:
syuilo 2018-10-25 16:10:48 +09:00
parent b1dead1186
commit 5918285326
No known key found for this signature in database
GPG Key ID: BDC4C49D06AB9D69

View File

@ -20,7 +20,6 @@ type ArrayValue<T> = {
type Span = 'day' | 'hour'; type Span = 'day' | 'hour';
//#region Chart Core
type Log<T extends Obj> = { type Log<T extends Obj> = {
_id: mongo.ObjectID; _id: mongo.ObjectID;
@ -87,13 +86,33 @@ export default abstract class Chart<T> {
} }
@autobind @autobind
private async getCurrentLog(span: Span, group?: any): Promise<Log<T>> { private getCurrentDate(): [number, number, number, number] {
const now = new Date(); const now = new Date();
const y = now.getFullYear(); const y = now.getFullYear();
const m = now.getMonth(); const m = now.getMonth();
const d = now.getDate(); const d = now.getDate();
const h = now.getHours(); const h = now.getHours();
return [y, m, d, h];
}
@autobind
private getLatestLog(span: Span, group?: any): Promise<Log<T>> {
return this.collection.findOne({
group: group,
span: span
}, {
sort: {
date: -1
}
});
}
@autobind
private async getCurrentLog(span: Span, group?: any): Promise<Log<T>> {
const [y, m, d, h] = this.getCurrentDate();
const current = const current =
span == 'day' ? new Date(y, m, d) : span == 'day' ? new Date(y, m, d) :
span == 'hour' ? new Date(y, m, d, h) : span == 'hour' ? new Date(y, m, d, h) :
@ -106,54 +125,56 @@ export default abstract class Chart<T> {
date: current date: current
}); });
if (currentLog) { // ログがあればそれを返して終了
if (currentLog != null) {
return currentLog; return currentLog;
} }
let log: Log<T>;
let data: T;
// 集計期間が変わってから、初めてのチャート更新なら // 集計期間が変わってから、初めてのチャート更新なら
// 最も最近のログを持ってくる // 最も最近のログを持ってくる
// * 例えば集計期間が「日」である場合で考えると、 // * 例えば集計期間が「日」である場合で考えると、
// * 昨日何もチャートを更新するような出来事がなかった場合は、 // * 昨日何もチャートを更新するような出来事がなかった場合は、
// * ログがそもそも作られずドキュメントが存在しないということがあり得るため、 // * ログがそもそも作られずドキュメントが存在しないということがあり得るため、
// * 「昨日の」と決め打ちせずに「もっとも最近の」とします // * 「昨日の」と決め打ちせずに「もっとも最近の」とします
const latest = await this.collection.findOne({ const latest = await this.getLatestLog(span, group);
group: group,
span: span
}, {
sort: {
date: -1
}
});
if (latest) { if (latest != null) {
// 現在のログを初期挿入 // 空ログデータを作成
const data = await this.getTemplate(false, latest.data); data = await this.getTemplate(false, latest.data);
const log = await this.collection.insert({
group: group,
span: span,
date: current,
data: data
});
return log;
} else { } else {
// ログが存在しなかったら // ログが存在しなかったら
// * Misskeyインスタンスを建てて初めてのチャート更新時など // (Misskeyインスタンスを建てて初めてのチャート更新時など
// または何らかの理由でチャートコレクションを抹消した場合)
// 空のログを作成 // 初期ログデータを作成
const data = await this.getTemplate(true, null, group); data = await this.getTemplate(true, null, group);
}
const log = await this.collection.insert({ try {
// 新規ログ挿入
log = await this.collection.insert({
group: group, group: group,
span: span, span: span,
date: current, date: current,
data: data data: data
}); });
} catch (e) {
// 11000 is duplicate key error
// 並列動作している他のチャートエンジンプロセスと処理が重なる場合がある
// その場合は再度最も新しいログを持ってくる
if (e.code === 11000) {
log = await this.getLatestLog(span, group);
} else {
console.error(e);
throw e;
}
}
return log; return log;
} }
}
@autobind @autobind
protected commit(query: Obj, group?: any, uniqueKey?: string, uniqueValue?: string): void { protected commit(query: Obj, group?: any, uniqueKey?: string, uniqueValue?: string): void {
@ -173,6 +194,7 @@ export default abstract class Chart<T> {
}; };
} }
// ログ更新
this.collection.update({ this.collection.update({
_id: log._id _id: log._id
}, query); }, query);
@ -200,16 +222,14 @@ export default abstract class Chart<T> {
public async getChart(span: Span, range: number, group?: any): Promise<ArrayValue<T>> { public async getChart(span: Span, range: number, group?: any): Promise<ArrayValue<T>> {
const promisedChart: Promise<T>[] = []; const promisedChart: Promise<T>[] = [];
const now = new Date(); const [y, m, d, h] = this.getCurrentDate();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
const h = now.getHours();
const gt = const gt =
span == 'day' ? new Date(y, m, d - range) : span == 'day' ? new Date(y, m, d - range) :
span == 'hour' ? new Date(y, m, d, h - range) : null; span == 'hour' ? new Date(y, m, d, h - range) :
null;
// ログ取得
const logs = await this.collection.find({ const logs = await this.collection.find({
group: group, group: group,
span: span, span: span,
@ -225,6 +245,7 @@ export default abstract class Chart<T> {
} }
}); });
// 整形
for (let i = (range - 1); i >= 0; i--) { for (let i = (range - 1); i >= 0; i--) {
const current = const current =
span == 'day' ? new Date(y, m, d - i) : span == 'day' ? new Date(y, m, d - i) :
@ -235,7 +256,8 @@ export default abstract class Chart<T> {
if (log) { if (log) {
promisedChart.unshift(Promise.resolve(log.data)); promisedChart.unshift(Promise.resolve(log.data));
} else { // 隙間埋め } else {
// 隙間埋め
const latest = logs.find(l => l.date.getTime() < current.getTime()); const latest = logs.find(l => l.date.getTime() < current.getTime());
promisedChart.unshift(this.getTemplate(false, latest ? latest.data : null)); promisedChart.unshift(this.getTemplate(false, latest ? latest.data : null));
} }
@ -282,4 +304,3 @@ export default abstract class Chart<T> {
return res; return res;
} }
} }
//#endregion