enhance(backend): metaのポーリング頻度を減らし、redisで更新を受け取るように
This commit is contained in:
		
							parent
							
								
									55f8a641a6
								
							
						
					
					
						commit
						dc43fc68ef
					
				
					 3 changed files with 45 additions and 6 deletions
				
			
		|  | @ -1,6 +1,6 @@ | ||||||
| import { Inject, Injectable } from '@nestjs/common'; | import { Inject, Injectable } from '@nestjs/common'; | ||||||
| import { DataSource } from 'typeorm'; | import { DataSource } from 'typeorm'; | ||||||
| import type { UsersRepository } from '@/models/index.js'; | import Redis from 'ioredis'; | ||||||
| import { DI } from '@/di-symbols.js'; | import { DI } from '@/di-symbols.js'; | ||||||
| import { Meta } from '@/models/entities/Meta.js'; | import { Meta } from '@/models/entities/Meta.js'; | ||||||
| import type { OnApplicationShutdown } from '@nestjs/common'; | import type { OnApplicationShutdown } from '@nestjs/common'; | ||||||
|  | @ -11,19 +11,27 @@ export class MetaService implements OnApplicationShutdown { | ||||||
| 	private intervalId: NodeJS.Timer; | 	private intervalId: NodeJS.Timer; | ||||||
| 
 | 
 | ||||||
| 	constructor( | 	constructor( | ||||||
|  | 		@Inject(DI.redisSubscriber) | ||||||
|  | 		private redisSubscriber: Redis.Redis, | ||||||
|  | 
 | ||||||
| 		@Inject(DI.db) | 		@Inject(DI.db) | ||||||
| 		private db: DataSource, | 		private db: DataSource, | ||||||
| 	) { | 	) { | ||||||
|  | 		this.onMessage = this.onMessage.bind(this); | ||||||
|  | 
 | ||||||
| 		if (process.env.NODE_ENV !== 'test') { | 		if (process.env.NODE_ENV !== 'test') { | ||||||
| 			this.intervalId = setInterval(() => { | 			this.intervalId = setInterval(() => { | ||||||
| 				this.fetch(true).then(meta => { | 				this.fetch(true).then(meta => { | ||||||
|  | 					// fetch内でもセットしてるけど仕様変更の可能性もあるため一応
 | ||||||
| 					this.cache = meta; | 					this.cache = meta; | ||||||
| 				}); | 				}); | ||||||
| 			}, 1000 * 10); | 			}, 1000 * 60 * 5); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		this.redisSubscriber.on('message', this.onMessage); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	async fetch(noCache = false): Promise<Meta> { | 	public async fetch(noCache = false): Promise<Meta> { | ||||||
| 		if (!noCache && this.cache) return this.cache; | 		if (!noCache && this.cache) return this.cache; | ||||||
| 	 | 	 | ||||||
| 		return await this.db.transaction(async transactionalEntityManager => { | 		return await this.db.transaction(async transactionalEntityManager => { | ||||||
|  | @ -56,8 +64,25 @@ export class MetaService implements OnApplicationShutdown { | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 	 | 
 | ||||||
|  | 	private async onMessage(_, data) { | ||||||
|  | 		const obj = JSON.parse(data); | ||||||
|  | 
 | ||||||
|  | 		if (obj.channel === 'internal') { | ||||||
|  | 			const { type, body } = obj.message; | ||||||
|  | 			switch (type) { | ||||||
|  | 				case 'metaUpdated': { | ||||||
|  | 					this.cache = body; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 				default: | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public onApplicationShutdown(signal?: string | undefined) { | 	public onApplicationShutdown(signal?: string | undefined) { | ||||||
| 		clearInterval(this.intervalId); | 		clearInterval(this.intervalId); | ||||||
|  | 		this.redisSubscriber.off('message', this.onMessage); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ import { ModerationLogService } from '@/core/ModerationLogService.js'; | ||||||
| import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits.js'; | import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits.js'; | ||||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||||
| import { DI } from '@/di-symbols.js'; | import { DI } from '@/di-symbols.js'; | ||||||
|  | import { GlobalEventService } from '@/core/GlobalEventService.js'; | ||||||
| 
 | 
 | ||||||
| export const meta = { | export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
|  | @ -115,6 +116,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||||
| 		@Inject(DI.db) | 		@Inject(DI.db) | ||||||
| 		private db: DataSource, | 		private db: DataSource, | ||||||
| 
 | 
 | ||||||
|  | 		private globalEventService: GlobalEventService, | ||||||
| 		private moderationLogService: ModerationLogService, | 		private moderationLogService: ModerationLogService, | ||||||
| 	) { | 	) { | ||||||
| 		super(meta, paramDef, async (ps, me) => { | 		super(meta, paramDef, async (ps, me) => { | ||||||
|  | @ -436,7 +438,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||||
| 				set.enableActiveEmailValidation = ps.enableActiveEmailValidation; | 				set.enableActiveEmailValidation = ps.enableActiveEmailValidation; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			await this.db.transaction(async transactionalEntityManager => { | 			const updated = await this.db.transaction(async transactionalEntityManager => { | ||||||
| 				const metas = await transactionalEntityManager.find(Meta, { | 				const metas = await transactionalEntityManager.find(Meta, { | ||||||
| 					order: { | 					order: { | ||||||
| 						id: 'DESC', | 						id: 'DESC', | ||||||
|  | @ -447,11 +449,21 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||||
| 
 | 
 | ||||||
| 				if (meta) { | 				if (meta) { | ||||||
| 					await transactionalEntityManager.update(Meta, meta.id, set); | 					await transactionalEntityManager.update(Meta, meta.id, set); | ||||||
|  | 
 | ||||||
|  | 					const metas = await transactionalEntityManager.find(Meta, { | ||||||
|  | 						order: { | ||||||
|  | 							id: 'DESC', | ||||||
|  | 						}, | ||||||
|  | 					}); | ||||||
|  | 
 | ||||||
|  | 					return metas[0]; | ||||||
| 				} else { | 				} else { | ||||||
| 					await transactionalEntityManager.save(Meta, set); | 					return await transactionalEntityManager.save(Meta, set); | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
| 
 | 
 | ||||||
|  | 			this.globalEventService.publishInternalEvent('metaUpdated', updated); | ||||||
|  | 
 | ||||||
| 			this.moderationLogService.insertModerationLog(me, 'updateMeta'); | 			this.moderationLogService.insertModerationLog(me, 'updateMeta'); | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import type { Signin } from '@/models/entities/Signin.js'; | ||||||
| import type { Page } from '@/models/entities/Page.js'; | import type { Page } from '@/models/entities/Page.js'; | ||||||
| import type { Packed } from '@/misc/schema.js'; | import type { Packed } from '@/misc/schema.js'; | ||||||
| import type { Webhook } from '@/models/entities/Webhook.js'; | import type { Webhook } from '@/models/entities/Webhook.js'; | ||||||
|  | import type { Meta } from '@/models/entities/Meta.js'; | ||||||
| import type Emitter from 'strict-event-emitter-types'; | import type Emitter from 'strict-event-emitter-types'; | ||||||
| import type { EventEmitter } from 'events'; | import type { EventEmitter } from 'events'; | ||||||
| 
 | 
 | ||||||
|  | @ -29,6 +30,7 @@ export interface InternalStreamTypes { | ||||||
| 	antennaCreated: Antenna; | 	antennaCreated: Antenna; | ||||||
| 	antennaDeleted: Antenna; | 	antennaDeleted: Antenna; | ||||||
| 	antennaUpdated: Antenna; | 	antennaUpdated: Antenna; | ||||||
|  | 	metaUpdated: Meta, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface BroadcastTypes { | export interface BroadcastTypes { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue