This commit is contained in:
syuilo 2020-03-07 11:23:31 +09:00
parent 49a5b4eb14
commit 917726fecc
16 changed files with 96 additions and 105 deletions

View file

@ -1,13 +1,11 @@
const dateTimeIntervals = { const dateTimeIntervals = {
'day': 86400000, 'day': 86400000,
'hour': 3600000, 'hour': 3600000,
'ms': 1,
}; };
export function DateUTC(time: number[]): Date { export function dateUTC(time: number[]): Date {
const r = new Date(0); return new Date(Date.UTC(...time));
r.setUTCFullYear(time[0], time[1], time[2]);
if (time[3]) r.setUTCHours(time[3], ...time.slice(4));
return r;
} }
export function isTimeSame(a: Date, b: Date): boolean { export function isTimeSame(a: Date, b: Date): boolean {
@ -22,10 +20,10 @@ export function isTimeAfter(a: Date, b: Date): boolean {
return (a.getTime() - b.getTime()) > 0; return (a.getTime() - b.getTime()) > 0;
} }
export function addTimespan(x: Date, value: number, span: keyof typeof dateTimeIntervals): Date { export function addTime(x: Date, value: number, span: keyof typeof dateTimeIntervals = 'ms'): Date {
return new Date(x.getTime() + (value * dateTimeIntervals[span])); return new Date(x.getTime() + (value * dateTimeIntervals[span]));
} }
export function subtractTimespan(x: Date, value: number, span: keyof typeof dateTimeIntervals): Date { export function subtractTime(x: Date, value: number, span: keyof typeof dateTimeIntervals = 'ms'): Date {
return new Date(x.getTime() - (value * dateTimeIntervals[span])); return new Date(x.getTime() - (value * dateTimeIntervals[span]));
} }

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
}, },
@ -36,5 +36,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await activeUsersChart.getChart(ps.span as any, ps.limit!, ps.offset!); return await activeUsersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
}, },
@ -36,5 +36,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await driveChart.getChart(ps.span as any, ps.limit!, ps.offset!); return await driveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
}, },
@ -36,5 +36,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await federationChart.getChart(ps.span as any, ps.limit!, ps.offset!); return await federationChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
tag: { tag: {
@ -43,5 +43,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.offset!, ps.tag); return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.tag);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
host: { host: {
@ -44,5 +44,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await instanceChart.getChart(ps.span as any, ps.limit!, ps.offset!, ps.host); return await instanceChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.host);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
}, },
@ -36,5 +36,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await networkChart.getChart(ps.span as any, ps.limit!, ps.offset!); return await networkChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
}, },
@ -36,5 +36,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await notesChart.getChart(ps.span as any, ps.limit!, ps.offset!); return await notesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
}); });

View file

@ -28,8 +28,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
userId: { userId: {
@ -45,5 +45,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.offset!, ps.userId); return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
}); });

View file

@ -28,8 +28,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
userId: { userId: {
@ -45,5 +45,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.offset!, ps.userId); return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
}); });

View file

@ -28,8 +28,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
userId: { userId: {
@ -45,5 +45,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.offset!, ps.userId); return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
}); });

View file

@ -28,8 +28,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
userId: { userId: {
@ -45,5 +45,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.offset!, ps.userId); return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
}); });

View file

@ -27,8 +27,8 @@ export const meta = {
}, },
offset: { offset: {
validator: $.optional.num, validator: $.optional.nullable.num,
default: 0, default: null,
}, },
}, },
@ -36,5 +36,5 @@ export const meta = {
}; };
export default define(meta, async (ps) => { export default define(meta, async (ps) => {
return await usersChart.getChart(ps.span as any, ps.limit!, ps.offset!); return await usersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
}); });

View file

