diff --git a/src/misc/app-lock.ts b/src/misc/app-lock.ts index 3d5ff91882238e9efbeed0bde2e80fbe53c311db..ca2181f87998d6e5cee11c9a75c2db58739b2400 100644 --- a/src/misc/app-lock.ts +++ b/src/misc/app-lock.ts @@ -24,3 +24,7 @@ export function getApLock(uri: string, timeout = 30 * 1000) { export function getNodeinfoLock(host: string, timeout = 30 * 1000) { return lock(`nodeinfo:${host}`, timeout); } + +export function getChartInsertLock(lockKey: string, timeout = 30 * 1000) { + return lock(`chart-insert:${lockKey}`, timeout); +} diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts index 088c52478091001600282b713babc2e6dd267d35..f471a9920c39d7bf12765f0f73c281685072158b 100644 --- a/src/services/chart/core.ts +++ b/src/services/chart/core.ts @@ -9,8 +9,8 @@ import autobind from 'autobind-decorator'; import Logger from '../logger'; import { Schema } from '../../misc/schema'; import { EntitySchema, getRepository, Repository, LessThan, MoreThanOrEqual } from 'typeorm'; -import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error'; import { DateUTC, isTimeSame, isTimeBefore, subtractTimespan } from '../../prelude/time'; +import { getChartInsertLock } from '../../misc/app-lock'; const logger = new Logger('chart', 'white', process.env.NODE_ENV !== 'test'); @@ -283,30 +283,35 @@ export default abstract class Chart<T extends Record<string, any>> { logger.info(`${this.name + (group ? `:${group}` : '')} (${span}): Initial commit created`); } + const date = Chart.dateToTimestamp(current); + const lockKey = `${this.name}:${date}:${group}:${span}`; + + const unlock = await getChartInsertLock(lockKey); try { + // ãƒãƒƒã‚¯å†…ã§ã‚‚ã†1回ãƒã‚§ãƒƒã‚¯ã™ã‚‹ + const currentLog = await this.repository.findOne({ + span: span, + date: date, + ...(group ? { group: group } : {}) + }); + + // ãƒã‚°ãŒã‚ã‚Œã°ãれを返ã—ã¦çµ‚了 + if (currentLog != null) return currentLog; + // æ–°è¦ãƒã‚°æŒ¿å…¥ log = await this.repository.save({ group: group, span: span, - date: Chart.dateToTimestamp(current), + date: date, ...Chart.convertObjectToFlattenColumns(data) }); logger.info(`${this.name + (group ? `:${group}` : '')} (${span}): New commit created`); - } catch (e) { - // duplicate key error - // 並列動作ã—ã¦ã„ã‚‹ä»–ã®ãƒãƒ£ãƒ¼ãƒˆã‚¨ãƒ³ã‚¸ãƒ³ãƒ—ãƒã‚»ã‚¹ã¨å‡¦ç†ãŒé‡ãªã‚‹å ´åˆãŒã‚ã‚‹ - // ãã®å ´åˆã¯å†åº¦æœ€ã‚‚æ–°ã—ã„ãƒã‚°ã‚’æŒã£ã¦ãã‚‹ - if (isDuplicateKeyValueError(e)) { - log = await this.getLatestLog(span, group) as Log; - logger.info(`${this.name + (group ? `:${group}` : '')} (${span}): Commit duplicated`); - } else { - logger.error(e); - throw e; - } - } - return log; + return log; + } finally { + unlock(); + } } @autobind