fix(server): realtime loading (#14959)

#### PR Dependency Tree


* **PR #14959** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Rewired realtime and copilot services to require their runtime
dependencies, improving reliability and removing nullable/optional
runtime paths.

* **Tests**
* Centralized service creation in tests with helper factories and added
checks ensuring realtime dependency injection is configured as expected.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14959)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-05-14 11:54:45 +08:00
committed by GitHub
parent 419fc5d5e0
commit f626dbd590
11 changed files with 83 additions and 45 deletions
@@ -1,4 +1,4 @@
import { Injectable, OnModuleInit, Optional } from '@nestjs/common';
import { Injectable, OnModuleInit } from '@nestjs/common';
import { z } from 'zod';
import { OnEvent } from '../../../base';
@@ -22,8 +22,8 @@ export class CopilotEmbeddingRealtimeProvider implements OnModuleInit {
private readonly ac: AccessController,
private readonly models: Models,
private readonly context: CopilotContextService,
@Optional() private readonly registry?: RealtimeRegistry,
@Optional() private readonly publisher?: RealtimePublisher
private readonly registry: RealtimeRegistry,
private readonly publisher: RealtimePublisher
) {}
onModuleInit() {
@@ -1,10 +1,10 @@
import { Injectable, OnModuleInit, Optional } from '@nestjs/common';
import { Injectable, OnModuleInit } from '@nestjs/common';
import { z } from 'zod';
import { CopilotTranscriptionJobNotFound } from '../../../base';
import { AccessController } from '../../../core/permission';
import {
type RealtimeRegistry,
RealtimeRegistry,
realtimeTranscriptTaskRoom,
registerRealtimeLiveQuery,
} from '../../../core/realtime';
@@ -15,7 +15,7 @@ export class CopilotTranscriptRealtimeProvider implements OnModuleInit {
constructor(
private readonly ac: AccessController,
private readonly transcript: CopilotTranscriptionReader,
@Optional() private readonly registry?: RealtimeRegistry
private readonly registry: RealtimeRegistry
) {}
onModuleInit() {
@@ -1,4 +1,4 @@
import { BadRequestException, Injectable, Optional } from '@nestjs/common';
import { BadRequestException, Injectable } from '@nestjs/common';
import { AiJobStatus } from '@prisma/client';
import {
@@ -10,7 +10,7 @@ import {
sniffMime,
} from '../../../base';
import {
type RealtimePublisher,
RealtimePublisher,
realtimeTranscriptTaskRoom,
} from '../../../core/realtime';
import { Models } from '../../../models';
@@ -45,8 +45,8 @@ export class CopilotTranscriptionService {
private readonly tasks: TaskPolicy,
private readonly prompts: PromptService,
private readonly actionBridge: ActionRuntimeBridge,
@Optional() private readonly access?: CopilotAccessPolicy,
@Optional() private readonly realtime?: RealtimePublisher
private readonly access: CopilotAccessPolicy,
private readonly realtime: RealtimePublisher
) {}
private parseTaskPayload(payload: unknown): TranscriptionPayloadV2 {
@@ -180,7 +180,7 @@ export class CopilotTranscriptionService {
throw new CopilotTranscriptionJobExists();
}
await this.access?.assertQuotaOrByok({
await this.access.assertQuotaOrByok({
userId,
workspaceId,
featureKind: 'transcript',
@@ -234,7 +234,7 @@ export class CopilotTranscriptionService {
);
}
await this.access?.assertQuotaOrByok({
await this.access.assertQuotaOrByok({
userId,
workspaceId,
featureKind: 'transcript',
@@ -282,7 +282,7 @@ export class CopilotTranscriptionService {
return taskToJob(task);
}
await this.access?.assertQuotaOrByok({
await this.access.assertQuotaOrByok({
userId,
workspaceId,
featureKind: 'transcript',
@@ -412,7 +412,7 @@ export class CopilotTranscriptionService {
status: AiJobStatus,
error?: string
) {
this.realtime?.publish(
this.realtime.publish(
'copilot.transcript.task.changed',
{ workspaceId, taskId },
{ taskId, status, error },