@ -60,9 +60,9 @@ export default define(meta, async () => {
Notes.count({ where: { userHost: null }, cache: 3600000 }), Notes.count({ where: { userHost: null }, cache: 3600000 }),
Users.count({ cache: 3600000 }), Users.count({ cache: 3600000 }),
Users.count({ where: { host: null }, cache: 3600000 }), Users.count({ where: { host: null }, cache: 3600000 }),
federationChart.getChart('hour', 1, 0).then(chart => chart.instance.total[0]), federationChart.getChart('hour', 1, null).then(chart => chart.instance.total[0]),
driveChart.getChart('hour', 1, 0).then(chart => chart.local.totalSize[0]), driveChart.getChart('hour', 1, null).then(chart => chart.local.totalSize[0]),
driveChart.getChart('hour', 1, 0).then(chart => chart.remote.totalSize[0]), driveChart.getChart('hour', 1, null).then(chart => chart.remote.totalSize[0]),
]); ]);
return { return {

View file

@ -8,8 +8,8 @@ import * as nestedProperty from 'nested-property';
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Logger from '../logger'; import Logger from '../logger';
import { Schema } from '../../misc/schema'; import { Schema } from '../../misc/schema';
import { EntitySchema, getRepository, Repository, LessThan, MoreThanOrEqual, Between } from 'typeorm'; import { EntitySchema, getRepository, Repository, LessThan, Between } from 'typeorm';
import { DateUTC, isTimeSame, isTimeBefore, subtractTimespan } from '../../prelude/time'; import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '../../prelude/time';
import { getChartInsertLock } from '../../misc/app-lock'; import { getChartInsertLock } from '../../misc/app-lock';
const logger = new Logger('chart', 'white', process.env.NODE_ENV !== 'test'); const logger = new Logger('chart', 'white', process.env.NODE_ENV !== 'test');
@ -134,18 +134,21 @@ export default abstract class Chart<T extends Record<string, any>> {
} }
@autobind @autobind
private static dateToYMDH(date: Date): [number, number, number, number] { private static parseDate(date: Date): [number, number, number, number, number, number, number] {
const y = date.getUTCFullYear(); const y = date.getUTCFullYear();
const m = date.getUTCMonth(); const m = date.getUTCMonth();
const d = date.getUTCDate(); const d = date.getUTCDate();
const h = date.getUTCHours(); const h = date.getUTCHours();
const _m = date.getUTCMinutes();
const _s = date.getUTCSeconds();
const _ms = date.getUTCMilliseconds();
return [y, m, d, h]; return [y, m, d, h, _m, _s, _ms];
} }
@autobind @autobind
private static getCurrentDate(): [number, number, number, number] { private static getCurrentDate() {
return Chart.dateToYMDH(new Date()); return Chart.parseDate(new Date());
} }
@autobind @autobind
@ -243,8 +246,8 @@ export default abstract class Chart<T extends Record<string, any>> {
const [y, m, d, h] = Chart.getCurrentDate(); const [y, m, d, h] = Chart.getCurrentDate();
const current = const current =
span == 'day' ? DateUTC([y, m, d]) : span == 'day' ? dateUTC([y, m, d, 0]) :
span == 'hour' ? DateUTC([y, m, d, h]) : span == 'hour' ? dateUTC([y, m, d, h]) :
null as never; null as never;
// 現在(今日または今のHour)のログ // 現在(今日または今のHour)のログ
@ -381,23 +384,15 @@ export default abstract class Chart<T extends Record<string, any>> {
} }
@autobind @autobind
public async getChart(span: Span, amount: number, offset: number, group: string | null = null): Promise<ArrayValue<T>> { public async getChart(span: Span, amount: number, begin: Date | null, group: string | null = null): Promise<ArrayValue<T>> {
let [y, m, d, h] = Chart.getCurrentDate(); const [y, m, d, h, _m, _s, _ms] = begin ? Chart.parseDate(subtractTime(addTime(begin, 1, span), 1)) : Chart.getCurrentDate();
const [y2, m2, d2, h2] = begin ? Chart.parseDate(addTime(begin, 1, span)) : [] as never;
let lt: Date = null as never; const lt = dateUTC([y, m, d, h, _m, _s, _ms]);
if (offset > 0) {
[y, m, d, h] = Chart.dateToYMDH(subtractTimespan(DateUTC([y, m, d, h]), offset, span));
lt =
span === 'day' ? DateUTC([y, m, d]) :
span === 'hour' ? DateUTC([y, m, d, h]) :
null as never;
}
const gt = const gt =
span === 'day' ? subtractTimespan(DateUTC([y, m, d]), amount - 1, 'day') : span === 'day' ? subtractTime(begin ? dateUTC([y2, m2, d2, 0]) : dateUTC([y, m, d, 0]), amount - 1, 'day') :
span === 'hour' ? subtractTimespan(DateUTC([y, m, d, h]), amount - 1, 'hour') : span === 'hour' ? subtractTime(begin ? dateUTC([y2, m2, d2, h2]) : dateUTC([y, m, d, h]), amount - 1, 'hour') :
null as never; null as never;
// ログ取得 // ログ取得
@ -405,9 +400,7 @@ export default abstract class Chart<T extends Record<string, any>> {
where: { where: {
group: group, group: group,
span: span, span: span,
date: offset === 0 date: Between(Chart.dateToTimestamp(gt), Chart.dateToTimestamp(lt))
? MoreThanOrEqual(Chart.dateToTimestamp(gt))
: Between(Chart.dateToTimestamp(gt), Chart.dateToTimestamp(lt))
}, },
order: { order: {
date: -1 date: -1
@ -455,8 +448,8 @@ export default abstract class Chart<T extends Record<string, any>> {
// 整形 // 整形
for (let i = (amount - 1); i >= 0; i--) { for (let i = (amount - 1); i >= 0; i--) {
const current = const current =
span == 'day' ? subtractTimespan(DateUTC([y, m, d]), i, 'day') : span === 'day' ? subtractTime(dateUTC([y, m, d, 0]), i, 'day') :
span == 'hour' ? subtractTimespan(DateUTC([y, m, d, h]), i, 'hour') : span === 'hour' ? subtractTime(dateUTC([y, m, d, h]), i, 'hour') :
null as never; null as never;
const log = logs.find(l => isTimeSame(new Date(l.date * 1000), current)); const log = logs.find(l => isTimeSame(new Date(l.date * 1000), current));

View file

@ -86,8 +86,8 @@ describe('Chart', () => {
it('Can updates', async(async () => { it('Can updates', async(async () => {
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -109,8 +109,8 @@ describe('Chart', () => {
it('Can updates (dec)', async(async () => { it('Can updates (dec)', async(async () => {
await testChart.decrement(); await testChart.decrement();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -130,8 +130,8 @@ describe('Chart', () => {
})); }));
it('Empty chart', async(async () => { it('Empty chart', async(async () => {
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -155,8 +155,8 @@ describe('Chart', () => {
await testChart.increment(); await testChart.increment();
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -182,8 +182,8 @@ describe('Chart', () => {
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -209,8 +209,8 @@ describe('Chart', () => {
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -235,8 +235,8 @@ describe('Chart', () => {
clock.tick('05:00:00'); clock.tick('05:00:00');
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -262,8 +262,8 @@ describe('Chart', () => {
clock.tick('05:00:00'); clock.tick('05:00:00');
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -289,8 +289,8 @@ describe('Chart', () => {
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 1); const chartHours = await testChart.getChart('hour', 3, new Date(Date.UTC(2000, 0, 1, 0, 0, 0)));
const chartDays = await testChart.getChart('day', 3, 1); const chartDays = await testChart.getChart('day', 3, new Date(Date.UTC(2000, 0, 1, 0, 0, 0)));
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -303,8 +303,8 @@ describe('Chart', () => {
assert.deepStrictEqual(chartDays, { assert.deepStrictEqual(chartDays, {
foo: { foo: {
dec: [0, 0, 0], dec: [0, 0, 0],
inc: [0, 0, 0], inc: [2, 0, 0],
total: [0, 0, 0] total: [2, 0, 0]
}, },
}); });
})); }));
@ -318,8 +318,8 @@ describe('Chart', () => {
await testChart.increment(); await testChart.increment();
const chartHours = await testChart.getChart('hour', 3, 1); const chartHours = await testChart.getChart('hour', 3, new Date(Date.UTC(2000, 0, 1, 0, 0, 0)));
const chartDays = await testChart.getChart('day', 3, 1); const chartDays = await testChart.getChart('day', 3, new Date(Date.UTC(2000, 0, 1, 0, 0, 0)));
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -342,10 +342,10 @@ describe('Chart', () => {
it('Can updates', async(async () => { it('Can updates', async(async () => {
await testGroupedChart.increment('alice'); await testGroupedChart.increment('alice');
const aliceChartHours = await testGroupedChart.getChart('hour', 3, 0, 'alice'); const aliceChartHours = await testGroupedChart.getChart('hour', 3, null, 'alice');
const aliceChartDays = await testGroupedChart.getChart('day', 3, 0, 'alice'); const aliceChartDays = await testGroupedChart.getChart('day', 3, null, 'alice');
const bobChartHours = await testGroupedChart.getChart('hour', 3, 0, 'bob'); const bobChartHours = await testGroupedChart.getChart('hour', 3, null, 'bob');
const bobChartDays = await testGroupedChart.getChart('day', 3, 0, 'bob'); const bobChartDays = await testGroupedChart.getChart('day', 3, null, 'bob');
assert.deepStrictEqual(aliceChartHours, { assert.deepStrictEqual(aliceChartHours, {
foo: { foo: {
@ -387,8 +387,8 @@ describe('Chart', () => {
await testUniqueChart.uniqueIncrement('alice'); await testUniqueChart.uniqueIncrement('alice');
await testUniqueChart.uniqueIncrement('bob'); await testUniqueChart.uniqueIncrement('bob');
const chartHours = await testUniqueChart.getChart('hour', 3, 0); const chartHours = await testUniqueChart.getChart('hour', 3, null);
const chartDays = await testUniqueChart.getChart('day', 3, 0); const chartDays = await testUniqueChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: [2, 0, 0], foo: [2, 0, 0],
@ -406,8 +406,8 @@ describe('Chart', () => {
await testChart.resync(); await testChart.resync();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {
@ -435,8 +435,8 @@ describe('Chart', () => {
await testChart.resync(); await testChart.resync();
const chartHours = await testChart.getChart('hour', 3, 0); const chartHours = await testChart.getChart('hour', 3, null);
const chartDays = await testChart.getChart('day', 3, 0); const chartDays = await testChart.getChart('day', 3, null);
assert.deepStrictEqual(chartHours, { assert.deepStrictEqual(chartHours, {
foo: { foo: {