update deps (MisskeyIO#889)
- メンテナンスされないredis-lockを自前実装に変更 - 既にロックされている場合のリトライ間隔を調整
This commit is contained in:
parent
5f6cbe048a
commit
68c3eb5b5d
35 changed files with 546 additions and 517 deletions
|
@ -6,7 +6,7 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/MisskeyIO/misskey.git"
|
"url": "https://github.com/MisskeyIO/misskey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.15.3",
|
"packageManager": "pnpm@9.15.4",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/frontend",
|
"packages/frontend",
|
||||||
"packages/backend",
|
"packages/backend",
|
||||||
|
@ -63,19 +63,19 @@
|
||||||
"cssnano": "7.0.6",
|
"cssnano": "7.0.6",
|
||||||
"execa": "9.5.2",
|
"execa": "9.5.2",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"postcss": "8.4.49",
|
"postcss": "8.5.1",
|
||||||
"terser": "5.37.0",
|
"terser": "5.37.0",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||||
"@typescript-eslint/parser": "7.10.0",
|
"@typescript-eslint/parser": "7.10.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "13.17.0",
|
"cypress": "13.17.0",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"start-server-and-test": "2.0.9"
|
"start-server-and-test": "2.0.10"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tensorflow/tfjs-core": "4.22.0"
|
"@tensorflow/tfjs-core": "4.22.0"
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"blurhash": "2.0.5",
|
"blurhash": "2.0.5",
|
||||||
"body-parser": "1.20.3",
|
"body-parser": "1.20.3",
|
||||||
"bullmq": "5.34.9",
|
"bullmq": "5.34.10",
|
||||||
"cacheable-lookup": "7.0.0",
|
"cacheable-lookup": "7.0.0",
|
||||||
"cbor": "10.0.3",
|
"cbor": "10.0.3",
|
||||||
"chalk": "5.4.1",
|
"chalk": "5.4.1",
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"jsonld": "8.3.3",
|
"jsonld": "8.3.3",
|
||||||
"jsrsasign": "11.1.0",
|
"jsrsasign": "11.1.0",
|
||||||
"meilisearch": "0.47.0",
|
"meilisearch": "0.48.0",
|
||||||
"mfm-js": "0.24.0",
|
"mfm-js": "0.24.0",
|
||||||
"microformats-parser": "2.0.2",
|
"microformats-parser": "2.0.2",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
|
@ -163,7 +163,6 @@
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"re2": "1.21.4",
|
"re2": "1.21.4",
|
||||||
"redis-lock": "0.1.4",
|
|
||||||
"reflect-metadata": "0.2.2",
|
"reflect-metadata": "0.2.2",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
"rss-parser": "3.13.0",
|
"rss-parser": "3.13.0",
|
||||||
|
@ -210,7 +209,7 @@
|
||||||
"@types/jsrsasign": "10.5.15",
|
"@types/jsrsasign": "10.5.15",
|
||||||
"@types/mime-types": "2.1.4",
|
"@types/mime-types": "2.1.4",
|
||||||
"@types/ms": "0.7.34",
|
"@types/ms": "0.7.34",
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@types/node-forge": "1.3.11",
|
"@types/node-forge": "1.3.11",
|
||||||
"@types/nodemailer": "6.4.17",
|
"@types/nodemailer": "6.4.17",
|
||||||
"@types/oauth": "0.9.6",
|
"@types/oauth": "0.9.6",
|
||||||
|
|
13
packages/backend/src/@types/redis-lock.d.ts
vendored
13
packages/backend/src/@types/redis-lock.d.ts
vendored
|
@ -1,13 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module 'redis-lock' {
|
|
||||||
import type Redis from 'ioredis';
|
|
||||||
|
|
||||||
type Lock = (lockName: string, timeout?: number, taskToPerform?: () => Promise<void>) => void;
|
|
||||||
function redisLock(client: Redis.Redis, retryDelay: number): Lock;
|
|
||||||
|
|
||||||
export = redisLock;
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { promisify } from 'node:util';
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
|
||||||
import redisLock from 'redis-lock';
|
|
||||||
import * as Redis from 'ioredis';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
|
||||||
import { bindThis } from '@/decorators.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retry delay (ms) for lock acquisition
|
|
||||||
*/
|
|
||||||
const retryDelay = 100;
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AppLockService {
|
|
||||||
private lock: (key: string, timeout?: number, _?: (() => Promise<void>) | undefined) => Promise<() => void>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
@Inject(DI.redis)
|
|
||||||
private redisClient: Redis.Redis,
|
|
||||||
) {
|
|
||||||
this.lock = promisify(redisLock(this.redisClient, retryDelay));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get AP Object lock
|
|
||||||
* @param uri AP object ID
|
|
||||||
* @param timeout Lock timeout (ms), The timeout releases previous lock.
|
|
||||||
* @returns Unlock function
|
|
||||||
*/
|
|
||||||
@bindThis
|
|
||||||
public getApLock(uri: string, timeout = 30 * 1000): Promise<() => void> {
|
|
||||||
return this.lock(`ap-object:${uri}`, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public getChartInsertLock(lockKey: string, timeout = 30 * 1000): Promise<() => void> {
|
|
||||||
return this.lock(`chart-insert:${lockKey}`, timeout);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,6 @@ import { AccountUpdateService } from './AccountUpdateService.js';
|
||||||
import { AiService } from './AiService.js';
|
import { AiService } from './AiService.js';
|
||||||
import { AnnouncementService } from './AnnouncementService.js';
|
import { AnnouncementService } from './AnnouncementService.js';
|
||||||
import { AntennaService } from './AntennaService.js';
|
import { AntennaService } from './AntennaService.js';
|
||||||
import { AppLockService } from './AppLockService.js';
|
|
||||||
import { AchievementService } from './AchievementService.js';
|
import { AchievementService } from './AchievementService.js';
|
||||||
import { AvatarDecorationService } from './AvatarDecorationService.js';
|
import { AvatarDecorationService } from './AvatarDecorationService.js';
|
||||||
import { CaptchaService } from './CaptchaService.js';
|
import { CaptchaService } from './CaptchaService.js';
|
||||||
|
@ -149,7 +148,6 @@ const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useEx
|
||||||
const $AiService: Provider = { provide: 'AiService', useExisting: AiService };
|
const $AiService: Provider = { provide: 'AiService', useExisting: AiService };
|
||||||
const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService };
|
const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService };
|
||||||
const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService };
|
const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService };
|
||||||
const $AppLockService: Provider = { provide: 'AppLockService', useExisting: AppLockService };
|
|
||||||
const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService };
|
const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService };
|
||||||
const $AvatarDecorationService: Provider = { provide: 'AvatarDecorationService', useExisting: AvatarDecorationService };
|
const $AvatarDecorationService: Provider = { provide: 'AvatarDecorationService', useExisting: AvatarDecorationService };
|
||||||
const $CaptchaService: Provider = { provide: 'CaptchaService', useExisting: CaptchaService };
|
const $CaptchaService: Provider = { provide: 'CaptchaService', useExisting: CaptchaService };
|
||||||
|
@ -292,7 +290,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
|
||||||
AiService,
|
AiService,
|
||||||
AnnouncementService,
|
AnnouncementService,
|
||||||
AntennaService,
|
AntennaService,
|
||||||
AppLockService,
|
|
||||||
AchievementService,
|
AchievementService,
|
||||||
AvatarDecorationService,
|
AvatarDecorationService,
|
||||||
CaptchaService,
|
CaptchaService,
|
||||||
|
@ -429,7 +426,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
|
||||||
$AiService,
|
$AiService,
|
||||||
$AnnouncementService,
|
$AnnouncementService,
|
||||||
$AntennaService,
|
$AntennaService,
|
||||||
$AppLockService,
|
|
||||||
$AchievementService,
|
$AchievementService,
|
||||||
$AvatarDecorationService,
|
$AvatarDecorationService,
|
||||||
$CaptchaService,
|
$CaptchaService,
|
||||||
|
@ -567,7 +563,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
|
||||||
AiService,
|
AiService,
|
||||||
AnnouncementService,
|
AnnouncementService,
|
||||||
AntennaService,
|
AntennaService,
|
||||||
AppLockService,
|
|
||||||
AchievementService,
|
AchievementService,
|
||||||
AvatarDecorationService,
|
AvatarDecorationService,
|
||||||
CaptchaService,
|
CaptchaService,
|
||||||
|
@ -703,7 +698,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
|
||||||
$AiService,
|
$AiService,
|
||||||
$AnnouncementService,
|
$AnnouncementService,
|
||||||
$AntennaService,
|
$AntennaService,
|
||||||
$AppLockService,
|
|
||||||
$AchievementService,
|
$AchievementService,
|
||||||
$AvatarDecorationService,
|
$AvatarDecorationService,
|
||||||
$CaptchaService,
|
$CaptchaService,
|
||||||
|
|
|
@ -376,7 +376,10 @@ export class QueueService {
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public createReportAbuseJob(report: MiAbuseUserReport) {
|
public createReportAbuseJob(report: MiAbuseUserReport) {
|
||||||
return this.dbQueue.add('reportAbuse', report);
|
return this.dbQueue.add('reportAbuse', report, {
|
||||||
|
removeOnComplete: true,
|
||||||
|
removeOnFail: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
||||||
|
@ -14,8 +15,8 @@ import { NotePiningService } from '@/core/NotePiningService.js';
|
||||||
import { UserBlockingService } from '@/core/UserBlockingService.js';
|
import { UserBlockingService } from '@/core/UserBlockingService.js';
|
||||||
import { NoteDeleteService } from '@/core/NoteDeleteService.js';
|
import { NoteDeleteService } from '@/core/NoteDeleteService.js';
|
||||||
import { NoteCreateService } from '@/core/NoteCreateService.js';
|
import { NoteCreateService } from '@/core/NoteCreateService.js';
|
||||||
|
import { acquireApObjectLock } from '@/misc/distributed-lock.js';
|
||||||
import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js';
|
import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
|
@ -49,6 +50,9 @@ export class ApInboxService {
|
||||||
@Inject(DI.config)
|
@Inject(DI.config)
|
||||||
private config: Config,
|
private config: Config,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@ -77,7 +81,6 @@ export class ApInboxService {
|
||||||
private userBlockingService: UserBlockingService,
|
private userBlockingService: UserBlockingService,
|
||||||
private noteCreateService: NoteCreateService,
|
private noteCreateService: NoteCreateService,
|
||||||
private noteDeleteService: NoteDeleteService,
|
private noteDeleteService: NoteDeleteService,
|
||||||
private appLockService: AppLockService,
|
|
||||||
private apResolverService: ApResolverService,
|
private apResolverService: ApResolverService,
|
||||||
private apDbResolverService: ApDbResolverService,
|
private apDbResolverService: ApDbResolverService,
|
||||||
private apLoggerService: ApLoggerService,
|
private apLoggerService: ApLoggerService,
|
||||||
|
@ -312,7 +315,7 @@ export class ApInboxService {
|
||||||
const meta = await this.metaService.fetch();
|
const meta = await this.metaService.fetch();
|
||||||
if (this.utilityService.isItemListedIn(this.utilityService.extractHost(uri), meta.blockedHosts)) return 'skip: blocked host';
|
if (this.utilityService.isItemListedIn(this.utilityService.extractHost(uri), meta.blockedHosts)) return 'skip: blocked host';
|
||||||
|
|
||||||
const unlock = await this.appLockService.getApLock(uri);
|
const unlock = await acquireApObjectLock(this.redisForTimelines, uri);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 既に同じURIを持つものが登録されていないかチェック
|
// 既に同じURIを持つものが登録されていないかチェック
|
||||||
|
@ -440,7 +443,7 @@ export class ApInboxService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unlock = await this.appLockService.getApLock(uri);
|
const unlock = await acquireApObjectLock(this.redisForTimelines, uri);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const exist = await this.apNoteService.fetchNote(note);
|
const exist = await this.apNoteService.fetchNote(note);
|
||||||
|
@ -543,7 +546,7 @@ export class ApInboxService {
|
||||||
private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> {
|
private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> {
|
||||||
this.logger.info(`Deleting the Note: ${uri}`);
|
this.logger.info(`Deleting the Note: ${uri}`);
|
||||||
|
|
||||||
const unlock = await this.appLockService.getApLock(uri);
|
const unlock = await acquireApObjectLock(this.redisForTimelines, uri);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const note = await this.apDbResolverService.getNoteFromApId(uri);
|
const note = await this.apDbResolverService.getNoteFromApId(uri);
|
||||||
|
@ -813,7 +816,7 @@ export class ApInboxService {
|
||||||
return 'ok: Question updated';
|
return 'ok: Question updated';
|
||||||
} else if (additionalCc && isPost(object)) {
|
} else if (additionalCc && isPost(object)) {
|
||||||
const uri = getApId(object);
|
const uri = getApId(object);
|
||||||
const unlock = await this.appLockService.getApLock(uri);
|
const unlock = await acquireApObjectLock(this.redisForTimelines, uri);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const exist = await this.apNoteService.fetchNote(object);
|
const exist = await this.apNoteService.fetchNote(object);
|
||||||
|
|
|
@ -5,15 +5,16 @@
|
||||||
|
|
||||||
import { forwardRef, Inject, Injectable } from '@nestjs/common';
|
import { forwardRef, Inject, Injectable } from '@nestjs/common';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { UsersRepository, PollsRepository, EmojisRepository } from '@/models/_.js';
|
import type { UsersRepository, PollsRepository, EmojisRepository } from '@/models/_.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import type { MiRemoteUser } from '@/models/User.js';
|
import type { MiRemoteUser } from '@/models/User.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
|
import { acquireApObjectLock } from '@/misc/distributed-lock.js';
|
||||||
import { toArray, toSingle, unique } from '@/misc/prelude/array.js';
|
import { toArray, toSingle, unique } from '@/misc/prelude/array.js';
|
||||||
import type { MiEmoji } from '@/models/Emoji.js';
|
import type { MiEmoji } from '@/models/Emoji.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||||
import { NoteCreateService } from '@/core/NoteCreateService.js';
|
import { NoteCreateService } from '@/core/NoteCreateService.js';
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
|
@ -47,6 +48,9 @@ export class ApNoteService {
|
||||||
@Inject(DI.config)
|
@Inject(DI.config)
|
||||||
private config: Config,
|
private config: Config,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@ -70,7 +74,6 @@ export class ApNoteService {
|
||||||
private apImageService: ApImageService,
|
private apImageService: ApImageService,
|
||||||
private apQuestionService: ApQuestionService,
|
private apQuestionService: ApQuestionService,
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
private appLockService: AppLockService,
|
|
||||||
private pollService: PollService,
|
private pollService: PollService,
|
||||||
private noteCreateService: NoteCreateService,
|
private noteCreateService: NoteCreateService,
|
||||||
private apDbResolverService: ApDbResolverService,
|
private apDbResolverService: ApDbResolverService,
|
||||||
|
@ -379,7 +382,7 @@ export class ApNoteService {
|
||||||
throw new StatusError('blocked host', 451);
|
throw new StatusError('blocked host', 451);
|
||||||
}
|
}
|
||||||
|
|
||||||
const unlock = await this.appLockService.getApLock(uri);
|
const unlock = await acquireApObjectLock(this.redisForTimelines, uri);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//#region このサーバーに既に登録されていたらそれを返す
|
//#region このサーバーに既に登録されていたらそれを返す
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
import * as Redis from 'ioredis';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/active-users.js';
|
import { name, schema } from './entities/active-users.js';
|
||||||
|
@ -28,11 +29,13 @@ export default class ActiveUsersChart extends Chart<typeof schema> { // eslint-d
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
private idService: IdService,
|
private idService: IdService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/ap-request.js';
|
import { name, schema } from './entities/ap-request.js';
|
||||||
|
@ -22,10 +23,12 @@ export default class ApRequestChart extends Chart<typeof schema> { // eslint-dis
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/drive.js';
|
import { name, schema } from './entities/drive.js';
|
||||||
|
@ -23,10 +24,12 @@ export default class DriveChart extends Chart<typeof schema> { // eslint-disable
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { FollowingsRepository, InstancesRepository } from '@/models/_.js';
|
import type { FollowingsRepository, InstancesRepository } from '@/models/_.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/federation.js';
|
import { name, schema } from './entities/federation.js';
|
||||||
|
@ -24,6 +25,9 @@ export default class FederationChart extends Chart<typeof schema> { // eslint-di
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.followingsRepository)
|
@Inject(DI.followingsRepository)
|
||||||
private followingsRepository: FollowingsRepository,
|
private followingsRepository: FollowingsRepository,
|
||||||
|
|
||||||
|
@ -31,10 +35,9 @@ export default class FederationChart extends Chart<typeof schema> { // eslint-di
|
||||||
private instancesRepository: InstancesRepository,
|
private instancesRepository: InstancesRepository,
|
||||||
|
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
private appLockService: AppLockService,
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { DriveFilesRepository, FollowingsRepository, UsersRepository, NotesRepository } from '@/models/_.js';
|
import type { DriveFilesRepository, FollowingsRepository, UsersRepository, NotesRepository } from '@/models/_.js';
|
||||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { UtilityService } from '@/core/UtilityService.js';
|
import { UtilityService } from '@/core/UtilityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/instance.js';
|
import { name, schema } from './entities/instance.js';
|
||||||
|
@ -26,6 +27,9 @@ export default class InstanceChart extends Chart<typeof schema> { // eslint-disa
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@ -39,10 +43,9 @@ export default class InstanceChart extends Chart<typeof schema> { // eslint-disa
|
||||||
private followingsRepository: FollowingsRepository,
|
private followingsRepository: FollowingsRepository,
|
||||||
|
|
||||||
private utilityService: UtilityService,
|
private utilityService: UtilityService,
|
||||||
private appLockService: AppLockService,
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { Not, IsNull, DataSource } from 'typeorm';
|
import { Not, IsNull, DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { NotesRepository } from '@/models/_.js';
|
import type { NotesRepository } from '@/models/_.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/notes.js';
|
import { name, schema } from './entities/notes.js';
|
||||||
|
@ -24,13 +25,15 @@ export default class NotesChart extends Chart<typeof schema> { // eslint-disable
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.notesRepository)
|
@Inject(DI.notesRepository)
|
||||||
private notesRepository: NotesRepository,
|
private notesRepository: NotesRepository,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { DriveFilesRepository } from '@/models/_.js';
|
import type { DriveFilesRepository } from '@/models/_.js';
|
||||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/per-user-drive.js';
|
import { name, schema } from './entities/per-user-drive.js';
|
||||||
|
@ -25,14 +26,16 @@ export default class PerUserDriveChart extends Chart<typeof schema> { // eslint-
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.driveFilesRepository)
|
@Inject(DI.driveFilesRepository)
|
||||||
private driveFilesRepository: DriveFilesRepository,
|
private driveFilesRepository: DriveFilesRepository,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
|
||||||
private driveFileEntityService: DriveFileEntityService,
|
private driveFileEntityService: DriveFileEntityService,
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { Not, IsNull, DataSource } from 'typeorm';
|
import { Not, IsNull, DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import type { FollowingsRepository } from '@/models/_.js';
|
import type { FollowingsRepository } from '@/models/_.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/per-user-following.js';
|
import { name, schema } from './entities/per-user-following.js';
|
||||||
|
@ -25,14 +26,16 @@ export default class PerUserFollowingChart extends Chart<typeof schema> { // esl
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.followingsRepository)
|
@Inject(DI.followingsRepository)
|
||||||
private followingsRepository: FollowingsRepository,
|
private followingsRepository: FollowingsRepository,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
|
||||||
private userEntityService: UserEntityService,
|
private userEntityService: UserEntityService,
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { NotesRepository } from '@/models/_.js';
|
import type { NotesRepository } from '@/models/_.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/per-user-notes.js';
|
import { name, schema } from './entities/per-user-notes.js';
|
||||||
|
@ -25,13 +26,15 @@ export default class PerUserNotesChart extends Chart<typeof schema> { // eslint-
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.notesRepository)
|
@Inject(DI.notesRepository)
|
||||||
private notesRepository: NotesRepository,
|
private notesRepository: NotesRepository,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { addTime, dateUTC, subtractTime } from '@/misc/prelude/time.js';
|
import { addTime, dateUTC, subtractTime } from '@/misc/prelude/time.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/per-user-pv.js';
|
import { name, schema } from './entities/per-user-pv.js';
|
||||||
|
@ -24,10 +25,12 @@ export default class PerUserPvChart extends Chart<typeof schema> { // eslint-dis
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/per-user-reactions.js';
|
import { name, schema } from './entities/per-user-reactions.js';
|
||||||
|
@ -25,11 +26,13 @@ export default class PerUserReactionsChart extends Chart<typeof schema> { // esl
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
private userEntityService: UserEntityService,
|
private userEntityService: UserEntityService,
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import Logger from '@/logger.js';
|
import Logger from '@/logger.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { name, schema } from './entities/test-grouped.js';
|
import { name, schema } from './entities/test-grouped.js';
|
||||||
import type { KVs } from '../core.js';
|
import type { KVs } from '../core.js';
|
||||||
|
@ -24,10 +25,12 @@ export default class TestGroupedChart extends Chart<typeof schema> { // eslint-d
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema, true);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), logger, name, schema, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import Logger from '@/logger.js';
|
import Logger from '@/logger.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { name, schema } from './entities/test-intersection.js';
|
import { name, schema } from './entities/test-intersection.js';
|
||||||
import type { KVs } from '../core.js';
|
import type { KVs } from '../core.js';
|
||||||
|
@ -22,10 +23,12 @@ export default class TestIntersectionChart extends Chart<typeof schema> { // esl
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import Logger from '@/logger.js';
|
import Logger from '@/logger.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { name, schema } from './entities/test-unique.js';
|
import { name, schema } from './entities/test-unique.js';
|
||||||
import type { KVs } from '../core.js';
|
import type { KVs } from '../core.js';
|
||||||
|
@ -22,10 +23,12 @@ export default class TestUniqueChart extends Chart<typeof schema> { // eslint-di
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import Logger from '@/logger.js';
|
import Logger from '@/logger.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { name, schema } from './entities/test.js';
|
import { name, schema } from './entities/test.js';
|
||||||
import type { KVs } from '../core.js';
|
import type { KVs } from '../core.js';
|
||||||
|
@ -24,10 +25,12 @@ export default class TestChart extends Chart<typeof schema> { // eslint-disable-
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
|
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { Not, IsNull, DataSource } from 'typeorm';
|
import { Not, IsNull, DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import type { UsersRepository } from '@/models/_.js';
|
import type { UsersRepository } from '@/models/_.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
|
||||||
import Chart from '../core.js';
|
import Chart from '../core.js';
|
||||||
import { ChartLoggerService } from '../ChartLoggerService.js';
|
import { ChartLoggerService } from '../ChartLoggerService.js';
|
||||||
import { name, schema } from './entities/users.js';
|
import { name, schema } from './entities/users.js';
|
||||||
|
@ -25,14 +26,16 @@ export default class UsersChart extends Chart<typeof schema> { // eslint-disable
|
||||||
@Inject(DI.db)
|
@Inject(DI.db)
|
||||||
private db: DataSource,
|
private db: DataSource,
|
||||||
|
|
||||||
|
@Inject(DI.redisForTimelines)
|
||||||
|
private redisForTimelines: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
private appLockService: AppLockService,
|
|
||||||
private userEntityService: UserEntityService,
|
private userEntityService: UserEntityService,
|
||||||
private chartLoggerService: ChartLoggerService,
|
private chartLoggerService: ChartLoggerService,
|
||||||
) {
|
) {
|
||||||
super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
|
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
||||||
|
|
44
packages/backend/src/misc/distributed-lock.ts
Normal file
44
packages/backend/src/misc/distributed-lock.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
|
|
||||||
|
export async function acquireDistributedLock(
|
||||||
|
redis: Redis.Redis,
|
||||||
|
name: string,
|
||||||
|
timeout: number,
|
||||||
|
maxRetries: number,
|
||||||
|
retryInterval: number,
|
||||||
|
): Promise<() => Promise<void>> {
|
||||||
|
const lockKey = `lock:${name}`;
|
||||||
|
const identifier = Math.random().toString(36).slice(2);
|
||||||
|
|
||||||
|
let retries = 0;
|
||||||
|
while (retries < maxRetries) {
|
||||||
|
const result = await redis.set(lockKey, identifier, 'PX', timeout, 'NX');
|
||||||
|
if (result === 'OK') {
|
||||||
|
return async () => {
|
||||||
|
const currentIdentifier = await redis.get(lockKey);
|
||||||
|
if (currentIdentifier === identifier) {
|
||||||
|
await redis.del(lockKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise(resolve => setTimeout(resolve, retryInterval));
|
||||||
|
retries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Failed to acquire lock ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function acquireApObjectLock(
|
||||||
|
redis: Redis.Redis,
|
||||||
|
uri: string,
|
||||||
|
): Promise<() => Promise<void>> {
|
||||||
|
return acquireDistributedLock(redis, `ap-object:${uri}`, 30 * 1000, 600, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function acquireChartInsertLock(
|
||||||
|
redis: Redis.Redis,
|
||||||
|
name: string,
|
||||||
|
): Promise<() => Promise<void>> {
|
||||||
|
return acquireDistributedLock(redis, `chart-insert:${name}`, 30 * 1000, 120, 500);
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import * as assert from 'assert';
|
||||||
import { jest } from '@jest/globals';
|
import { jest } from '@jest/globals';
|
||||||
import * as lolex from '@sinonjs/fake-timers';
|
import * as lolex from '@sinonjs/fake-timers';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import * as Redis from 'ioredis';
|
||||||
import TestChart from '@/core/chart/charts/test.js';
|
import TestChart from '@/core/chart/charts/test.js';
|
||||||
import TestGroupedChart from '@/core/chart/charts/test-grouped.js';
|
import TestGroupedChart from '@/core/chart/charts/test-grouped.js';
|
||||||
import TestUniqueChart from '@/core/chart/charts/test-unique.js';
|
import TestUniqueChart from '@/core/chart/charts/test-unique.js';
|
||||||
|
@ -18,16 +19,16 @@ import { entity as TestGroupedChartEntity } from '@/core/chart/charts/entities/t
|
||||||
import { entity as TestUniqueChartEntity } from '@/core/chart/charts/entities/test-unique.js';
|
import { entity as TestUniqueChartEntity } from '@/core/chart/charts/entities/test-unique.js';
|
||||||
import { entity as TestIntersectionChartEntity } from '@/core/chart/charts/entities/test-intersection.js';
|
import { entity as TestIntersectionChartEntity } from '@/core/chart/charts/entities/test-intersection.js';
|
||||||
import { loadConfig } from '@/config.js';
|
import { loadConfig } from '@/config.js';
|
||||||
import type { AppLockService } from '@/core/AppLockService.js';
|
|
||||||
import { coreLogger } from '@/logger.js';
|
import { coreLogger } from '@/logger.js';
|
||||||
|
|
||||||
describe('Chart', () => {
|
describe('Chart', () => {
|
||||||
const config = loadConfig();
|
const config = loadConfig();
|
||||||
const appLockService = {
|
|
||||||
getChartInsertLock: () => () => Promise.resolve(() => {}),
|
|
||||||
} as unknown as jest.Mocked<AppLockService>;
|
|
||||||
|
|
||||||
let db: DataSource | undefined;
|
let db: DataSource | undefined;
|
||||||
|
let redisForTimelines = {
|
||||||
|
set: () => Promise.resolve('OK'),
|
||||||
|
get: () => Promise.resolve(null),
|
||||||
|
} as unknown as jest.Mocked<Redis.Redis>;
|
||||||
|
|
||||||
let testChart: TestChart;
|
let testChart: TestChart;
|
||||||
let testGroupedChart: TestGroupedChart;
|
let testGroupedChart: TestGroupedChart;
|
||||||
|
@ -64,10 +65,10 @@ describe('Chart', () => {
|
||||||
await db.initialize();
|
await db.initialize();
|
||||||
|
|
||||||
const logger = coreLogger.createSubLogger('chart'); // TODO: モックにする
|
const logger = coreLogger.createSubLogger('chart'); // TODO: モックにする
|
||||||
testChart = new TestChart(db, appLockService, logger);
|
testChart = new TestChart(db, redisForTimelines, logger);
|
||||||
testGroupedChart = new TestGroupedChart(db, appLockService, logger);
|
testGroupedChart = new TestGroupedChart(db, redisForTimelines, logger);
|
||||||
testUniqueChart = new TestUniqueChart(db, appLockService, logger);
|
testUniqueChart = new TestUniqueChart(db, redisForTimelines, logger);
|
||||||
testIntersectionChart = new TestIntersectionChart(db, appLockService, logger);
|
testIntersectionChart = new TestIntersectionChart(db, redisForTimelines, logger);
|
||||||
|
|
||||||
clock = lolex.install({
|
clock = lolex.install({
|
||||||
now: new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
now: new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
"chartjs-chart-matrix": "2.0.1",
|
"chartjs-chart-matrix": "2.0.1",
|
||||||
"chartjs-plugin-gradient": "0.6.1",
|
"chartjs-plugin-gradient": "0.6.1",
|
||||||
"chartjs-plugin-zoom": "2.2.0",
|
"chartjs-plugin-zoom": "2.2.0",
|
||||||
"chromatic": "11.22.2",
|
"chromatic": "11.23.0",
|
||||||
"compare-versions": "6.1.1",
|
"compare-versions": "6.1.1",
|
||||||
"cropperjs": "2.0.0-rc.0",
|
"cropperjs": "2.0.0-rc.0",
|
||||||
"date-fns": "4.1.0",
|
"date-fns": "4.1.0",
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
"punycode.js": "2.3.1",
|
"punycode.js": "2.3.1",
|
||||||
"rollup": "4.30.1",
|
"rollup": "4.30.1",
|
||||||
"sanitize-html": "2.14.0",
|
"sanitize-html": "2.14.0",
|
||||||
"sass": "1.83.1",
|
"sass": "1.83.4",
|
||||||
"shiki": "1.26.2",
|
"shiki": "1.27.0",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.172.0",
|
"three": "0.172.0",
|
||||||
|
@ -105,7 +105,7 @@
|
||||||
"@types/estree": "1.0.6",
|
"@types/estree": "1.0.6",
|
||||||
"@types/matter-js": "0.19.8",
|
"@types/matter-js": "0.19.8",
|
||||||
"@types/micromatch": "4.0.9",
|
"@types/micromatch": "4.0.9",
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||||
"@types/sanitize-html": "2.13.0",
|
"@types/sanitize-html": "2.13.0",
|
||||||
"@types/three": "0.172.0",
|
"@types/three": "0.172.0",
|
||||||
|
@ -132,7 +132,7 @@
|
||||||
"prettier": "3.4.2",
|
"prettier": "3.4.2",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"start-server-and-test": "2.0.9",
|
"start-server-and-test": "2.0.10",
|
||||||
"storybook": "8.4.7",
|
"storybook": "8.4.7",
|
||||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||||
"vite-plugin-turbosnap": "1.0.3",
|
"vite-plugin-turbosnap": "1.0.3",
|
||||||
|
|
|
@ -19,7 +19,7 @@ import MkAnimBg from '@/components/MkAnimBg.vue';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
|
import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
|
||||||
import { nextTick, onMounted, useTemplateRef } from "vue";
|
import { nextTick, onMounted, useTemplateRef } from "vue";
|
||||||
import { $i } from "@/account.js";
|
import { $i } from '@/account.js';
|
||||||
|
|
||||||
const transactionIdMeta = document.querySelector<HTMLMetaElement>('meta[name="misskey:sso:transaction-id"]');
|
const transactionIdMeta = document.querySelector<HTMLMetaElement>('meta[name="misskey:sso:transaction-id"]');
|
||||||
if (transactionIdMeta) {
|
if (transactionIdMeta) {
|
||||||
|
|
|
@ -58,7 +58,7 @@ import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import { miLocalStorage } from "@/local-storage.js";
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
|
||||||
const kawaiiMode = miLocalStorage.getItem('kawaii') === 'true';
|
const kawaiiMode = miLocalStorage.getItem('kawaii') === 'true';
|
||||||
const menu = toRef(defaultStore.state, 'menu');
|
const menu = toRef(defaultStore.state, 'menu');
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
"@misskey-dev/eslint-plugin": "1.0.0",
|
||||||
"@types/matter-js": "0.19.8",
|
"@types/matter-js": "0.19.8",
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||||
"@typescript-eslint/parser": "7.10.0",
|
"@typescript-eslint/parser": "7.10.0",
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
"@misskey-dev/eslint-plugin": "1.0.0",
|
||||||
"@readme/openapi-parser": "2.6.0",
|
"@readme/openapi-parser": "2.6.0",
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||||
"@typescript-eslint/parser": "7.10.0",
|
"@typescript-eslint/parser": "7.10.0",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
"@misskey-dev/eslint-plugin": "1.0.0",
|
||||||
"@swc/jest": "0.2.37",
|
"@swc/jest": "0.2.37",
|
||||||
"@types/jest": "29.5.14",
|
"@types/jest": "29.5.14",
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||||
"@typescript-eslint/parser": "7.10.0",
|
"@typescript-eslint/parser": "7.10.0",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
"@misskey-dev/eslint-plugin": "1.0.0",
|
||||||
"@types/node": "22.10.5",
|
"@types/node": "22.10.6",
|
||||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||||
"@typescript-eslint/parser": "7.10.0",
|
"@typescript-eslint/parser": "7.10.0",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
"@misskey-dev/eslint-plugin": "1.0.0",
|
||||||
"@types/serviceworker": "0.0.111",
|
"@types/serviceworker": "0.0.112",
|
||||||
"@typescript-eslint/parser": "7.10.0",
|
"@typescript-eslint/parser": "7.10.0",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
"eslint-plugin-import": "2.31.0",
|
"eslint-plugin-import": "2.31.0",
|
||||||
|
|
727
pnpm-lock.yaml
727
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue