summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authoranatawa12 <anatawa12@icloud.com>2025-12-22 17:01:10 +0900
committerGitHub <noreply@github.com>2025-12-22 17:01:10 +0900
commit74e847a04d1b287f50a10f7c1e44a4e7bc2f91ac (patch)
treef50e8a73312f2e01262d66c4d034ad5c0df52304 /packages/backend
parentfeat: use tsgo where capable (#16984) (diff)
downloadmisskey-74e847a04d1b287f50a10f7c1e44a4e7bc2f91ac.tar.gz
misskey-74e847a04d1b287f50a10f7c1e44a4e7bc2f91ac.tar.bz2
misskey-74e847a04d1b287f50a10f7c1e44a4e7bc2f91ac.zip
refactor: use TRANSIENT scope to avoid service bucket relay (#16985)
* refactor: use TRANSIENT scope to avoid service bucket relay * lint: fix lints * refactor: use transient for apResolver * Update packages/backend/src/core/activitypub/models/ApImageService.ts * fix
Diffstat (limited to 'packages/backend')
-rw-r--r--packages/backend/src/core/CoreModule.ts4
-rw-r--r--packages/backend/src/core/activitypub/ApInboxService.ts14
-rw-r--r--packages/backend/src/core/activitypub/ApResolverService.ts79
-rw-r--r--packages/backend/src/core/activitypub/models/ApImageService.ts2
-rw-r--r--packages/backend/src/core/activitypub/models/ApNoteService.ts2
-rw-r--r--packages/backend/src/core/activitypub/models/ApPersonService.ts8
-rw-r--r--packages/backend/src/core/activitypub/models/ApQuestionService.ts4
-rw-r--r--packages/backend/src/server/ServerModule.ts76
-rw-r--r--packages/backend/src/server/api/StreamingApiServerService.ts33
-rw-r--r--packages/backend/src/server/api/endpoints/ap/get.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/ap/show.ts2
-rw-r--r--packages/backend/src/server/api/stream/ChannelsService.ts94
-rw-r--r--packages/backend/src/server/api/stream/Connection.ts91
-rw-r--r--packages/backend/src/server/api/stream/channel.ts19
-rw-r--r--packages/backend/src/server/api/stream/channels/admin.ts34
-rw-r--r--packages/backend/src/server/api/stream/channels/antenna.ts37
-rw-r--r--packages/backend/src/server/api/stream/channels/channel.ts36
-rw-r--r--packages/backend/src/server/api/stream/channels/chat-room.ts37
-rw-r--r--packages/backend/src/server/api/stream/channels/chat-user.ts37
-rw-r--r--packages/backend/src/server/api/stream/channels/drive.ts34
-rw-r--r--packages/backend/src/server/api/stream/channels/global-timeline.ts41
-rw-r--r--packages/backend/src/server/api/stream/channels/hashtag.ts37
-rw-r--r--packages/backend/src/server/api/stream/channels/home-timeline.ts37
-rw-r--r--packages/backend/src/server/api/stream/channels/hybrid-timeline.ts41
-rw-r--r--packages/backend/src/server/api/stream/channels/local-timeline.ts43
-rw-r--r--packages/backend/src/server/api/stream/channels/main.ts37
-rw-r--r--packages/backend/src/server/api/stream/channels/queue-stats.ts34
-rw-r--r--packages/backend/src/server/api/stream/channels/reversi-game.ts39
-rw-r--r--packages/backend/src/server/api/stream/channels/reversi.ts33
-rw-r--r--packages/backend/src/server/api/stream/channels/role-timeline.ts39
-rw-r--r--packages/backend/src/server/api/stream/channels/server-stats.ts34
-rw-r--r--packages/backend/src/server/api/stream/channels/user-list.ts49
32 files changed, 397 insertions, 712 deletions
diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts
index 87575ca59a..f075671d93 100644
--- a/packages/backend/src/core/CoreModule.ts
+++ b/packages/backend/src/core/CoreModule.ts
@@ -141,7 +141,7 @@ import { ApLoggerService } from './activitypub/ApLoggerService.js';
import { ApMfmService } from './activitypub/ApMfmService.js';
import { ApRendererService } from './activitypub/ApRendererService.js';
import { ApRequestService } from './activitypub/ApRequestService.js';
-import { ApResolverService } from './activitypub/ApResolverService.js';
+import { ApResolverService, Resolver } from './activitypub/ApResolverService.js';
import { JsonLdService } from './activitypub/JsonLdService.js';
import { RemoteLoggerService } from './RemoteLoggerService.js';
import { RemoteUserResolveService } from './RemoteUserResolveService.js';
@@ -447,6 +447,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApRendererService,
ApRequestService,
ApResolverService,
+ Resolver,
JsonLdService,
RemoteLoggerService,
RemoteUserResolveService,
@@ -745,6 +746,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApRendererService,
ApRequestService,
ApResolverService,
+ Resolver,
JsonLdService,
RemoteLoggerService,
RemoteUserResolveService,
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 81637580e3..ff47ca930d 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -95,7 +95,7 @@ export class ApInboxService {
if (isCollectionOrOrderedCollection(activity)) {
const results = [] as [string, string | void][];
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
const items = toArray(isCollection(activity) ? activity.items : activity.orderedItems);
if (items.length >= resolver.getRecursionLimit()) {
@@ -221,7 +221,7 @@ export class ApInboxService {
this.logger.info(`Accept: ${uri}`);
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(err => {
this.logger.error(`Resolution failed: ${err}`);
@@ -284,7 +284,7 @@ export class ApInboxService {
this.logger.info(`Announce: ${uri}`);
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
if (!activity.object) return 'skip: activity has no object property';
const targetUri = getApId(activity.object);
@@ -406,7 +406,7 @@ export class ApInboxService {
}
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.logger.error(`Resolution failed: ${e}`);
@@ -575,7 +575,7 @@ export class ApInboxService {
this.logger.info(`Reject: ${uri}`);
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.logger.error(`Resolution failed: ${e}`);
@@ -642,7 +642,7 @@ export class ApInboxService {
this.logger.info(`Undo: ${uri}`);
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.logger.error(`Resolution failed: ${e}`);
@@ -774,7 +774,7 @@ export class ApInboxService {
this.logger.debug('Update');
// eslint-disable-next-line no-param-reassign
- resolver ??= this.apResolverService.createResolver();
+ resolver ??= await this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.logger.error(`Resolution failed: ${e}`);
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index 646150455b..0f51b1ce8d 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -3,10 +3,17 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Inject, Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { IsNull, Not } from 'typeorm';
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
-import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository, FollowRequestsRepository, MiMeta } from '@/models/_.js';
+import type {
+ FollowRequestsRepository,
+ MiMeta,
+ NoteReactionsRepository,
+ NotesRepository,
+ PollsRepository,
+ UsersRepository
+} from '@/models/_.js';
import type { Config } from '@/config.js';
import { HttpRequestService } from '@/core/HttpRequestService.js';
import { DI } from '@/di-symbols.js';
@@ -16,26 +23,43 @@ import { LoggerService } from '@/core/LoggerService.js';
import type Logger from '@/logger.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
+import type { ICollection, IObject, IOrderedCollection } from './type.js';
import { isCollectionOrOrderedCollection } from './type.js';
import { ApDbResolverService } from './ApDbResolverService.js';
import { ApRendererService } from './ApRendererService.js';
import { ApRequestService } from './ApRequestService.js';
import { FetchAllowSoftFailMask } from './misc/check-against-url.js';
-import type { IObject, ICollection, IOrderedCollection } from './type.js';
+import { ModuleRef } from '@nestjs/core';
+@Injectable({ scope: Scope.TRANSIENT })
export class Resolver {
private history: Set<string>;
private user?: MiLocalUser;
private logger: Logger;
+ private recursionLimit = 256;
constructor(
+ @Inject(DI.config)
private config: Config,
+
+ @Inject(DI.meta)
private meta: MiMeta,
+
+ @Inject(DI.usersRepository)
private usersRepository: UsersRepository,
+
+ @Inject(DI.notesRepository)
private notesRepository: NotesRepository,
+
+ @Inject(DI.pollsRepository)
private pollsRepository: PollsRepository,
+
+ @Inject(DI.noteReactionsRepository)
private noteReactionsRepository: NoteReactionsRepository,
+
+ @Inject(DI.followRequestsRepository)
private followRequestsRepository: FollowRequestsRepository,
+
private utilityService: UtilityService,
private systemAccountService: SystemAccountService,
private apRequestService: ApRequestService,
@@ -43,7 +67,6 @@ export class Resolver {
private apRendererService: ApRendererService,
private apDbResolverService: ApDbResolverService,
private loggerService: LoggerService,
- private recursionLimit = 256,
) {
this.history = new Set();
this.logger = this.loggerService.getLogger('ap-resolve');
@@ -180,54 +203,12 @@ export class Resolver {
@Injectable()
export class ApResolverService {
constructor(
- @Inject(DI.config)
- private config: Config,
-
- @Inject(DI.meta)
- private meta: MiMeta,
-
- @Inject(DI.usersRepository)
- private usersRepository: UsersRepository,
-
- @Inject(DI.notesRepository)
- private notesRepository: NotesRepository,
-
- @Inject(DI.pollsRepository)
- private pollsRepository: PollsRepository,
-
- @Inject(DI.noteReactionsRepository)
- private noteReactionsRepository: NoteReactionsRepository,
-
- @Inject(DI.followRequestsRepository)
- private followRequestsRepository: FollowRequestsRepository,
-
- private utilityService: UtilityService,
- private systemAccountService: SystemAccountService,
- private apRequestService: ApRequestService,
- private httpRequestService: HttpRequestService,
- private apRendererService: ApRendererService,
- private apDbResolverService: ApDbResolverService,
- private loggerService: LoggerService,
+ private moduleRef: ModuleRef,
) {
}
@bindThis
- public createResolver(): Resolver {
- return new Resolver(
- this.config,
- this.meta,
- this.usersRepository,
- this.notesRepository,
- this.pollsRepository,
- this.noteReactionsRepository,
- this.followRequestsRepository,
- this.utilityService,
- this.systemAccountService,
- this.apRequestService,
- this.httpRequestService,
- this.apRendererService,
- this.apDbResolverService,
- this.loggerService,
- );
+ public async createResolver(): Promise<Resolver> {
+ return await this.moduleRef.create(Resolver);
}
}
diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts
index e7ece87b01..0496774c19 100644
--- a/packages/backend/src/core/activitypub/models/ApImageService.ts
+++ b/packages/backend/src/core/activitypub/models/ApImageService.ts
@@ -46,7 +46,7 @@ export class ApImageService {
throw new Error('actor has been suspended');
}
- const image = await this.apResolverService.createResolver().resolve(value);
+ const image = await (await this.apResolverService.createResolver()).resolve(value);
if (!isDocument(image)) return null;
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index 214d32f67f..1fc5728c98 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -128,7 +128,7 @@ export class ApNoteService {
@bindThis
public async createNote(value: string | IObject, actor?: MiRemoteUser, resolver?: Resolver, silent = false): Promise<MiNote | null> {
// eslint-disable-next-line no-param-reassign
- if (resolver == null) resolver = this.apResolverService.createResolver();
+ if (resolver == null) resolver = await this.apResolverService.createResolver();
const object = await resolver.resolve(value);
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index e52078ed0f..ebe8e9c964 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -310,7 +310,7 @@ export class ApPersonService implements OnModuleInit {
}
// eslint-disable-next-line no-param-reassign
- if (resolver == null) resolver = this.apResolverService.createResolver();
+ if (resolver == null) resolver = await this.apResolverService.createResolver();
const object = await resolver.resolve(uri);
if (object.id == null) throw new Error('invalid object.id: ' + object.id);
@@ -500,7 +500,7 @@ export class ApPersonService implements OnModuleInit {
//#endregion
// eslint-disable-next-line no-param-reassign
- if (resolver == null) resolver = this.apResolverService.createResolver();
+ if (resolver == null) resolver = await this.apResolverService.createResolver();
const object = hint ?? await resolver.resolve(uri);
@@ -678,7 +678,7 @@ export class ApPersonService implements OnModuleInit {
// リモートサーバーからフェッチしてきて登録
// eslint-disable-next-line no-param-reassign
- if (resolver == null) resolver = this.apResolverService.createResolver();
+ if (resolver == null) resolver = await this.apResolverService.createResolver();
return await this.createPerson(uri, resolver);
}
@@ -707,7 +707,7 @@ export class ApPersonService implements OnModuleInit {
this.logger.info(`Updating the featured: ${user.uri}`);
- const _resolver = resolver ?? this.apResolverService.createResolver();
+ const _resolver = resolver ?? await this.apResolverService.createResolver();
// Resolve to (Ordered)Collection Object
const collection = await _resolver.resolveCollection(user.featured);
diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
index a2cdaf02ca..8ac2f21e26 100644
--- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts
+++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
@@ -45,7 +45,7 @@ export class ApQuestionService {
@bindThis
public async extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
// eslint-disable-next-line no-param-reassign
- if (resolver == null) resolver = this.apResolverService.createResolver();
+ if (resolver == null) resolver = await this.apResolverService.createResolver();
const question = await resolver.resolve(source);
if (!isQuestion(question)) throw new Error('invalid type');
@@ -91,7 +91,7 @@ export class ApQuestionService {
// resolve new Question object
// eslint-disable-next-line no-param-reassign
- if (resolver == null) resolver = this.apResolverService.createResolver();
+ if (resolver == null) resolver = await this.apResolverService.createResolver();
const question = await resolver.resolve(value);
this.logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
diff --git a/packages/backend/src/server/ServerModule.ts b/packages/backend/src/server/ServerModule.ts
index 111421472d..8259a2a9e4 100644
--- a/packages/backend/src/server/ServerModule.ts
+++ b/packages/backend/src/server/ServerModule.ts
@@ -13,7 +13,6 @@ import { NodeinfoServerService } from './NodeinfoServerService.js';
import { ServerService } from './ServerService.js';
import { WellKnownServerService } from './WellKnownServerService.js';
import { GetterService } from './api/GetterService.js';
-import { ChannelsService } from './api/stream/ChannelsService.js';
import { ActivityPubServerService } from './ActivityPubServerService.js';
import { ApiLoggerService } from './api/ApiLoggerService.js';
import { ApiServerService } from './api/ApiServerService.js';
@@ -31,24 +30,25 @@ import { UrlPreviewService } from './web/UrlPreviewService.js';
import { ClientLoggerService } from './web/ClientLoggerService.js';
import { OAuth2ProviderService } from './oauth/OAuth2ProviderService.js';
-import { MainChannelService } from './api/stream/channels/main.js';
-import { AdminChannelService } from './api/stream/channels/admin.js';
-import { AntennaChannelService } from './api/stream/channels/antenna.js';
-import { ChannelChannelService } from './api/stream/channels/channel.js';
-import { DriveChannelService } from './api/stream/channels/drive.js';
-import { GlobalTimelineChannelService } from './api/stream/channels/global-timeline.js';
-import { HashtagChannelService } from './api/stream/channels/hashtag.js';
-import { HomeTimelineChannelService } from './api/stream/channels/home-timeline.js';
-import { HybridTimelineChannelService } from './api/stream/channels/hybrid-timeline.js';
-import { LocalTimelineChannelService } from './api/stream/channels/local-timeline.js';
-import { QueueStatsChannelService } from './api/stream/channels/queue-stats.js';
-import { ServerStatsChannelService } from './api/stream/channels/server-stats.js';
-import { UserListChannelService } from './api/stream/channels/user-list.js';
-import { RoleTimelineChannelService } from './api/stream/channels/role-timeline.js';
-import { ChatUserChannelService } from './api/stream/channels/chat-user.js';
-import { ChatRoomChannelService } from './api/stream/channels/chat-room.js';
-import { ReversiChannelService } from './api/stream/channels/reversi.js';
-import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js';
+import MainStreamConnection from '@/server/api/stream/Connection.js';
+import { MainChannel } from './api/stream/channels/main.js';
+import { AdminChannel } from './api/stream/channels/admin.js';
+import { AntennaChannel } from './api/stream/channels/antenna.js';
+import { ChannelChannel } from './api/stream/channels/channel.js';
+import { DriveChannel } from './api/stream/channels/drive.js';
+import { GlobalTimelineChannel } from './api/stream/channels/global-timeline.js';
+import { HashtagChannel } from './api/stream/channels/hashtag.js';
+import { HomeTimelineChannel } from './api/stream/channels/home-timeline.js';
+import { HybridTimelineChannel } from './api/stream/channels/hybrid-timeline.js';
+import { LocalTimelineChannel } from './api/stream/channels/local-timeline.js';
+import { QueueStatsChannel } from './api/stream/channels/queue-stats.js';
+import { ServerStatsChannel } from './api/stream/channels/server-stats.js';
+import { UserListChannel } from './api/stream/channels/user-list.js';
+import { RoleTimelineChannel } from './api/stream/channels/role-timeline.js';
+import { ChatUserChannel } from './api/stream/channels/chat-user.js';
+import { ChatRoomChannel } from './api/stream/channels/chat-room.js';
+import { ReversiChannel } from './api/stream/channels/reversi.js';
+import { ReversiGameChannel } from './api/stream/channels/reversi-game.js';
import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.js';
@Module({
@@ -69,7 +69,7 @@ import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.j
ServerService,
WellKnownServerService,
GetterService,
- ChannelsService,
+ MainStreamConnection,
ApiCallService,
ApiLoggerService,
ApiServerService,
@@ -80,24 +80,24 @@ import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.j
SigninService,
SignupApiService,
StreamingApiServerService,
- MainChannelService,
- AdminChannelService,
- AntennaChannelService,
- ChannelChannelService,
- DriveChannelService,
- GlobalTimelineChannelService,
- HashtagChannelService,
- RoleTimelineChannelService,
- ChatUserChannelService,
- ChatRoomChannelService,
- ReversiChannelService,
- ReversiGameChannelService,
- HomeTimelineChannelService,
- HybridTimelineChannelService,
- LocalTimelineChannelService,
- QueueStatsChannelService,
- ServerStatsChannelService,
- UserListChannelService,
+ MainChannel,
+ AdminChannel,
+ AntennaChannel,
+ ChannelChannel,
+ DriveChannel,
+ GlobalTimelineChannel,
+ HashtagChannel,
+ RoleTimelineChannel,
+ ChatUserChannel,
+ ChatRoomChannel,
+ ReversiChannel,
+ ReversiGameChannel,
+ HomeTimelineChannel,
+ HybridTimelineChannel,
+ LocalTimelineChannel,
+ QueueStatsChannel,
+ ServerStatsChannel,
+ UserListChannel,
OpenApiServerService,
OAuth2ProviderService,
],
diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts
index 21f2f0b7e2..359c361ed4 100644
--- a/packages/backend/src/server/api/StreamingApiServerService.ts
+++ b/packages/backend/src/server/api/StreamingApiServerService.ts
@@ -8,18 +8,14 @@ import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import * as WebSocket from 'ws';
import { DI } from '@/di-symbols.js';
-import type { UsersRepository, MiAccessToken } from '@/models/_.js';
-import { NotificationService } from '@/core/NotificationService.js';
+import type { MiAccessToken } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
-import { CacheService } from '@/core/CacheService.js';
import { MiLocalUser } from '@/models/User.js';
import { UserService } from '@/core/UserService.js';
-import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
-import { ChannelMutingService } from '@/core/ChannelMutingService.js';
import { AuthenticateService, AuthenticationError } from './AuthenticateService.js';
-import MainStreamConnection from './stream/Connection.js';
-import { ChannelsService } from './stream/ChannelsService.js';
+import MainStreamConnection, { ConnectionRequest } from './stream/Connection.js';
import type * as http from 'node:http';
+import { ContextIdFactory, ModuleRef } from '@nestjs/core';
@Injectable()
export class StreamingApiServerService {
@@ -31,16 +27,9 @@ export class StreamingApiServerService {
@Inject(DI.redisForSub)
private redisForSub: Redis.Redis,
- @Inject(DI.usersRepository)
- private usersRepository: UsersRepository,
-
- private cacheService: CacheService,
+ private moduleRef: ModuleRef,
private authenticateService: AuthenticateService,
- private channelsService: ChannelsService,
- private notificationService: NotificationService,
private usersService: UserService,
- private channelFollowingService: ChannelFollowingService,
- private channelMutingService: ChannelMutingService,
) {
}
@@ -94,14 +83,12 @@ export class StreamingApiServerService {
return;
}
- const stream = new MainStreamConnection(
- this.channelsService,
- this.notificationService,
- this.cacheService,
- this.channelFollowingService,
- this.channelMutingService,
- user, app,
- );
+ const contextId = ContextIdFactory.create();
+ this.moduleRef.registerRequestByContextId<ConnectionRequest>({
+ user,
+ token: app,
+ }, contextId);
+ const stream = await this.moduleRef.create(MainStreamConnection, contextId);
await stream.init();
diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts
index 14286bc23e..ff03fce72b 100644
--- a/packages/backend/src/server/api/endpoints/ap/get.ts
+++ b/packages/backend/src/server/api/endpoints/ap/get.ts
@@ -43,7 +43,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private apResolverService: ApResolverService,
) {
super(meta, paramDef, async (ps, me) => {
- const resolver = this.apResolverService.createResolver();
+ const resolver = await this.apResolverService.createResolver();
const object = await resolver.resolve(ps.uri);
return object;
});
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index fe48e7497a..140b054fcc 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -148,7 +148,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (this.utilityService.isSelfHost(host)) return null;
// リモートから一旦オブジェクトフェッチ
- const resolver = this.apResolverService.createResolver();
+ const resolver = await this.apResolverService.createResolver();
// allow ap/show exclusively to lookup URLs that are cross-origin or non-canonical (like https://alice.example.com/@bob@bob.example.com -> https://bob.example.com/@bob)
const object = await resolver.resolve(uri, FetchAllowSoftFailMask.CrossOrigin | FetchAllowSoftFailMask.NonCanonicalId).catch((err) => {
if (err instanceof IdentifiableError) {
diff --git a/packages/backend/src/server/api/stream/ChannelsService.ts b/packages/backend/src/server/api/stream/ChannelsService.ts
index c0ef589dea..63ad9281b2 100644
--- a/packages/backend/src/server/api/stream/ChannelsService.ts
+++ b/packages/backend/src/server/api/stream/ChannelsService.ts
@@ -4,72 +4,54 @@
*/
import { Injectable } from '@nestjs/common';
+import { HybridTimelineChannel } from './channels/hybrid-timeline.js';
+import { LocalTimelineChannel } from './channels/local-timeline.js';
+import { HomeTimelineChannel } from './channels/home-timeline.js';
+import { GlobalTimelineChannel } from './channels/global-timeline.js';
+import { MainChannel } from './channels/main.js';
+import { ChannelChannel } from './channels/channel.js';
+import { AdminChannel } from './channels/admin.js';
+import { ServerStatsChannel } from './channels/server-stats.js';
+import { QueueStatsChannel } from './channels/queue-stats.js';
+import { UserListChannel } from './channels/user-list.js';
+import { AntennaChannel } from './channels/antenna.js';
+import { DriveChannel } from './channels/drive.js';
+import { HashtagChannel } from './channels/hashtag.js';
+import { RoleTimelineChannel } from './channels/role-timeline.js';
+import { ChatUserChannel } from './channels/chat-user.js';
+import { ChatRoomChannel } from './channels/chat-room.js';
+import { ReversiChannel } from './channels/reversi.js';
+import { ReversiGameChannel } from './channels/reversi-game.js';
+import type { ChannelConstructor } from './channel.js';
import { bindThis } from '@/decorators.js';
-import { HybridTimelineChannelService } from './channels/hybrid-timeline.js';
-import { LocalTimelineChannelService } from './channels/local-timeline.js';
-import { HomeTimelineChannelService } from './channels/home-timeline.js';
-import { GlobalTimelineChannelService } from './channels/global-timeline.js';
-import { MainChannelService } from './channels/main.js';
-import { ChannelChannelService } from './channels/channel.js';
-import { AdminChannelService } from './channels/admin.js';
-import { ServerStatsChannelService } from './channels/server-stats.js';
-import { QueueStatsChannelService } from './channels/queue-stats.js';
-import { UserListChannelService } from './channels/user-list.js';
-import { AntennaChannelService } from './channels/antenna.js';
-import { DriveChannelService } from './channels/drive.js';
-import { HashtagChannelService } from './channels/hashtag.js';
-import { RoleTimelineChannelService } from './channels/role-timeline.js';
-import { ChatUserChannelService } from './channels/chat-user.js';
-import { ChatRoomChannelService } from './channels/chat-room.js';
-import { ReversiChannelService } from './channels/reversi.js';
-import { ReversiGameChannelService } from './channels/reversi-game.js';
-import { type MiChannelService } from './channel.js';
@Injectable()
export class ChannelsService {
constructor(
- private mainChannelService: MainChannelService,
- private homeTimelineChannelService: HomeTimelineChannelService,
- private localTimelineChannelService: LocalTimelineChannelService,
- private hybridTimelineChannelService: HybridTimelineChannelService,
- private globalTimelineChannelService: GlobalTimelineChannelService,
- private userListChannelService: UserListChannelService,
- private hashtagChannelService: HashtagChannelService,
- private roleTimelineChannelService: RoleTimelineChannelService,
- private antennaChannelService: AntennaChannelService,
- private channelChannelService: ChannelChannelService,
- private driveChannelService: DriveChannelService,
- private serverStatsChannelService: ServerStatsChannelService,
- private queueStatsChannelService: QueueStatsChannelService,
- private adminChannelService: AdminChannelService,
- private chatUserChannelService: ChatUserChannelService,
- private chatRoomChannelService: ChatRoomChannelService,
- private reversiChannelService: ReversiChannelService,
- private reversiGameChannelService: ReversiGameChannelService,
) {
}
@bindThis
- public getChannelService(name: string): MiChannelService<boolean> {
+ public getChannelConstructor(name: string): ChannelConstructor<boolean> {
switch (name) {
- case 'main': return this.mainChannelService;
- case 'homeTimeline': return this.homeTimelineChannelService;
- case 'localTimeline': return this.localTimelineChannelService;
- case 'hybridTimeline': return this.hybridTimelineChannelService;
- case 'globalTimeline': return this.globalTimelineChannelService;
- case 'userList': return this.userListChannelService;
- case 'hashtag': return this.hashtagChannelService;
- case 'roleTimeline': return this.roleTimelineChannelService;
- case 'antenna': return this.antennaChannelService;
- case 'channel': return this.channelChannelService;
- case 'drive': return this.driveChannelService;
- case 'serverStats': return this.serverStatsChannelService;
- case 'queueStats': return this.queueStatsChannelService;
- case 'admin': return this.adminChannelService;
- case 'chatUser': return this.chatUserChannelService;
- case 'chatRoom': return this.chatRoomChannelService;
- case 'reversi': return this.reversiChannelService;
- case 'reversiGame': return this.reversiGameChannelService;
+ case 'main': return MainChannel;
+ case 'homeTimeline': return HomeTimelineChannel;
+ case 'localTimeline': return LocalTimelineChannel;
+ case 'hybridTimeline': return HybridTimelineChannel;
+ case 'globalTimeline': return GlobalTimelineChannel;
+ case 'userList': return UserListChannel;
+ case 'hashtag': return HashtagChannel;
+ case 'roleTimeline': return RoleTimelineChannel;
+ case 'antenna': return AntennaChannel;
+ case 'channel': return ChannelChannel;
+ case 'drive': return DriveChannel;
+ case 'serverStats': return ServerStatsChannel;
+ case 'queueStats': return QueueStatsChannel;
+ case 'admin': return AdminChannel;
+ case 'chatUser': return ChatUserChannel;
+ case 'chatRoom': return ChatRoomChannel;
+ case 'reversi': return ReversiChannel;
+ case 'reversiGame': return ReversiGameChannel;
default:
throw new Error(`no such channel: ${name}`);
diff --git a/packages/backend/src/server/api/stream/Connection.ts b/packages/backend/src/server/api/stream/Connection.ts
index 222086c960..d19a223a21 100644
--- a/packages/backend/src/server/api/stream/Connection.ts
+++ b/packages/backend/src/server/api/stream/Connection.ts
@@ -6,19 +6,39 @@
import * as WebSocket from 'ws';
import type { MiUser } from '@/models/User.js';
import type { MiAccessToken } from '@/models/AccessToken.js';
-import type { Packed } from '@/misc/json-schema.js';
-import type { NotificationService } from '@/core/NotificationService.js';
+import { NotificationService } from '@/core/NotificationService.js';
import { bindThis } from '@/decorators.js';
import { CacheService } from '@/core/CacheService.js';
import { MiFollowing, MiUserProfile } from '@/models/_.js';
import type { GlobalEvents, StreamEventEmitter } from '@/core/GlobalEventService.js';
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
-import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
-import type { ChannelsService } from './ChannelsService.js';
+import { isJsonObject } from '@/misc/json-value.js';
import type { EventEmitter } from 'events';
import type Channel from './channel.js';
+import type { ChannelConstructor } from './channel.js';
+import type { ChannelRequest } from './channel.js';
+import { ContextIdFactory, ModuleRef, REQUEST } from '@nestjs/core';
+import { Inject, Injectable, Scope } from '@nestjs/common';
+import { MainChannel } from '@/server/api/stream/channels/main.js';
+import { HomeTimelineChannel } from '@/server/api/stream/channels/home-timeline.js';
+import { LocalTimelineChannel } from '@/server/api/stream/channels/local-timeline.js';
+import { HybridTimelineChannel } from '@/server/api/stream/channels/hybrid-timeline.js';
+import { GlobalTimelineChannel } from '@/server/api/stream/channels/global-timeline.js';
+import { UserListChannel } from '@/server/api/stream/channels/user-list.js';
+import { HashtagChannel } from '@/server/api/stream/channels/hashtag.js';
+import { RoleTimelineChannel } from '@/server/api/stream/channels/role-timeline.js';
+import { AntennaChannel } from '@/server/api/stream/channels/antenna.js';
+import { ChannelChannel } from '@/server/api/stream/channels/channel.js';
+import { DriveChannel } from '@/server/api/stream/channels/drive.js';
+import { ServerStatsChannel } from '@/server/api/stream/channels/server-stats.js';
+import { QueueStatsChannel } from '@/server/api/stream/channels/queue-stats.js';
+import { AdminChannel } from '@/server/api/stream/channels/admin.js';
+import { ChatUserChannel } from '@/server/api/stream/channels/chat-user.js';
+import { ChatRoomChannel } from '@/server/api/stream/channels/chat-room.js';
+import { ReversiChannel } from '@/server/api/stream/channels/reversi.js';
+import { ReversiGameChannel } from '@/server/api/stream/channels/reversi-game.js';
const MAX_CHANNELS_PER_CONNECTION = 32;
@@ -26,6 +46,7 @@ const MAX_CHANNELS_PER_CONNECTION = 32;
* Main stream connection
*/
// eslint-disable-next-line import/no-default-export
+@Injectable({ scope: Scope.TRANSIENT })
export default class Connection {
public user?: MiUser;
public token?: MiAccessToken;
@@ -44,16 +65,16 @@ export default class Connection {
private fetchIntervalId: NodeJS.Timeout | null = null;
constructor(
- private channelsService: ChannelsService,
+ private moduleRef: ModuleRef,
private notificationService: NotificationService,
private cacheService: CacheService,
private channelFollowingService: ChannelFollowingService,
private channelMutingService: ChannelMutingService,
- user: MiUser | null | undefined,
- token: MiAccessToken | null | undefined,
+ @Inject(REQUEST)
+ request: ConnectionRequest,
) {
- if (user) this.user = user;
- if (token) this.token = token;
+ if (request.user) this.user = request.user;
+ if (request.token) this.token = request.token;
}
@bindThis
@@ -232,28 +253,34 @@ export default class Connection {
* チャンネルに接続
*/
@bindThis
- public connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) {
+ public async connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) {
if (this.channels.length >= MAX_CHANNELS_PER_CONNECTION) {
return;
}
- const channelService = this.channelsService.getChannelService(channel);
+ const channelConstructor = this.getChannelConstructor(channel);
- if (channelService.requireCredential && this.user == null) {
+ if (channelConstructor.requireCredential && this.user == null) {
return;
}
- if (this.token && ((channelService.kind && !this.token.permission.some(p => p === channelService.kind))
- || (!channelService.kind && channelService.requireCredential))) {
+ if (this.token && ((channelConstructor.kind && !this.token.permission.some(p => p === channelConstructor.kind))
+ || (!channelConstructor.kind && channelConstructor.requireCredential))) {
return;
}
// 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視
- if (channelService.shouldShare && this.channels.some(c => c.chName === channel)) {
+ if (channelConstructor.shouldShare && this.channels.some(c => c.chName === channel)) {
return;
}
- const ch: Channel = channelService.create(id, this);
+ const contextId = ContextIdFactory.create();
+ this.moduleRef.registerRequestByContextId<ChannelRequest>({
+ id: id,
+ connection: this,
+ }, contextId);
+ const ch: Channel = await this.moduleRef.create<Channel>(channelConstructor, contextId);
+
this.channels.push(ch);
ch.init(params ?? {});
@@ -264,6 +291,33 @@ export default class Connection {
}
}
+ @bindThis
+ public getChannelConstructor(name: string): ChannelConstructor<boolean> {
+ switch (name) {
+ case 'main': return MainChannel;
+ case 'homeTimeline': return HomeTimelineChannel;
+ case 'localTimeline': return LocalTimelineChannel;
+ case 'hybridTimeline': return HybridTimelineChannel;
+ case 'globalTimeline': return GlobalTimelineChannel;
+ case 'userList': return UserListChannel;
+ case 'hashtag': return HashtagChannel;
+ case 'roleTimeline': return RoleTimelineChannel;
+ case 'antenna': return AntennaChannel;
+ case 'channel': return ChannelChannel;
+ case 'drive': return DriveChannel;
+ case 'serverStats': return ServerStatsChannel;
+ case 'queueStats': return QueueStatsChannel;
+ case 'admin': return AdminChannel;
+ case 'chatUser': return ChatUserChannel;
+ case 'chatRoom': return ChatRoomChannel;
+ case 'reversi': return ReversiChannel;
+ case 'reversiGame': return ReversiGameChannel;
+
+ default:
+ throw new Error(`no such channel: ${name}`);
+ }
+ }
+
/**
* チャンネルから切断
* @param id チャンネルコネクションID
@@ -306,3 +360,8 @@ export default class Connection {
}
}
}
+
+export interface ConnectionRequest {
+ user: MiUser | null | undefined,
+ token: MiAccessToken | null | undefined,
+}
diff --git a/packages/backend/src/server/api/stream/channel.ts b/packages/backend/src/server/api/stream/channel.ts
index 465ed4238c..86b073414d 100644
--- a/packages/backend/src/server/api/stream/channel.ts
+++ b/packages/backend/src/server/api/stream/channel.ts
@@ -22,7 +22,7 @@ export default abstract class Channel {
public abstract readonly chName: string;
public static readonly shouldShare: boolean;
public static readonly requireCredential: boolean;
- public static readonly kind?: string | null;
+ public static readonly kind: string | null;
protected get user() {
return this.connection.user;
@@ -85,9 +85,9 @@ export default abstract class Channel {
return false;
}
- constructor(id: string, connection: Connection) {
- this.id = id;
- this.connection = connection;
+ constructor(request: ChannelRequest) {
+ this.id = request.id;
+ this.connection = request.connection;
}
public send(payload: { type: string, body: JsonValue }): void;
@@ -111,9 +111,14 @@ export default abstract class Channel {
public onMessage?(type: string, body: JsonValue): void;
}
-export type MiChannelService<T extends boolean> = {
+export interface ChannelRequest {
+ id: string,
+ connection: Connection,
+}
+
+export interface ChannelConstructor<T extends boolean> {
+ new(...args: any[]): Channel;
shouldShare: boolean;
requireCredential: T;
kind: T extends true ? string : string | null | undefined;
- create: (id: string, connection: Connection) => Channel;
-};
+}
diff --git a/packages/backend/src/server/api/stream/channels/admin.ts b/packages/backend/src/server/api/stream/channels/admin.ts
index 355d5dba21..821888cca0 100644
--- a/packages/backend/src/server/api/stream/channels/admin.ts
+++ b/packages/backend/src/server/api/stream/channels/admin.ts
@@ -3,17 +3,26 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class AdminChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class AdminChannel extends Channel {
public readonly chName = 'admin';
public static shouldShare = true;
public static requireCredential = true as const;
public static kind = 'read:admin:stream';
+ constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+ ) {
+ super(request);
+ }
+
@bindThis
public async init(params: JsonObject) {
// Subscribe admin stream
@@ -22,22 +31,3 @@ class AdminChannel extends Channel {
});
}
}
-
-@Injectable()
-export class AdminChannelService implements MiChannelService<true> {
- public readonly shouldShare = AdminChannel.shouldShare;
- public readonly requireCredential = AdminChannel.requireCredential;
- public readonly kind = AdminChannel.kind;
-
- constructor(
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): AdminChannel {
- return new AdminChannel(
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts
index e08562fdf9..ece9d2c8b1 100644
--- a/packages/backend/src/server/api/stream/channels/antenna.ts
+++ b/packages/backend/src/server/api/stream/channels/antenna.ts
@@ -3,14 +3,16 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class AntennaChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class AntennaChannel extends Channel {
public readonly chName = 'antenna';
public static shouldShare = false;
public static requireCredential = true as const;
@@ -18,12 +20,12 @@ class AntennaChannel extends Channel {
private antennaId: string;
constructor(
- private noteEntityService: NoteEntityService,
+ @Inject(REQUEST)
+ request: ChannelRequest,
- id: string,
- connection: Channel['connection'],
+ private noteEntityService: NoteEntityService,
) {
- super(id, connection);
+ super(request);
//this.onEvent = this.onEvent.bind(this);
}
@@ -55,24 +57,3 @@ class AntennaChannel extends Channel {
this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent);
}
}
-
-@Injectable()
-export class AntennaChannelService implements MiChannelService<true> {
- public readonly shouldShare = AntennaChannel.shouldShare;
- public readonly requireCredential = AntennaChannel.requireCredential;
- public readonly kind = AntennaChannel.kind;
-
- constructor(
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): AntennaChannel {
- return new AntennaChannel(
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts
index c07eaac98d..1706b17526 100644
--- a/packages/backend/src/server/api/stream/channels/channel.ts
+++ b/packages/backend/src/server/api/stream/channels/channel.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
@@ -11,20 +11,23 @@ import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import { isInstanceMuted } from '@/misc/is-instance-muted.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class ChannelChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class ChannelChannel extends Channel {
public readonly chName = 'channel';
public static shouldShare = false;
public static requireCredential = false as const;
private channelId: string;
constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
private noteEntityService: NoteEntityService,
- id: string,
- connection: Channel['connection'],
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -92,24 +95,3 @@ class ChannelChannel extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
-
-@Injectable()
-export class ChannelChannelService implements MiChannelService<false> {
- public readonly shouldShare = ChannelChannel.shouldShare;
- public readonly requireCredential = ChannelChannel.requireCredential;
- public readonly kind = ChannelChannel.kind;
-
- constructor(
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): ChannelChannel {
- return new ChannelChannel(
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/chat-room.ts b/packages/backend/src/server/api/stream/channels/chat-room.ts
index eda333dd30..7f949032e2 100644
--- a/packages/backend/src/server/api/stream/channels/chat-room.ts
+++ b/packages/backend/src/server/api/stream/channels/chat-room.ts
@@ -3,14 +3,16 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import type { JsonObject } from '@/misc/json-value.js';
import { ChatService } from '@/core/ChatService.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class ChatRoomChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class ChatRoomChannel extends Channel {
public readonly chName = 'chatRoom';
public static shouldShare = false;
public static requireCredential = true as const;
@@ -18,12 +20,12 @@ class ChatRoomChannel extends Channel {
private roomId: string;
constructor(
- private chatService: ChatService,
+ @Inject(REQUEST)
+ request: ChannelRequest,
- id: string,
- connection: Channel['connection'],
+ private chatService: ChatService,
) {
- super(id, connection);
+ super(request);
}
@bindThis
@@ -55,24 +57,3 @@ class ChatRoomChannel extends Channel {
this.subscriber.off(`chatRoomStream:${this.roomId}`, this.onEvent);
}
}
-
-@Injectable()
-export class ChatRoomChannelService implements MiChannelService<true> {
- public readonly shouldShare = ChatRoomChannel.shouldShare;
- public readonly requireCredential = ChatRoomChannel.requireCredential;
- public readonly kind = ChatRoomChannel.kind;
-
- constructor(
- private chatService: ChatService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): ChatRoomChannel {
- return new ChatRoomChannel(
- this.chatService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/chat-user.ts b/packages/backend/src/server/api/stream/channels/chat-user.ts
index 5323484ed7..36f3f67b28 100644
--- a/packages/backend/src/server/api/stream/channels/chat-user.ts
+++ b/packages/backend/src/server/api/stream/channels/chat-user.ts
@@ -3,14 +3,16 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import type { JsonObject } from '@/misc/json-value.js';
import { ChatService } from '@/core/ChatService.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class ChatUserChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class ChatUserChannel extends Channel {
public readonly chName = 'chatUser';
public static shouldShare = false;
public static requireCredential = true as const;
@@ -18,12 +20,12 @@ class ChatUserChannel extends Channel {
private otherId: string;
constructor(
- private chatService: ChatService,
+ @Inject(REQUEST)
+ request: ChannelRequest,
- id: string,
- connection: Channel['connection'],
+ private chatService: ChatService,
) {
- super(id, connection);
+ super(request);
}
@bindThis
@@ -55,24 +57,3 @@ class ChatUserChannel extends Channel {
this.subscriber.off(`chatUserStream:${this.user!.id}-${this.otherId}`, this.onEvent);
}
}
-
-@Injectable()
-export class ChatUserChannelService implements MiChannelService<true> {
- public readonly shouldShare = ChatUserChannel.shouldShare;
- public readonly requireCredential = ChatUserChannel.requireCredential;
- public readonly kind = ChatUserChannel.kind;
-
- constructor(
- private chatService: ChatService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): ChatUserChannel {
- return new ChatUserChannel(
- this.chatService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/drive.ts b/packages/backend/src/server/api/stream/channels/drive.ts
index 03768f3d23..6f2eb2c8f9 100644
--- a/packages/backend/src/server/api/stream/channels/drive.ts
+++ b/packages/backend/src/server/api/stream/channels/drive.ts
@@ -3,17 +3,26 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class DriveChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class DriveChannel extends Channel {
public readonly chName = 'drive';
public static shouldShare = true;
public static requireCredential = true as const;
public static kind = 'read:account';
+ constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+ ) {
+ super(request);
+ }
+
@bindThis
public async init(params: JsonObject) {
// Subscribe drive stream
@@ -22,22 +31,3 @@ class DriveChannel extends Channel {
});
}
}
-
-@Injectable()
-export class DriveChannelService implements MiChannelService<true> {
- public readonly shouldShare = DriveChannel.shouldShare;
- public readonly requireCredential = DriveChannel.requireCredential;
- public readonly kind = DriveChannel.kind;
-
- constructor(
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): DriveChannel {
- return new DriveChannel(
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts
index d7c781ad12..be6be1b1e7 100644
--- a/packages/backend/src/server/api/stream/channels/global-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
import { MetaService } from '@/core/MetaService.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
@@ -11,9 +11,11 @@ import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class GlobalTimelineChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class GlobalTimelineChannel extends Channel {
public readonly chName = 'globalTimeline';
public static shouldShare = false;
public static requireCredential = false as const;
@@ -21,14 +23,14 @@ class GlobalTimelineChannel extends Channel {
private withFiles: boolean;
constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
private metaService: MetaService,
private roleService: RoleService,
private noteEntityService: NoteEntityService,
-
- id: string,
- connection: Channel['connection'],
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -74,28 +76,3 @@ class GlobalTimelineChannel extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
-
-@Injectable()
-export class GlobalTimelineChannelService implements MiChannelService<false> {
- public readonly shouldShare = GlobalTimelineChannel.shouldShare;
- public readonly requireCredential = GlobalTimelineChannel.requireCredential;
- public readonly kind = GlobalTimelineChannel.kind;
-
- constructor(
- private metaService: MetaService,
- private roleService: RoleService,
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): GlobalTimelineChannel {
- return new GlobalTimelineChannel(
- this.metaService,
- this.roleService,
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts
index c911d63642..1456b4f262 100644
--- a/packages/backend/src/server/api/stream/channels/hashtag.ts
+++ b/packages/backend/src/server/api/stream/channels/hashtag.ts
@@ -3,28 +3,30 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
import type { Packed } from '@/misc/json-schema.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class HashtagChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class HashtagChannel extends Channel {
public readonly chName = 'hashtag';
public static shouldShare = false;
public static requireCredential = false as const;
private q: string[][];
constructor(
- private noteEntityService: NoteEntityService,
+ @Inject(REQUEST)
+ request: ChannelRequest,
- id: string,
- connection: Channel['connection'],
+ private noteEntityService: NoteEntityService,
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -62,24 +64,3 @@ class HashtagChannel extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
-
-@Injectable()
-export class HashtagChannelService implements MiChannelService<false> {
- public readonly shouldShare = HashtagChannel.shouldShare;
- public readonly requireCredential = HashtagChannel.requireCredential;
- public readonly kind = HashtagChannel.kind;
-
- constructor(
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): HashtagChannel {
- return new HashtagChannel(
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts
index eb5b4a8c6c..665c11b692 100644
--- a/packages/backend/src/server/api/stream/channels/home-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts
@@ -3,15 +3,17 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class HomeTimelineChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class HomeTimelineChannel extends Channel {
public readonly chName = 'homeTimeline';
public static shouldShare = false;
public static requireCredential = true as const;
@@ -20,12 +22,12 @@ class HomeTimelineChannel extends Channel {
private withFiles: boolean;
constructor(
- private noteEntityService: NoteEntityService,
+ @Inject(REQUEST)
+ request: ChannelRequest,
- id: string,
- connection: Channel['connection'],
+ private noteEntityService: NoteEntityService,
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -98,24 +100,3 @@ class HomeTimelineChannel extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
-
-@Injectable()
-export class HomeTimelineChannelService implements MiChannelService<true> {
- public readonly shouldShare = HomeTimelineChannel.shouldShare;
- public readonly requireCredential = HomeTimelineChannel.requireCredential;
- public readonly kind = HomeTimelineChannel.kind;
-
- constructor(
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): HomeTimelineChannel {
- return new HomeTimelineChannel(
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
index 2155e02012..54250d2a90 100644
--- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
import { MetaService } from '@/core/MetaService.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
@@ -11,9 +11,11 @@ import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class HybridTimelineChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class HybridTimelineChannel extends Channel {
public readonly chName = 'hybridTimeline';
public static shouldShare = false;
public static requireCredential = true as const;
@@ -23,14 +25,14 @@ class HybridTimelineChannel extends Channel {
private withFiles: boolean;
constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
private metaService: MetaService,
private roleService: RoleService,
private noteEntityService: NoteEntityService,
-
- id: string,
- connection: Channel['connection'],
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -118,28 +120,3 @@ class HybridTimelineChannel extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
-
-@Injectable()
-export class HybridTimelineChannelService implements MiChannelService<true> {
- public readonly shouldShare = HybridTimelineChannel.shouldShare;
- public readonly requireCredential = HybridTimelineChannel.requireCredential;
- public readonly kind = HybridTimelineChannel.kind;
-
- constructor(
- private metaService: MetaService,
- private roleService: RoleService,
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): HybridTimelineChannel {
- return new HybridTimelineChannel(
- this.metaService,
- this.roleService,
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts
index 3d7ed6acdb..b394e9663f 100644
--- a/packages/backend/src/server/api/stream/channels/local-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
import { MetaService } from '@/core/MetaService.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
@@ -11,25 +11,27 @@ import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import { isQuotePacked, isRenotePacked } from '@/misc/is-renote.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class LocalTimelineChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class LocalTimelineChannel extends Channel {
public readonly chName = 'localTimeline';
- public static shouldShare = false;
+ public static shouldShare = false as const;
public static requireCredential = false as const;
private withRenotes: boolean;
private withReplies: boolean;
private withFiles: boolean;
constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
private metaService: MetaService,
private roleService: RoleService,
private noteEntityService: NoteEntityService,
-
- id: string,
- connection: Channel['connection'],
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -84,28 +86,3 @@ class LocalTimelineChannel extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
-
-@Injectable()
-export class LocalTimelineChannelService implements MiChannelService<false> {
- public readonly shouldShare = LocalTimelineChannel.shouldShare;
- public readonly requireCredential = LocalTimelineChannel.requireCredential;
- public readonly kind = LocalTimelineChannel.kind;
-
- constructor(
- private metaService: MetaService,
- private roleService: RoleService,
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): LocalTimelineChannel {
- return new LocalTimelineChannel(
- this.metaService,
- this.roleService,
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/main.ts b/packages/backend/src/server/api/stream/channels/main.ts
index 525f24c105..2ce53ac288 100644
--- a/packages/backend/src/server/api/stream/channels/main.ts
+++ b/packages/backend/src/server/api/stream/channels/main.ts
@@ -3,26 +3,28 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class MainChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class MainChannel extends Channel {
public readonly chName = 'main';
public static shouldShare = true;
public static requireCredential = true as const;
public static kind = 'read:account';
constructor(
- private noteEntityService: NoteEntityService,
+ @Inject(REQUEST)
+ request: ChannelRequest,
- id: string,
- connection: Channel['connection'],
+ private noteEntityService: NoteEntityService,
) {
- super(id, connection);
+ super(request);
}
@bindThis
@@ -61,24 +63,3 @@ class MainChannel extends Channel {
});
}
}
-
-@Injectable()
-export class MainChannelService implements MiChannelService<true> {
- public readonly shouldShare = MainChannel.shouldShare;
- public readonly requireCredential = MainChannel.requireCredential;
- public readonly kind = MainChannel.kind;
-
- constructor(
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): MainChannel {
- return new MainChannel(
- this.noteEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/queue-stats.ts b/packages/backend/src/server/api/stream/channels/queue-stats.ts
index 91b62255b4..a87863f26c 100644
--- a/packages/backend/src/server/api/stream/channels/queue-stats.ts
+++ b/packages/backend/src/server/api/stream/channels/queue-stats.ts
@@ -4,21 +4,26 @@
*/
import Xev from 'xev';
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
const ev = new Xev();
-class QueueStatsChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class QueueStatsChannel extends Channel {
public readonly chName = 'queueStats';
public static shouldShare = true;
public static requireCredential = false as const;
- constructor(id: string, connection: Channel['connection']) {
- super(id, connection);
+ constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+ ) {
+ super(request);
//this.onStats = this.onStats.bind(this);
//this.onMessage = this.onMessage.bind(this);
}
@@ -56,22 +61,3 @@ class QueueStatsChannel extends Channel {
ev.removeListener('queueStats', this.onStats);
}
}
-
-@Injectable()
-export class QueueStatsChannelService implements MiChannelService<false> {
- public readonly shouldShare = QueueStatsChannel.shouldShare;
- public readonly requireCredential = QueueStatsChannel.requireCredential;
- public readonly kind = QueueStatsChannel.kind;
-
- constructor(
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): QueueStatsChannel {
- return new QueueStatsChannel(
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/reversi-game.ts b/packages/backend/src/server/api/stream/channels/reversi-game.ts
index 7597a1cfa3..58fc16e98c 100644
--- a/packages/backend/src/server/api/stream/channels/reversi-game.ts
+++ b/packages/backend/src/server/api/stream/channels/reversi-game.ts
@@ -3,31 +3,32 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Inject, Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { MiReversiGame } from '@/models/_.js';
-import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { ReversiService } from '@/core/ReversiService.js';
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
import { reversiUpdateKeys } from 'misskey-js';
+import { REQUEST } from '@nestjs/core';
-class ReversiGameChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class ReversiGameChannel extends Channel {
public readonly chName = 'reversiGame';
public static shouldShare = false;
public static requireCredential = false as const;
private gameId: MiReversiGame['id'] | null = null;
constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
private reversiService: ReversiService,
private reversiGameEntityService: ReversiGameEntityService,
-
- id: string,
- connection: Channel['connection'],
) {
- super(id, connection);
+ super(request);
}
@bindThis
@@ -107,25 +108,3 @@ class ReversiGameChannel extends Channel {
}
}
-@Injectable()
-export class ReversiGameChannelService implements MiChannelService<false> {
- public readonly shouldShare = ReversiGameChannel.shouldShare;
- public readonly requireCredential = ReversiGameChannel.requireCredential;
- public readonly kind = ReversiGameChannel.kind;
-
- constructor(
- private reversiService: ReversiService,
- private reversiGameEntityService: ReversiGameEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): ReversiGameChannel {
- return new ReversiGameChannel(
- this.reversiService,
- this.reversiGameEntityService,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/reversi.ts b/packages/backend/src/server/api/stream/channels/reversi.ts
index 6e88939724..5eff73eeef 100644
--- a/packages/backend/src/server/api/stream/channels/reversi.ts
+++ b/packages/backend/src/server/api/stream/channels/reversi.ts
@@ -3,22 +3,24 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class ReversiChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class ReversiChannel extends Channel {
public readonly chName = 'reversi';
public static shouldShare = true;
public static requireCredential = true as const;
public static kind = 'read:account';
constructor(
- id: string,
- connection: Channel['connection'],
+ @Inject(REQUEST)
+ request: ChannelRequest,
) {
- super(id, connection);
+ super(request);
}
@bindThis
@@ -32,22 +34,3 @@ class ReversiChannel extends Channel {
this.subscriber.off(`reversiStream:${this.user!.id}`, this.send);
}
}
-
-@Injectable()
-export class ReversiChannelService implements MiChannelService<true> {
- public readonly shouldShare = ReversiChannel.shouldShare;
- public readonly requireCredential = ReversiChannel.requireCredential;
- public readonly kind = ReversiChannel.kind;
-
- constructor(
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): ReversiChannel {
- return new ReversiChannel(
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/role-timeline.ts b/packages/backend/src/server/api/stream/channels/role-timeline.ts
index fcfa26c38b..99e0b69023 100644
--- a/packages/backend/src/server/api/stream/channels/role-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/role-timeline.ts
@@ -3,28 +3,30 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class RoleTimelineChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class RoleTimelineChannel extends Channel {
public readonly chName = 'roleTimeline';
public static shouldShare = false;
public static requireCredential = false as const;
private roleId: string;
constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
private noteEntityService: NoteEntityService,
private roleservice: RoleService,
-
- id: string,
- connection: Channel['connection'],
) {
- super(id, connection);
+ super(request);
//this.onNote = this.onNote.bind(this);
}
@@ -60,26 +62,3 @@ class RoleTimelineChannel extends Channel {
this.subscriber.off(`roleTimelineStream:${this.roleId}`, this.onEvent);
}
}
-
-@Injectable()
-export class RoleTimelineChannelService implements MiChannelService<false> {
- public readonly shouldShare = RoleTimelineChannel.shouldShare;
- public readonly requireCredential = RoleTimelineChannel.requireCredential;
- public readonly kind = RoleTimelineChannel.kind;
-
- constructor(
- private noteEntityService: NoteEntityService,
- private roleservice: RoleService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): RoleTimelineChannel {
- return new RoleTimelineChannel(
- this.noteEntityService,
- this.roleservice,
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/server-stats.ts b/packages/backend/src/server/api/stream/channels/server-stats.ts
index ec5352d12d..aece5435b0 100644
--- a/packages/backend/src/server/api/stream/channels/server-stats.ts
+++ b/packages/backend/src/server/api/stream/channels/server-stats.ts
@@ -4,21 +4,26 @@
*/
import Xev from 'xev';
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
const ev = new Xev();
-class ServerStatsChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class ServerStatsChannel extends Channel {
public readonly chName = 'serverStats';
public static shouldShare = true;
public static requireCredential = false as const;
- constructor(id: string, connection: Channel['connection']) {
- super(id, connection);
+ constructor(
+ @Inject(REQUEST)
+ request: ChannelRequest,
+ ) {
+ super(request);
//this.onStats = this.onStats.bind(this);
//this.onMessage = this.onMessage.bind(this);
}
@@ -54,22 +59,3 @@ class ServerStatsChannel extends Channel {
ev.removeListener('serverStats', this.onStats);
}
}
-
-@Injectable()
-export class ServerStatsChannelService implements MiChannelService<false> {
- public readonly shouldShare = ServerStatsChannel.shouldShare;
- public readonly requireCredential = ServerStatsChannel.requireCredential;
- public readonly kind = ServerStatsChannel.kind;
-
- constructor(
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): ServerStatsChannel {
- return new ServerStatsChannel(
- id,
- connection,
- );
- }
-}
diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts
index 5bfd8fa68c..2f7345e150 100644
--- a/packages/backend/src/server/api/stream/channels/user-list.ts
+++ b/packages/backend/src/server/api/stream/channels/user-list.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Inject, Injectable } from '@nestjs/common';
+import { Inject, Injectable, Scope } from '@nestjs/common';
import type { MiUserListMembership, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
@@ -11,9 +11,11 @@ import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
import type { JsonObject } from '@/misc/json-value.js';
-import Channel, { type MiChannelService } from '../channel.js';
+import Channel, { type ChannelRequest } from '../channel.js';
+import { REQUEST } from '@nestjs/core';
-class UserListChannel extends Channel {
+@Injectable({ scope: Scope.TRANSIENT })
+export class UserListChannel extends Channel {
public readonly chName = 'userList';
public static shouldShare = false;
public static requireCredential = false as const;
@@ -24,14 +26,18 @@ class UserListChannel extends Channel {
private withRenotes: boolean;
constructor(
+ @Inject(DI.userListsRepository)
private userListsRepository: UserListsRepository,
+
+ @Inject(DI.userListMembershipsRepository)
private userListMembershipsRepository: UserListMembershipsRepository,
- private noteEntityService: NoteEntityService,
- id: string,
- connection: Channel['connection'],
+ @Inject(REQUEST)
+ request: ChannelRequest,
+
+ private noteEntityService: NoteEntityService,
) {
- super(id, connection);
+ super(request);
//this.updateListUsers = this.updateListUsers.bind(this);
//this.onNote = this.onNote.bind(this);
}
@@ -130,32 +136,3 @@ class UserListChannel extends Channel {
clearInterval(this.listUsersClock);
}
}
-
-@Injectable()
-export class UserListChannelService implements MiChannelService<false> {
- public readonly shouldShare = UserListChannel.shouldShare;
- public readonly requireCredential = UserListChannel.requireCredential;
- public readonly kind = UserListChannel.kind;
-
- constructor(
- @Inject(DI.userListsRepository)
- private userListsRepository: UserListsRepository,
-
- @Inject(DI.userListMembershipsRepository)
- private userListMembershipsRepository: UserListMembershipsRepository,
-
- private noteEntityService: NoteEntityService,
- ) {
- }
-
- @bindThis
- public create(id: string, connection: Channel['connection']): UserListChannel {
- return new UserListChannel(
- this.userListsRepository,
- this.userListMembershipsRepository,
- this.noteEntityService,
- id,
- connection,
- );
- }
-}