refactor(core): adjust effect api (#11935)

This commit is contained in:
EYHN
2025-04-24 10:06:11 +00:00
parent 1d38e5787b
commit eaa1bc6bf1
41 changed files with 79 additions and 146 deletions
@@ -95,13 +95,6 @@ export function effect(...args: any[]) {
function subscribe() { function subscribe() {
subscription = subject$.pipe.apply(subject$, args as any).subscribe({ subscription = subject$.pipe.apply(subject$, args as any).subscribe({
next(value) {
const error = new EffectError('should not emit value', value);
// make a uncaught exception
setTimeout(() => {
throw error;
}, 0);
},
complete() { complete() {
const error = new EffectError('effect unexpected complete'); const error = new EffectError('effect unexpected complete');
// make a uncaught exception // make a uncaught exception
@@ -7,7 +7,7 @@ import {
exhaustMapWithTrailing, exhaustMapWithTrailing,
fromPromise, fromPromise,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { debounceTime, EMPTY, mergeMap, Observable, timeout } from 'rxjs'; import { debounceTime, Observable, timeout } from 'rxjs';
import { logger } from '../logger'; import { logger } from '../logger';
@@ -127,8 +127,7 @@ export class PersistentJSONFileStorage implements Memento {
timeout(5000), timeout(5000),
backoffRetry({ backoffRetry({
count: Infinity, count: Infinity,
}), })
mergeMap(() => EMPTY)
); );
}) })
); );
@@ -44,14 +44,7 @@ import {
} from '@toeverything/infra'; } from '@toeverything/infra';
import { useSetAtom } from 'jotai'; import { useSetAtom } from 'jotai';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { import { catchError, EMPTY, finalize, switchMap, tap, timeout } from 'rxjs';
catchError,
EMPTY,
finalize,
mergeMap,
switchMap,
timeout,
} from 'rxjs';
/** /**
* @deprecated just for legacy code, will be removed in the future * @deprecated just for legacy code, will be removed in the future
@@ -88,12 +81,11 @@ export const WorkspaceSideEffects = () => {
return { doc, mode }; return { doc, mode };
}).pipe( }).pipe(
timeout(10000 /* 10s */), timeout(10000 /* 10s */),
mergeMap(({ mode, doc }) => { tap(({ mode, doc }) => {
if (doc) { if (doc) {
docsList.setPrimaryMode(doc.id, mode as DocMode); docsList.setPrimaryMode(doc.id, mode as DocMode);
workbench.openDoc(doc.id); workbench.openDoc(doc.id);
} }
return EMPTY;
}), }),
onStart(() => { onStart(() => {
pushGlobalLoadingEvent({ pushGlobalLoadingEvent({
@@ -11,7 +11,7 @@ import { effect, fromPromise, useServices } from '@toeverything/infra';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import { EMPTY, mergeMap, switchMap } from 'rxjs'; import { switchMap } from 'rxjs';
import { generateSubscriptionCallbackLink } from '../../../components/hooks/affine/use-subscription-notify'; import { generateSubscriptionCallbackLink } from '../../../components/hooks/affine/use-subscription-notify';
import { import {
@@ -162,7 +162,7 @@ export const Component = () => {
const e = UserFriendlyError.fromAny(err); const e = UserFriendlyError.fromAny(err);
setMessage(e.message); setMessage(e.message);
} }
}).pipe(mergeMap(() => EMPTY)); });
}) })
); );
@@ -6,7 +6,7 @@ import {
LiveData, LiveData,
Service, Service,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { catchError, distinctUntilChanged, EMPTY, mergeMap } from 'rxjs'; import { catchError, distinctUntilChanged, EMPTY } from 'rxjs';
import type { NavigationGestureProvider } from '../providers/navigation-gesture'; import type { NavigationGestureProvider } from '../providers/navigation-gesture';
@@ -35,7 +35,6 @@ export class NavigationGestureService extends Service {
} }
return; return;
}).pipe( }).pipe(
mergeMap(() => EMPTY),
catchError(err => { catchError(err => {
logger.error('navigationGestureProvider error', err); logger.error('navigationGestureProvider error', err);
return EMPTY; return EMPTY;
@@ -5,13 +5,7 @@ import {
fromPromise, fromPromise,
Service, Service,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { import { catchError, distinctUntilChanged, EMPTY, throttleTime } from 'rxjs';
catchError,
distinctUntilChanged,
EMPTY,
mergeMap,
throttleTime,
} from 'rxjs';
import type { AIButtonProvider } from '../provider/ai-button'; import type { AIButtonProvider } from '../provider/ai-button';
@@ -37,7 +31,6 @@ export class AIButtonService extends Service {
} }
return; return;
}).pipe( }).pipe(
mergeMap(() => EMPTY),
catchError(err => { catchError(err => {
logger.error('presentAIButton error', err); logger.error('presentAIButton error', err);
return EMPTY; return EMPTY;
@@ -7,7 +7,7 @@ import {
onStart, onStart,
Service, Service,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap, switchMap } from 'rxjs'; import { switchMap, tap } from 'rxjs';
import type { DesktopApiService } from '../../desktop-api'; import type { DesktopApiService } from '../../desktop-api';
import type { WorkspacesService } from '../../workspace'; import type { WorkspacesService } from '../../workspace';
@@ -37,9 +37,8 @@ export class BackupService extends Service {
fromPromise(async () => { fromPromise(async () => {
return this.desktopApiService.handler.workspace.getBackupWorkspaces(); return this.desktopApiService.handler.workspace.getBackupWorkspaces();
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.pageBackupWorkspaces$.setValue(data); this.pageBackupWorkspaces$.setValue(data);
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isLoading$.setValue(true)), onStart(() => this.isLoading$.setValue(true)),
@@ -9,14 +9,13 @@ import {
} from '@toeverything/infra'; } from '@toeverything/infra';
import { fileTypeFromBuffer } from 'file-type'; import { fileTypeFromBuffer } from 'file-type';
import { import {
EMPTY,
filter, filter,
firstValueFrom, firstValueFrom,
fromEvent, fromEvent,
map, map,
mergeMap,
switchMap, switchMap,
takeUntil, takeUntil,
tap,
} from 'rxjs'; } from 'rxjs';
import type { DocsSearchService } from '../../docs-search'; import type { DocsSearchService } from '../../docs-search';
@@ -46,9 +45,8 @@ export class UnusedBlobs extends Entity {
fromPromise(async () => { fromPromise(async () => {
return await this.getUnusedBlobs(); return await this.getUnusedBlobs();
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.unusedBlobs$.setValue(data); this.unusedBlobs$.setValue(data);
return EMPTY;
}), }),
onStart(() => this.isLoading$.setValue(true)), onStart(() => this.isLoading$.setValue(true)),
onComplete(() => this.isLoading$.setValue(false)) onComplete(() => this.isLoading$.setValue(false))
@@ -10,7 +10,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import type { DocService } from '../../doc'; import type { DocService } from '../../doc';
import type { GlobalCache } from '../../storage'; import type { GlobalCache } from '../../storage';
@@ -47,9 +47,8 @@ export class CloudDocMeta extends Entity {
this.store.fetchCloudDocMeta(this.workspaceId, this.docId) this.store.fetchCloudDocMeta(this.workspaceId, this.docId)
).pipe( ).pipe(
smartRetry(), smartRetry(),
mergeMap(meta => { tap(meta => {
this.cache.set<CloudDocMetaType>(this.cacheKey, meta); this.cache.set<CloudDocMetaType>(this.cacheKey, meta);
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -10,7 +10,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, map, mergeMap } from 'rxjs'; import { map, tap } from 'rxjs';
import type { InvoicesStore } from '../stores/invoices'; import type { InvoicesStore } from '../stores/invoices';
@@ -44,10 +44,9 @@ export class Invoices extends Entity {
signal signal
); );
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.invoiceCount$.setValue(data.invoiceCount); this.invoiceCount$.setValue(data.invoiceCount);
this.pageInvoices$.setValue(data.invoices); this.pageInvoices$.setValue(data.invoices);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -8,7 +8,7 @@ import {
onComplete, onComplete,
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, map, mergeMap } from 'rxjs'; import { exhaustMap, map, tap } from 'rxjs';
import { ServerScope } from '../scopes/server'; import { ServerScope } from '../scopes/server';
import { AuthService } from '../services/auth'; import { AuthService } from '../services/auth';
@@ -77,7 +77,7 @@ export class Server extends Entity<{
backoffRetry({ backoffRetry({
count: Infinity, count: Infinity,
}), }),
mergeMap(config => { tap(config => {
this.serverListStore.updateServerConfig(this.serverMetadata.id, { this.serverListStore.updateServerConfig(this.serverMetadata.id, {
credentialsRequirement: config.credentialsRequirement, credentialsRequirement: config.credentialsRequirement,
features: config.features, features: config.features,
@@ -87,7 +87,6 @@ export class Server extends Entity<{
version: config.version, version: config.version,
initialized: config.initialized, initialized: config.initialized,
}); });
return EMPTY;
}), }),
onStart(() => { onStart(() => {
this.isConfigRevalidating$.next(true); this.isConfigRevalidating$.next(true);
@@ -10,7 +10,7 @@ import {
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import { validateAndReduceImage } from '../../../utils/reduce-image'; import { validateAndReduceImage } from '../../../utils/reduce-image';
import type { AccountProfile, AuthStore } from '../stores/auth'; import type { AccountProfile, AuthStore } from '../stores/auth';
@@ -78,11 +78,10 @@ export class AuthSession extends Entity {
backoffRetry({ backoffRetry({
count: Infinity, count: Infinity,
}), }),
mergeMap(sessionInfo => { tap(sessionInfo => {
if (!isEqual(this.store.getCachedAuthSession(), sessionInfo)) { if (!isEqual(this.store.getCachedAuthSession(), sessionInfo)) {
this.store.setCachedAuthSession(sessionInfo); this.store.setCachedAuthSession(sessionInfo);
} }
return EMPTY;
}), }),
onStart(() => { onStart(() => {
this.isRevalidating$.next(true); this.isRevalidating$.next(true);
@@ -15,7 +15,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, map, mergeMap } from 'rxjs'; import { map, tap } from 'rxjs';
import type { AuthService } from '../services/auth'; import type { AuthService } from '../services/auth';
import type { ServerService } from '../services/server'; import type { ServerService } from '../services/server';
@@ -122,7 +122,7 @@ export class Subscription extends Entity {
}; };
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data) { if (data) {
this.store.setCachedSubscriptions( this.store.setCachedSubscriptions(
data.userId, data.userId,
@@ -132,7 +132,6 @@ export class Subscription extends Entity {
} else { } else {
this.subscription$.next(undefined); this.subscription$.next(undefined);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -9,7 +9,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, map, mergeMap } from 'rxjs'; import { map, tap } from 'rxjs';
import type { AuthService } from '../services/auth'; import type { AuthService } from '../services/auth';
import type { ServerService } from '../services/server'; import type { ServerService } from '../services/server';
@@ -54,7 +54,7 @@ export class UserCopilotQuota extends Entity {
return aiQuota; return aiQuota;
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data) { if (data) {
const { limit, used } = data; const { limit, used } = data;
this.copilotActionUsed$.next(used); this.copilotActionUsed$.next(used);
@@ -65,7 +65,6 @@ export class UserCopilotQuota extends Entity {
this.copilotActionUsed$.next(null); this.copilotActionUsed$.next(null);
this.copilotActionLimit$.next(null); this.copilotActionLimit$.next(null);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -10,7 +10,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, map, mergeMap } from 'rxjs'; import { map, tap } from 'rxjs';
import type { AuthService } from '../services/auth'; import type { AuthService } from '../services/auth';
import type { UserFeatureStore } from '../stores/user-feature'; import type { UserFeatureStore } from '../stores/user-feature';
@@ -64,13 +64,12 @@ export class UserFeature extends Entity {
}; };
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data) { if (data) {
this.features$.next(data.features); this.features$.next(data.features);
} else { } else {
this.features$.next(null); this.features$.next(null);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -12,7 +12,7 @@ import {
} from '@toeverything/infra'; } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme'; import { cssVar } from '@toeverything/theme';
import bytes from 'bytes'; import bytes from 'bytes';
import { EMPTY, map, mergeMap } from 'rxjs'; import { map, tap } from 'rxjs';
import type { AuthService } from '../services/auth'; import type { AuthService } from '../services/auth';
import type { UserQuotaStore } from '../stores/user-quota'; import type { UserQuotaStore } from '../stores/user-quota';
@@ -79,7 +79,7 @@ export class UserQuota extends Entity {
return { quota, used }; return { quota, used };
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data) { if (data) {
const { quota, used } = data; const { quota, used } = data;
this.quota$.next(quota); this.quota$.next(quota);
@@ -88,7 +88,6 @@ export class UserQuota extends Entity {
this.quota$.next(null); this.quota$.next(null);
this.used$.next(null); this.used$.next(null);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -10,7 +10,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, map, mergeMap } from 'rxjs'; import { map, tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { WorkspaceServerService } from '../services/workspace-server'; import type { WorkspaceServerService } from '../services/workspace-server';
@@ -55,10 +55,9 @@ export class WorkspaceInvoices extends Entity {
signal signal
); );
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.invoiceCount$.setValue(data.invoiceCount); this.invoiceCount$.setValue(data.invoiceCount);
this.pageInvoices$.setValue(data.invoices); this.pageInvoices$.setValue(data.invoices);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -11,7 +11,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { WorkspaceServerService } from '../services/workspace-server'; import type { WorkspaceServerService } from '../services/workspace-server';
@@ -123,7 +123,7 @@ export class WorkspaceSubscription extends Entity {
}; };
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data && data.subscription && data.workspaceId && this.store) { if (data && data.subscription && data.workspaceId && this.store) {
this.store.setCachedWorkspaceSubscription( this.store.setCachedWorkspaceSubscription(
data.workspaceId, data.workspaceId,
@@ -133,7 +133,6 @@ export class WorkspaceSubscription extends Entity {
} else { } else {
this.subscription$.next(undefined); this.subscription$.next(undefined);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -7,7 +7,7 @@ import {
onStart, onStart,
Service, Service,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, mergeMap, switchMap } from 'rxjs'; import { exhaustMap, switchMap, tap } from 'rxjs';
import type { ValidatorProvider } from '../provider/validator'; import type { ValidatorProvider } from '../provider/validator';
import type { FetchService } from './fetch'; import type { FetchService } from './fetch';
@@ -58,11 +58,10 @@ export class CaptchaService extends Service {
} }
return { challenge: data.challenge, token: undefined }; return { challenge: data.challenge, token: undefined };
}).pipe( }).pipe(
mergeMap(({ challenge, token }) => { tap(({ challenge, token }) => {
this.verifyToken$.next(token); this.verifyToken$.next(token);
this.challenge$.next(challenge); this.challenge$.next(challenge);
this.resetAfter5min(); this.resetAfter5min();
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => { onStart(() => {
@@ -83,11 +82,10 @@ export class CaptchaService extends Service {
}); });
return true; return true;
}).pipe( }).pipe(
mergeMap(_ => { tap(_ => {
this.challenge$.next(undefined); this.challenge$.next(undefined);
this.verifyToken$.next(undefined); this.verifyToken$.next(undefined);
this.isLoading$.next(false); this.isLoading$.next(false);
return EMPTY;
}) })
); );
}) })
@@ -9,7 +9,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap, switchMap } from 'rxjs'; import { EMPTY, switchMap, tap } from 'rxjs';
import type { AcceptInviteStore } from '../stores/accept-invite'; import type { AcceptInviteStore } from '../stores/accept-invite';
import type { InviteInfoStore } from '../stores/invite-info'; import type { InviteInfoStore } from '../stores/invite-info';
@@ -36,9 +36,8 @@ export class InvitationService extends Service {
return fromPromise(async () => { return fromPromise(async () => {
return await this.inviteInfoStore.getInviteInfo(inviteId); return await this.inviteInfoStore.getInviteInfo(inviteId);
}).pipe( }).pipe(
mergeMap(res => { tap(res => {
this.inviteInfo$.setValue(res); this.inviteInfo$.setValue(res);
return EMPTY;
}), }),
smartRetry({ smartRetry({
count: 1, count: 1,
@@ -7,7 +7,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { catchError, EMPTY, exhaustMap, groupBy, mergeMap } from 'rxjs'; import { catchError, EMPTY, exhaustMap, groupBy, mergeMap, tap } from 'rxjs';
import type { PublicUserStore } from '../stores/public-user'; import type { PublicUserStore } from '../stores/public-user';
@@ -98,10 +98,9 @@ export class PublicUserService extends Service {
this.setError(id, error); this.setError(id, error);
return EMPTY; return EMPTY;
}), }),
mergeMap(user => { tap(user => {
this.setPublicUser(id, user); this.setPublicUser(id, user);
this.setError(id, null); // clear error this.setError(id, null); // clear error
return EMPTY;
}), }),
onStart(() => this.setLoading(id, true)), onStart(() => this.setLoading(id, true)),
onComplete(() => this.setLoading(id, false)) onComplete(() => this.setLoading(id, false))
@@ -9,7 +9,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { exhaustMap, tap } from 'rxjs';
import type { SelfhostGenerateLicenseStore } from '../stores/selfhost-generate-license'; import type { SelfhostGenerateLicenseStore } from '../stores/selfhost-generate-license';
@@ -27,9 +27,8 @@ export class SelfhostGenerateLicenseService extends Service {
return await this.store.generateKey(sessionId); return await this.store.generateKey(sessionId);
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(key => { tap(key => {
this.licenseKey$.next(key); this.licenseKey$.next(key);
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => { onStart(() => {
@@ -10,7 +10,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { SelfhostLicenseStore } from '../stores/selfhost-license'; import type { SelfhostLicenseStore } from '../stores/selfhost-license';
@@ -36,12 +36,10 @@ export class SelfhostLicenseService extends Service {
return await this.store.getLicense(currentWorkspaceId, signal); return await this.store.getLicense(currentWorkspaceId, signal);
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data) { if (data) {
this.license$.next(data); this.license$.next(data);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$), catchErrorInto(this.error$),
onStart(() => this.isRevalidating$.next(true)), onStart(() => this.isRevalidating$.next(true)),
@@ -8,7 +8,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { catchError, EMPTY, mergeMap } from 'rxjs'; import { catchError, EMPTY, tap } from 'rxjs';
import type { import type {
UpdateUserSettingsInput, UpdateUserSettingsInput,
@@ -33,9 +33,8 @@ export class UserSettingsService extends Service {
return this.store.getUserSettings(); return this.store.getUserSettings();
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(settings => { tap(settings => {
this.userSettings$.value = settings; this.userSettings$.value = settings;
return EMPTY;
}), }),
catchError(error => { catchError(error => {
this.error$.value = error; this.error$.value = error;
@@ -7,7 +7,7 @@ import {
SUPPORTED_LANGUAGES, SUPPORTED_LANGUAGES,
} from '@affine/i18n'; } from '@affine/i18n';
import { effect, Entity, fromPromise, LiveData } from '@toeverything/infra'; import { effect, Entity, fromPromise, LiveData } from '@toeverything/infra';
import { catchError, EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { catchError, EMPTY, exhaustMap } from 'rxjs';
import type { GlobalCache } from '../../storage'; import type { GlobalCache } from '../../storage';
@@ -76,8 +76,7 @@ export class I18n extends Entity {
logger.error('Failed to change language', error); logger.error('Failed to change language', error);
return EMPTY; return EMPTY;
}), })
mergeMap(() => EMPTY)
) )
) )
); );
@@ -8,7 +8,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap, switchMap } from 'rxjs'; import { switchMap, tap } from 'rxjs';
import type { TemplateDownloaderStore } from '../store/downloader'; import type { TemplateDownloaderStore } from '../store/downloader';
@@ -24,9 +24,8 @@ export class TemplateDownloader extends Entity {
readonly download = effect( readonly download = effect(
switchMap(({ snapshotUrl }: { snapshotUrl: string }) => { switchMap(({ snapshotUrl }: { snapshotUrl: string }) => {
return fromPromise(() => this.store.download(snapshotUrl)).pipe( return fromPromise(() => this.store.download(snapshotUrl)).pipe(
mergeMap(({ data }) => { tap(({ data }) => {
this.data$.next(data); this.data$.next(data);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -5,7 +5,7 @@ import {
onComplete, onComplete,
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { catchError, EMPTY, mergeMap, Observable, switchMap } from 'rxjs'; import { catchError, EMPTY, Observable, switchMap, tap } from 'rxjs';
import type { ReadwiseStore } from '../store/readwise'; import type { ReadwiseStore } from '../store/readwise';
import type { import type {
@@ -129,9 +129,8 @@ export class ReadwiseCrawler extends Entity {
abortController?.abort(); abortController?.abort();
}; };
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.data$.next(data); this.data$.next(data);
return EMPTY;
}), }),
catchError(err => { catchError(err => {
this.error$.next(err); this.error$.next(err);
@@ -10,7 +10,7 @@ import {
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { clamp } from 'lodash-es'; import { clamp } from 'lodash-es';
import { EMPTY, mergeMap, switchMap } from 'rxjs'; import { mergeMap, switchMap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
@@ -194,7 +194,6 @@ export class AudioMedia extends Entity<AudioSource> {
`Calculate audio stats time: ${performance.now() - startTime}ms` `Calculate audio stats time: ${performance.now() - startTime}ms`
); );
}), }),
mergeMap(() => EMPTY),
onStart(() => this.loading$.setValue(true)), onStart(() => this.loading$.setValue(true)),
onComplete(() => { onComplete(() => {
this.loading$.setValue(false); this.loading$.setValue(false);
@@ -10,7 +10,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap, switchMap, timer } from 'rxjs'; import { switchMap, tap, timer } from 'rxjs';
import { AccountChanged, type AuthService } from '../../cloud'; import { AccountChanged, type AuthService } from '../../cloud';
import { ServerStarted } from '../../cloud/events/server-started'; import { ServerStarted } from '../../cloud/events/server-started';
@@ -45,9 +45,8 @@ export class NotificationCountService extends Service {
} }
return this.store.getNotificationCount(signal); return this.store.getNotificationCount(signal);
}).pipe( }).pipe(
mergeMap(result => { tap(result => {
this.setCount(result ?? 0); this.setCount(result ?? 0);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -8,7 +8,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { EMPTY, exhaustMap, tap } from 'rxjs';
import type { Notification, NotificationStore } from '../stores/notification'; import type { Notification, NotificationStore } from '../stores/notification';
import type { NotificationCountService } from './count'; import type { NotificationCountService } from './count';
@@ -43,10 +43,10 @@ export class NotificationListService extends Service {
signal signal
) )
).pipe( ).pipe(
mergeMap(result => { tap(result => {
if (!result) { if (!result) {
// If the user is not logged in, we just ignore the result. // If the user is not logged in, we just ignore the result.
return EMPTY; return;
} }
const { edges, pageInfo, totalCount } = result; const { edges, pageInfo, totalCount } = result;
this.notifications$.next([ this.notifications$.next([
@@ -59,8 +59,6 @@ export class NotificationListService extends Service {
this.hasMore$.next(pageInfo.hasNextPage); this.hasMore$.next(pageInfo.hasNextPage);
this.nextCursor$.next(pageInfo.endCursor ?? undefined); this.nextCursor$.next(pageInfo.endCursor ?? undefined);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -9,7 +9,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, map, mergeMap, switchMap } from 'rxjs'; import { map, switchMap, tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { WorkspaceMembersStore } from '../stores/members'; import type { WorkspaceMembersStore } from '../stores/members';
@@ -45,10 +45,9 @@ export class WorkspaceMembers extends Entity {
signal signal
); );
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.memberCount$.setValue(data.memberCount); this.memberCount$.setValue(data.memberCount);
this.pageMembers$.setValue(data.members); this.pageMembers$.setValue(data.members);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -8,7 +8,7 @@ import {
onComplete, onComplete,
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { WorkspacePermissionStore } from '../stores/permission'; import type { WorkspacePermissionStore } from '../stores/permission';
@@ -51,13 +51,12 @@ export class WorkspacePermission extends Entity {
backoffRetry({ backoffRetry({
count: Infinity, count: Infinity,
}), }),
mergeMap(({ isOwner, isAdmin, isTeam }) => { tap(({ isOwner, isAdmin, isTeam }) => {
this.store.setWorkspacePermissionCache({ this.store.setWorkspacePermissionCache({
isOwner, isOwner,
isAdmin, isAdmin,
isTeam, isTeam,
}); });
return EMPTY;
}), }),
onStart(() => this.isRevalidating$.setValue(true)), onStart(() => this.isRevalidating$.setValue(true)),
onComplete(() => this.isRevalidating$.setValue(false)) onComplete(() => this.isRevalidating$.setValue(false))
@@ -9,7 +9,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { EMPTY, exhaustMap, tap } from 'rxjs';
import type { DocService } from '../../doc'; import type { DocService } from '../../doc';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
@@ -52,7 +52,7 @@ export class DocGrantedUsersService extends Service {
signal signal
); );
}).pipe( }).pipe(
mergeMap(({ edges, pageInfo, totalCount }) => { tap(({ edges, pageInfo, totalCount }) => {
this.grantedUsers$.next([ this.grantedUsers$.next([
...this.grantedUsers$.value, ...this.grantedUsers$.value,
...edges.map(edge => edge.node), ...edges.map(edge => edge.node),
@@ -61,8 +61,6 @@ export class DocGrantedUsersService extends Service {
this.grantedUserCount$.next(totalCount); this.grantedUserCount$.next(totalCount);
this.hasMore$.next(pageInfo.hasNextPage); this.hasMore$.next(pageInfo.hasNextPage);
this.nextCursor$.next(pageInfo.endCursor ?? undefined); this.nextCursor$.next(pageInfo.endCursor ?? undefined);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -8,7 +8,6 @@ import {
} from '@toeverything/infra'; } from '@toeverything/infra';
import { import {
combineLatest, combineLatest,
EMPTY,
exhaustMap, exhaustMap,
groupBy, groupBy,
map, map,
@@ -145,8 +144,7 @@ export class GuardService extends Service {
fromPromise(() => this.guardStore.getWorkspacePermissions()).pipe( fromPromise(() => this.guardStore.getWorkspacePermissions()).pipe(
backoffRetry({ backoffRetry({
count: Infinity, count: Infinity,
}), })
mergeMap(() => EMPTY)
) )
) )
); );
@@ -159,8 +157,7 @@ export class GuardService extends Service {
fromPromise(() => this.loadDocPermission(docId)).pipe( fromPromise(() => this.loadDocPermission(docId)).pipe(
backoffRetry({ backoffRetry({
count: Infinity, count: Infinity,
}), })
mergeMap(() => EMPTY)
) )
) )
) )
@@ -8,7 +8,7 @@ import {
Service, Service,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { EMPTY, exhaustMap, tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { Member } from '../entities/members'; import type { Member } from '../entities/members';
@@ -43,11 +43,9 @@ export class MemberSearchService extends Service {
signal signal
); );
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
this.result$.setValue([...this.result$.value, ...data.members]); this.result$.setValue([...this.result$.value, ...data.members]);
this.hasMore$.setValue(data.members.length === this.PAGE_SIZE); this.hasMore$.setValue(data.members.length === this.PAGE_SIZE);
return EMPTY;
}), }),
smartRetry(), smartRetry(),
catchErrorInto(this.error$), catchErrorInto(this.error$),
@@ -6,7 +6,7 @@ import {
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { truncate } from 'lodash-es'; import { truncate } from 'lodash-es';
import { EMPTY, map, mergeMap, of, switchMap, throttleTime } from 'rxjs'; import { map, of, switchMap, tap, throttleTime } from 'rxjs';
import type { DocRecord, DocsService } from '../../doc'; import type { DocRecord, DocsService } from '../../doc';
import type { DocDisplayMetaService } from '../../doc-display-meta'; import type { DocDisplayMetaService } from '../../doc-display-meta';
@@ -97,10 +97,9 @@ export class DocsQuickSearchSession
); );
} }
return out.pipe( return out.pipe(
mergeMap((items: QuickSearchItem<'docs', DocsPayload>[]) => { tap((items: QuickSearchItem<'docs', DocsPayload>[]) => {
this.items$.next(items); this.items$.next(items);
this.isQueryLoading$.next(false); this.isQueryLoading$.next(false);
return EMPTY;
}), }),
onStart(() => { onStart(() => {
this.items$.next([]); this.items$.next([]);
@@ -13,7 +13,7 @@ import {
} from '@toeverything/infra'; } from '@toeverything/infra';
import { cssVarV2 } from '@toeverything/theme/v2'; import { cssVarV2 } from '@toeverything/theme/v2';
import bytes from 'bytes'; import bytes from 'bytes';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { WorkspaceQuotaStore } from '../stores/quota'; import type { WorkspaceQuotaStore } from '../stores/quota';
@@ -76,7 +76,7 @@ export class WorkspaceQuota extends Entity {
return { quota: data, used: data.usedStorageQuota }; return { quota: data, used: data.usedStorageQuota };
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(data => { tap(data => {
if (data) { if (data) {
const { quota, used } = data; const { quota, used } = data;
this.quota$.next(quota); this.quota$.next(quota);
@@ -85,7 +85,6 @@ export class WorkspaceQuota extends Entity {
this.quota$.next(null); this.quota$.next(null);
this.used$.next(null); this.used$.next(null);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$, error => { catchErrorInto(this.error$, error => {
logger.error('Failed to fetch workspace quota', error); logger.error('Failed to fetch workspace quota', error);
@@ -11,7 +11,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, mergeMap } from 'rxjs'; import { tap } from 'rxjs';
import type { GlobalCache } from '../../storage'; import type { GlobalCache } from '../../storage';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
@@ -43,9 +43,8 @@ export class ShareDocsList extends Entity {
); );
}).pipe( }).pipe(
smartRetry(), smartRetry(),
mergeMap(list => { tap(list => {
this.cache.set('share-docs', list); this.cache.set('share-docs', list);
return EMPTY;
}), }),
catchErrorInto(this.error$, err => catchErrorInto(this.error$, err =>
logger.error('revalidate share docs error', err) logger.error('revalidate share docs error', err)
@@ -10,7 +10,7 @@ import {
onStart, onStart,
smartRetry, smartRetry,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { exhaustMap, tap } from 'rxjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { WorkspaceShareSettingStore } from '../stores/share-setting'; import type { WorkspaceShareSettingStore } from '../stores/share-setting';
@@ -45,13 +45,12 @@ export class WorkspaceShareSetting extends Entity {
) )
).pipe( ).pipe(
smartRetry(), smartRetry(),
mergeMap(value => { tap(value => {
if (value) { if (value) {
this.enableAi$.next(value.enableAi); this.enableAi$.next(value.enableAi);
this.enableUrlPreview$.next(value.enableUrlPreview); this.enableUrlPreview$.next(value.enableUrlPreview);
this.inviteLink$.next(value.inviteLink); this.inviteLink$.next(value.inviteLink);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$, error => { catchErrorInto(this.error$, error => {
logger.error('Failed to fetch enableUrlPreview', error); logger.error('Failed to fetch enableUrlPreview', error);
@@ -45,7 +45,7 @@ import {
Service, Service,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { EMPTY, map, mergeMap, Observable, switchMap } from 'rxjs'; import { map, Observable, switchMap, tap } from 'rxjs';
import { type Doc as YDoc, encodeStateAsUpdate } from 'yjs'; import { type Doc as YDoc, encodeStateAsUpdate } from 'yjs';
import type { Server, ServersService } from '../../cloud'; import type { Server, ServersService } from '../../cloud';
@@ -254,7 +254,7 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
})), })),
}; };
}).pipe( }).pipe(
mergeMap(data => { tap(data => {
if (data) { if (data) {
const { accountId, workspaces } = data; const { accountId, workspaces } = data;
const sorted = workspaces.sort((a, b) => { const sorted = workspaces.sort((a, b) => {
@@ -270,7 +270,6 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
} else { } else {
this.workspaces$.next([]); this.workspaces$.next([]);
} }
return EMPTY;
}), }),
catchErrorInto(this.error$, err => { catchErrorInto(this.error$, err => {
logger.error('error to revalidate cloud workspaces', err); logger.error('error to revalidate cloud workspaces', err);
@@ -8,7 +8,7 @@ import {
onStart, onStart,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { catchError, EMPTY, exhaustMap, mergeMap } from 'rxjs'; import { catchError, EMPTY, exhaustMap, tap } from 'rxjs';
import type { WorkspaceMetadata } from '../metadata'; import type { WorkspaceMetadata } from '../metadata';
import type { WorkspaceFlavourProvider } from '../providers/flavour'; import type { WorkspaceFlavourProvider } from '../providers/flavour';
@@ -76,11 +76,10 @@ export class WorkspaceProfile extends Entity<{ metadata: WorkspaceMetadata }> {
return fromPromise(signal => return fromPromise(signal =>
provider.getWorkspaceProfile(this.props.metadata.id, signal) provider.getWorkspaceProfile(this.props.metadata.id, signal)
).pipe( ).pipe(
mergeMap(info => { tap(info => {
if (info) { if (info) {
this.setProfile({ ...this.profile$.value, ...info }); this.setProfile({ ...this.profile$.value, ...info });
} }
return EMPTY;
}), }),
catchError(err => { catchError(err => {
logger.error(err); logger.error(err);