track federation-related promises to avoid data loss during restart
This commit is contained in:
parent
a4440e43a6
commit
c9f2554b2f
7 changed files with 29 additions and 24 deletions
|
|
@ -18,6 +18,7 @@ import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerServ
|
|||
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
import type { DataSource } from 'typeorm';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -84,7 +85,7 @@ export class NotePiningService {
|
|||
|
||||
// Deliver to remote followers
|
||||
if (this.userEntityService.isLocalUser(user) && !note.localOnly && ['public', 'home'].includes(note.visibility)) {
|
||||
await this.deliverPinnedChange(user, note.id, true);
|
||||
trackPromise(this.deliverPinnedChange(user, note.id, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +113,7 @@ export class NotePiningService {
|
|||
|
||||
// Deliver to remote followers
|
||||
if (this.userEntityService.isLocalUser(user) && !note.localOnly && ['public', 'home'].includes(note.visibility)) {
|
||||
await this.deliverPinnedChange(user, noteId, false);
|
||||
trackPromise(this.deliverPinnedChange(user, noteId, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import type { ThinUser } from '@/queue/types.js';
|
|||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import { InternalEventService } from '@/global/InternalEventService.js';
|
||||
import type Logger from '../logger.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
|
||||
type Local = MiLocalUser | {
|
||||
id: MiLocalUser['id'];
|
||||
|
|
@ -102,7 +103,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
@bindThis
|
||||
public async deliverAccept(follower: MiRemoteUser, followee: MiPartialLocalUser, requestId?: string) {
|
||||
const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
|
||||
this.queueService.deliver(followee, content, follower.inbox, false);
|
||||
await this.queueService.deliver(followee, content, follower.inbox, false);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
@ -152,7 +153,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
// すでにフォロー関係が存在している場合
|
||||
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
|
||||
// リモート → ローカル: acceptを送り返しておしまい
|
||||
this.deliverAccept(follower, followee, requestId);
|
||||
trackPromise(this.deliverAccept(follower, followee, requestId));
|
||||
return;
|
||||
}
|
||||
if (this.userEntityService.isLocalUser(follower)) {
|
||||
|
|
@ -206,7 +207,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
await this.insertFollowingDoc(followee, follower, silent, withReplies);
|
||||
|
||||
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
|
||||
this.deliverAccept(follower, followee, requestId);
|
||||
trackPromise(this.deliverAccept(follower, followee, requestId));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -581,7 +582,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
await this.insertFollowingDoc(followee, follower, false, request.withReplies);
|
||||
|
||||
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
|
||||
this.deliverAccept(follower, followee as MiPartialLocalUser, request.requestId ?? undefined);
|
||||
trackPromise(this.deliverAccept(follower, followee as MiPartialLocalUser, request.requestId ?? undefined));
|
||||
}
|
||||
|
||||
this.userEntityService.pack(followee.id, followee, {
|
||||
|
|
@ -595,14 +596,13 @@ export class UserFollowingService implements OnModuleInit {
|
|||
id: MiUser['id']; host: MiUser['host']; uri: MiUser['host']; inbox: MiUser['inbox']; sharedInbox: MiUser['sharedInbox'];
|
||||
},
|
||||
): Promise<void> {
|
||||
const requests = await this.followRequestsRepository.findBy({
|
||||
const requests = await this.followRequestsRepository.find({ where: {
|
||||
followeeId: user.id,
|
||||
});
|
||||
}, relations: {
|
||||
follower: true,
|
||||
} });
|
||||
|
||||
for (const request of requests) {
|
||||
const follower = await this.usersRepository.findOneByOrFail({ id: request.followerId });
|
||||
this.acceptFollowRequest(user, follower);
|
||||
}
|
||||
await Promise.all(requests.map(request => this.acceptFollowRequest(user, request.follower as MiUser)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -611,7 +611,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
@bindThis
|
||||
public async rejectFollowRequest(user: Local, follower: Both): Promise<void> {
|
||||
if (this.userEntityService.isRemoteUser(follower)) {
|
||||
this.deliverReject(user, follower);
|
||||
trackPromise(this.deliverReject(user, follower));
|
||||
}
|
||||
|
||||
await this.removeFollowRequest(user, follower);
|
||||
|
|
@ -627,7 +627,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
@bindThis
|
||||
public async rejectFollow(user: Local, follower: Both): Promise<void> {
|
||||
if (this.userEntityService.isRemoteUser(follower)) {
|
||||
this.deliverReject(user, follower);
|
||||
trackPromise(this.deliverReject(user, follower));
|
||||
}
|
||||
|
||||
await this.removeFollow(user, follower);
|
||||
|
|
@ -696,7 +696,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
});
|
||||
|
||||
const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee));
|
||||
this.queueService.deliver(followee, content, follower.inbox, false);
|
||||
await this.queueService.deliver(followee, content, follower.inbox, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -720,7 +720,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
|
||||
@bindThis
|
||||
public async isFollowing(followerId: MiUser['id'], followeeId: MiUser['id']) {
|
||||
return this.cacheService.isFollowing(followerId, followeeId);
|
||||
return await this.cacheService.isFollowing(followerId, followeeId);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import { IdentifiableError } from '@/misc/identifiable-error.js';
|
|||
import { toArray } from '@/misc/prelude/array.js';
|
||||
import { isPureRenote } from '@/misc/is-renote.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
import { AnyCollection, getApId, getNullableApId, IObjectWithId, isCollection, isCollectionOrOrderedCollection, isCollectionPage, isOrderedCollection, isOrderedCollectionPage } from './type.js';
|
||||
import { ApDbResolverService } from './ApDbResolverService.js';
|
||||
import { ApRendererService } from './ApRendererService.js';
|
||||
|
|
@ -269,8 +270,8 @@ export class Resolver {
|
|||
log.duration = calculateDurationSince(startTime);
|
||||
|
||||
// Save or finalize asynchronously
|
||||
this.apLogService.saveFetchLog(log)
|
||||
.catch(err => this.logger.error('Failed to record AP object fetch:', err));
|
||||
trackPromise(this.apLogService.saveFetchLog(log)
|
||||
.catch(err => this.logger.error('Failed to record AP object fetch:', err)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ export class ApNoteService implements OnModuleInit {
|
|||
|
||||
return x;
|
||||
})
|
||||
.catch(async err => {
|
||||
.catch(err => {
|
||||
this.logger.warn(`error ${renderInlineError(err)} fetching inReplyTo ${note.inReplyTo} for note ${entryUri}`);
|
||||
throw new IdentifiableError('1ebf0a96-2769-4973-a6c2-3dcbad409dff', `failed to create note ${entryUri}: could not fetch inReplyTo ${note.inReplyTo}`, true, err);
|
||||
})
|
||||
|
|
@ -456,7 +456,7 @@ export class ApNoteService implements OnModuleInit {
|
|||
|
||||
return x;
|
||||
})
|
||||
.catch(async err => {
|
||||
.catch(err => {
|
||||
this.logger.warn(`error ${renderInlineError(err)} fetching inReplyTo ${note.inReplyTo} for note ${entryUri}`);
|
||||
throw new IdentifiableError('1ebf0a96-2769-4973-a6c2-3dcbad409dff', `failed to update note ${entryUri}: could not fetch inReplyTo ${note.inReplyTo}`, true, err);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import { TimeService } from '@/global/TimeService.js';
|
|||
import { isRetryableError } from '@/misc/is-retryable-error.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||
import type { InboxJobData } from '../types.js';
|
||||
|
||||
|
|
@ -103,8 +104,8 @@ export class InboxProcessorService implements OnApplicationShutdown {
|
|||
log.duration = calculateDurationSince(startTime);
|
||||
|
||||
// Save or finalize asynchronously
|
||||
this.apLogService.saveInboxLog(log)
|
||||
.catch(err => this.logger.error('Failed to record AP activity:', err));
|
||||
trackPromise(this.apLogService.saveInboxLog(log)
|
||||
.catch(err => this.logger.error('Failed to record AP activity:', err)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import { trackPromise } from '@/misc/promise-tracker.js';
|
|||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { ApiLoggerService } from '../../ApiLoggerService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['account'],
|
||||
|
|
@ -643,7 +644,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
// 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認
|
||||
if (user.isLocked && ps.isLocked === false) {
|
||||
await this.userFollowingService.acceptAllFollowRequests(user);
|
||||
trackPromise(this.userFollowingService.acceptAllFollowRequests(user));
|
||||
}
|
||||
|
||||
// フォロワーにUpdateを配信
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { UserBlockingService } from '@/core/UserBlockingService.js';
|
||||
import { TimeService } from '@/global/TimeService.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
import { ApiError } from '../../../error.js';
|
||||
|
||||
export const meta = {
|
||||
|
|
@ -176,7 +177,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
}
|
||||
|
||||
// リモートフォロワーにUpdate配信
|
||||
await this.pollService.deliverQuestionUpdate(note);
|
||||
trackPromise(this.pollService.deliverQuestionUpdate(note));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue