feat(core): new worker workspace engine (#9257)
This commit is contained in:
@@ -11,9 +11,7 @@ export { AccountChanged } from './events/account-changed';
|
||||
export { AccountLoggedIn } from './events/account-logged-in';
|
||||
export { AccountLoggedOut } from './events/account-logged-out';
|
||||
export { ServerInitialized } from './events/server-initialized';
|
||||
export { RawFetchProvider } from './provider/fetch';
|
||||
export { ValidatorProvider } from './provider/validator';
|
||||
export { WebSocketAuthProvider } from './provider/websocket-auth';
|
||||
export { AuthService } from './services/auth';
|
||||
export { CaptchaService } from './services/captcha';
|
||||
export { DefaultServerService } from './services/default-server';
|
||||
@@ -27,7 +25,6 @@ export { SubscriptionService } from './services/subscription';
|
||||
export { UserCopilotQuotaService } from './services/user-copilot-quota';
|
||||
export { UserFeatureService } from './services/user-feature';
|
||||
export { UserQuotaService } from './services/user-quota';
|
||||
export { WebSocketService } from './services/websocket';
|
||||
export { WorkspaceInvoicesService } from './services/workspace-invoices';
|
||||
export { WorkspaceServerService } from './services/workspace-server';
|
||||
export { WorkspaceSubscriptionService } from './services/workspace-subscription';
|
||||
@@ -51,9 +48,7 @@ import { UserFeature } from './entities/user-feature';
|
||||
import { UserQuota } from './entities/user-quota';
|
||||
import { WorkspaceInvoices } from './entities/workspace-invoices';
|
||||
import { WorkspaceSubscription } from './entities/workspace-subscription';
|
||||
import { DefaultRawFetchProvider, RawFetchProvider } from './provider/fetch';
|
||||
import { ValidatorProvider } from './provider/validator';
|
||||
import { WebSocketAuthProvider } from './provider/websocket-auth';
|
||||
import { ServerScope } from './scopes/server';
|
||||
import { AuthService } from './services/auth';
|
||||
import { CaptchaService } from './services/captcha';
|
||||
@@ -69,7 +64,6 @@ import { SubscriptionService } from './services/subscription';
|
||||
import { UserCopilotQuotaService } from './services/user-copilot-quota';
|
||||
import { UserFeatureService } from './services/user-feature';
|
||||
import { UserQuotaService } from './services/user-quota';
|
||||
import { WebSocketService } from './services/websocket';
|
||||
import { WorkspaceInvoicesService } from './services/workspace-invoices';
|
||||
import { WorkspaceServerService } from './services/workspace-server';
|
||||
import { WorkspaceSubscriptionService } from './services/workspace-subscription';
|
||||
@@ -85,26 +79,16 @@ import { UserQuotaStore } from './stores/user-quota';
|
||||
|
||||
export function configureCloudModule(framework: Framework) {
|
||||
framework
|
||||
.impl(RawFetchProvider, DefaultRawFetchProvider)
|
||||
.service(ServersService, [ServerListStore, ServerConfigStore])
|
||||
.service(DefaultServerService, [ServersService])
|
||||
.store(ServerListStore, [GlobalStateService])
|
||||
.store(ServerConfigStore, [RawFetchProvider])
|
||||
.store(ServerConfigStore)
|
||||
.entity(Server, [ServerListStore])
|
||||
.scope(ServerScope)
|
||||
.service(ServerService, [ServerScope])
|
||||
.service(FetchService, [RawFetchProvider, ServerService])
|
||||
.service(FetchService, [ServerService])
|
||||
.service(EventSourceService, [ServerService])
|
||||
.service(GraphQLService, [FetchService])
|
||||
.service(
|
||||
WebSocketService,
|
||||
f =>
|
||||
new WebSocketService(
|
||||
f.get(ServerService),
|
||||
f.get(AuthService),
|
||||
f.getOptional(WebSocketAuthProvider)
|
||||
)
|
||||
)
|
||||
.service(CaptchaService, f => {
|
||||
return new CaptchaService(
|
||||
f.get(ServerService),
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { createIdentifier } from '@toeverything/infra';
|
||||
|
||||
import type { FetchInit } from '../services/fetch';
|
||||
|
||||
export interface RawFetchProvider {
|
||||
/**
|
||||
* standard fetch, in ios&android, we can use native fetch to implement this
|
||||
*/
|
||||
fetch: (input: string | URL, init?: FetchInit) => Promise<Response>;
|
||||
}
|
||||
|
||||
export const RawFetchProvider =
|
||||
createIdentifier<RawFetchProvider>('FetchProvider');
|
||||
|
||||
export const DefaultRawFetchProvider = {
|
||||
fetch: globalThis.fetch.bind(globalThis),
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
import { createIdentifier } from '@toeverything/infra';
|
||||
|
||||
export interface WebSocketAuthProvider {
|
||||
/**
|
||||
* Returns the token and userId for WebSocket authentication
|
||||
*
|
||||
* Useful when cookies are not available for WebSocket connections
|
||||
*
|
||||
* @param url - The URL of the WebSocket endpoint
|
||||
*/
|
||||
getAuthToken: (url: string) => Promise<
|
||||
| {
|
||||
token?: string;
|
||||
userId?: string;
|
||||
}
|
||||
| undefined
|
||||
>;
|
||||
}
|
||||
|
||||
export const WebSocketAuthProvider = createIdentifier<WebSocketAuthProvider>(
|
||||
'WebSocketAuthProvider'
|
||||
);
|
||||
@@ -3,7 +3,6 @@ import { UserFriendlyError } from '@affine/graphql';
|
||||
import { fromPromise, Service } from '@toeverything/infra';
|
||||
|
||||
import { BackendError, NetworkError } from '../error';
|
||||
import type { RawFetchProvider } from '../provider/fetch';
|
||||
import type { ServerService } from './server';
|
||||
|
||||
const logger = new DebugLogger('affine:fetch');
|
||||
@@ -11,10 +10,7 @@ const logger = new DebugLogger('affine:fetch');
|
||||
export type FetchInit = RequestInit & { timeout?: number };
|
||||
|
||||
export class FetchService extends Service {
|
||||
constructor(
|
||||
private readonly fetchProvider: RawFetchProvider,
|
||||
private readonly serverService: ServerService
|
||||
) {
|
||||
constructor(private readonly serverService: ServerService) {
|
||||
super();
|
||||
}
|
||||
rxFetch = (
|
||||
@@ -50,7 +46,7 @@ export class FetchService extends Service {
|
||||
abortController.abort('timeout');
|
||||
}, timeout);
|
||||
|
||||
const res = await this.fetchProvider
|
||||
const res = await globalThis
|
||||
.fetch(new URL(input, this.serverService.server.serverMetadata.baseUrl), {
|
||||
...init,
|
||||
signal: abortController.signal,
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
import { OnEvent, Service } from '@toeverything/infra';
|
||||
import { Manager } from 'socket.io-client';
|
||||
|
||||
import { ApplicationStarted } from '../../lifecycle';
|
||||
import { AccountChanged } from '../events/account-changed';
|
||||
import type { WebSocketAuthProvider } from '../provider/websocket-auth';
|
||||
import type { AuthService } from './auth';
|
||||
import type { ServerService } from './server';
|
||||
|
||||
@OnEvent(AccountChanged, e => e.update)
|
||||
@OnEvent(ApplicationStarted, e => e.update)
|
||||
export class WebSocketService extends Service {
|
||||
ioManager: Manager = new Manager(`${this.serverService.server.baseUrl}/`, {
|
||||
autoConnect: false,
|
||||
transports: ['websocket'],
|
||||
secure: location.protocol === 'https:',
|
||||
});
|
||||
socket = this.ioManager.socket('/', {
|
||||
auth: this.webSocketAuthProvider
|
||||
? cb => {
|
||||
this.webSocketAuthProvider
|
||||
?.getAuthToken(`${this.serverService.server.baseUrl}/`)
|
||||
.then(v => {
|
||||
cb(v ?? {});
|
||||
})
|
||||
.catch(e => {
|
||||
console.error('Failed to get auth token for websocket', e);
|
||||
});
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
refCount = 0;
|
||||
|
||||
constructor(
|
||||
private readonly serverService: ServerService,
|
||||
private readonly authService: AuthService,
|
||||
private readonly webSocketAuthProvider?: WebSocketAuthProvider
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect socket, with automatic connect and reconnect logic.
|
||||
* External code should not call `socket.connect()` or `socket.disconnect()` manually.
|
||||
* When socket is no longer needed, call `dispose()` to clean up resources.
|
||||
*/
|
||||
connect() {
|
||||
this.refCount++;
|
||||
this.update();
|
||||
return {
|
||||
socket: this.socket,
|
||||
dispose: () => {
|
||||
this.refCount--;
|
||||
this.update();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
update(): void {
|
||||
if (this.authService.session.account$.value && this.refCount > 0) {
|
||||
this.socket.connect();
|
||||
} else {
|
||||
this.socket.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,11 @@ import {
|
||||
} from '@affine/graphql';
|
||||
import { Store } from '@toeverything/infra';
|
||||
|
||||
import type { RawFetchProvider } from '../provider/fetch';
|
||||
|
||||
export type ServerConfigType = ServerConfigQuery['serverConfig'] &
|
||||
OauthProvidersQuery['serverConfig'];
|
||||
|
||||
export class ServerConfigStore extends Store {
|
||||
constructor(private readonly fetcher: RawFetchProvider) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -22,10 +20,7 @@ export class ServerConfigStore extends Store {
|
||||
serverBaseUrl: string,
|
||||
abortSignal?: AbortSignal
|
||||
): Promise<ServerConfigType> {
|
||||
const gql = gqlFetcherFactory(
|
||||
`${serverBaseUrl}/graphql`,
|
||||
this.fetcher.fetch
|
||||
);
|
||||
const gql = gqlFetcherFactory(`${serverBaseUrl}/graphql`, globalThis.fetch);
|
||||
const serverConfigData = await gql({
|
||||
query: serverConfigQuery,
|
||||
context: {
|
||||
|
||||
Reference in New Issue
Block a user