diff --git a/src/server/api/endpoints/admin/resync-chart.ts b/src/server/api/endpoints/admin/resync-chart.ts new file mode 100644 index 000000000..7f4c5e03c --- /dev/null +++ b/src/server/api/endpoints/admin/resync-chart.ts @@ -0,0 +1,21 @@ +import define from '../../define'; +import { driveChart, notesChart, usersChart, instanceChart } from '../../../../services/chart'; +import { insertModerationLog } from '../../../../services/insert-moderation-log'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, +}; + +export default define(meta, async (ps, me) => { + insertModerationLog(me, 'chartResync'); + + driveChart.resync(); + notesChart.resync(); + usersChart.resync(); + instanceChart.resync(); + + // TODO: ユーザーごとのチャートもキューに入れて更新する +}); diff --git a/src/services/chart/charts/classes/test.ts b/src/services/chart/charts/classes/test.ts index 57c22822f..0ca63d174 100644 --- a/src/services/chart/charts/classes/test.ts +++ b/src/services/chart/charts/classes/test.ts @@ -6,7 +6,7 @@ import { name, schema } from '../schemas/test'; type TestLog = SchemaType; export default class TestChart extends Chart { - private total = 0; + public total = 0; // publicにするのはテストのため constructor() { super(name, schema); diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts index 60ba1ebb4..9dc250f75 100644 --- a/src/services/chart/core.ts +++ b/src/services/chart/core.ts @@ -65,7 +65,7 @@ export default abstract class Chart> { public schema: Schema; protected repository: Repository; protected abstract genNewLog(latest: T): DeepPartial; - protected abstract async fetchActual(group?: string): Promise>; + protected abstract async fetchActual(group: string | null): Promise>; @autobind private static convertSchemaToFlatColumnDefinitions(schema: Schema) { @@ -341,6 +341,24 @@ export default abstract class Chart> { ]); } + @autobind + public async resync(group: string | null = null): Promise { + const data = await this.fetchActual(group); + + const update = async (log: Log) => { + await this.repository.createQueryBuilder() + .update() + .set(Chart.convertObjectToFlattenColumns(data)) + .where('id = :id', { id: log.id }) + .execute(); + }; + + return Promise.all([ + this.getCurrentLog('day', group).then(log => update(log)), + this.getCurrentLog('hour', group).then(log => update(log)), + ]); + } + @autobind protected async inc(inc: DeepPartial, group: string | null = null): Promise { await this.commit(Chart.convertQuery(inc as any), group); diff --git a/test/chart.ts b/test/chart.ts index 28f34193f..bd26f3bf3 100644 --- a/test/chart.ts +++ b/test/chart.ts @@ -320,4 +320,60 @@ describe('Chart', () => { }); })); }); + + describe('Resync', () => { + it('Can resync', async(async () => { + testChart.total = 1; + + await testChart.resync(); + + const chartHours = await testChart.getChart('hour', 3); + const chartDays = await testChart.getChart('day', 3); + + assert.deepStrictEqual(chartHours, { + foo: { + dec: [0, 0, 0], + inc: [0, 0, 0], + total: [1, 0, 0] + }, + }); + + assert.deepStrictEqual(chartDays, { + foo: { + dec: [0, 0, 0], + inc: [0, 0, 0], + total: [1, 0, 0] + }, + }); + })); + + it('Can resync (2)', async(async () => { + await testChart.increment(); + + clock.tick('01:00:00'); + + testChart.total = 100; + + await testChart.resync(); + + const chartHours = await testChart.getChart('hour', 3); + const chartDays = await testChart.getChart('day', 3); + + assert.deepStrictEqual(chartHours, { + foo: { + dec: [0, 0, 0], + inc: [0, 1, 0], + total: [100, 1, 0] + }, + }); + + assert.deepStrictEqual(chartDays, { + foo: { + dec: [0, 0, 0], + inc: [1, 0, 0], + total: [100, 0, 0] + }, + }); + })); + }); });