make sure validation errors in background update-featured are returned to the job queue
This commit is contained in:
parent
3c64fbc9a5
commit
e81c8b075b
5 changed files with 62 additions and 17 deletions
|
|
@ -44,7 +44,7 @@ import { TimeService } from '@/global/TimeService.js';
|
|||
import { verifyFieldLinks } from '@/misc/verify-field-link.js';
|
||||
import { isRetryableError } from '@/misc/is-retryable-error.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { errorCodes, IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { InternalEventService } from '@/core/InternalEventService.js';
|
||||
import { CollapsedQueueService } from '@/core/CollapsedQueueService.js';
|
||||
|
|
@ -919,16 +919,30 @@ export class ApPersonService implements OnModuleInit {
|
|||
*/
|
||||
@bindThis
|
||||
public async updateFeaturedLazy(userOrId: MiRemoteUser | MiUser['id']): Promise<void> {
|
||||
const user = await this.resolveUserForFeatured(userOrId);
|
||||
if (!user) return;
|
||||
const userId = typeof(userOrId) === 'object' ? userOrId.id : userOrId;
|
||||
const user = typeof(userOrId) === 'object' ? userOrId : await this.cacheService.findRemoteUserById(userId);
|
||||
|
||||
await this.queueService.createUpdateFeaturedJob(user.id);
|
||||
if (user.isDeleted || user.isSuspended) {
|
||||
this.logger.debug(`Not updating featured for ${userId}: user is deleted`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user.featured) {
|
||||
this.logger.debug(`Not updating featured for ${userId}: no featured collection`);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.queueService.createUpdateFeaturedJob(userId);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async updateFeatured(userOrId: MiRemoteUser | MiUser['id'], resolver?: Resolver): Promise<void> {
|
||||
const user = await this.resolveUserForFeatured(userOrId);
|
||||
if (!user) return;
|
||||
const userId = typeof(userOrId) === 'object' ? userOrId.id : userOrId;
|
||||
const user = typeof(userOrId) === 'object' ? userOrId : await this.cacheService.findRemoteUserById(userId);
|
||||
|
||||
if (user.isDeleted) throw new IdentifiableError(errorCodes.userIsDeleted, `Can't update featured for ${userId}: user is deleted`);
|
||||
if (user.isSuspended) throw new IdentifiableError(errorCodes.userIsSuspended, `Can't update featured for ${userId}: user is suspended`);
|
||||
if (!user.featured) throw new IdentifiableError(errorCodes.noFeaturedCollection, `Can't update featured for ${userId}: no featured collection`);
|
||||
|
||||
this.logger.info(`Updating featured notes for: ${user.uri}`);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,15 @@ export class IdentifiableError extends Error {
|
|||
this.isRetryable = isRetryable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard error codes to reference throughout the app
|
||||
*/
|
||||
export const errorCodes = {
|
||||
// User has been deleted (hard or soft deleted)
|
||||
userIsDeleted: '4cac9436-baa3-4955-a368-7628aea676cf',
|
||||
// User is suspended (directly or by instance)
|
||||
userIsSuspended: '1e56d624-737f-48e4-beb6-0bdddb9fa809',
|
||||
// User has no valid featured collection (not defined, invalid, etc)
|
||||
noFeaturedCollection: '2aa4766e-b7d8-4291-a671-56800498b085',
|
||||
} as const;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import { trackTask } from '@/misc/promise-tracker.js';
|
|||
import { UserSuspendService } from '@/core/UserSuspendService.js';
|
||||
import { ApLogService } from '@/core/ApLogService.js';
|
||||
import { CollapsedQueueService } from '@/core/CollapsedQueueService.js';
|
||||
import { isRemoteUser } from '@/models/User.js';
|
||||
import { errorCodes, IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
|
||||
@Injectable()
|
||||
export class BackgroundTaskProcessorService {
|
||||
|
|
@ -110,7 +112,7 @@ export class BackgroundTaskProcessorService {
|
|||
const user = await this.cacheService.findOptionalUserById(task.userId);
|
||||
if (!user || user.isDeleted) return `Skipping update-user task: user ${task.userId} has been deleted`;
|
||||
if (user.isSuspended) return `Skipping update-user task: user ${task.userId} is suspended`;
|
||||
if (!user.uri) return `Skipping update-user task: user ${task.userId} is local`;
|
||||
if (!isRemoteUser(user)) return `Skipping update-user task: user ${task.userId} is local`;
|
||||
|
||||
if (user.lastFetchedAt && Date.now() - user.lastFetchedAt.getTime() < 1000 * 60 * 60 * 24) {
|
||||
return `Skipping update-user task: user ${task.userId} was recently updated`;
|
||||
|
|
@ -124,14 +126,23 @@ export class BackgroundTaskProcessorService {
|
|||
const user = await this.cacheService.findOptionalUserById(task.userId);
|
||||
if (!user || user.isDeleted) return `Skipping update-featured task: user ${task.userId} has been deleted`;
|
||||
if (user.isSuspended) return `Skipping update-featured task: user ${task.userId} is suspended`;
|
||||
if (!user.uri) return `Skipping update-featured task: user ${task.userId} is local`;
|
||||
if (!isRemoteUser(user)) return `Skipping update-featured task: user ${task.userId} is local`;
|
||||
if (!user.featured) return `Skipping update-featured task: user ${task.userId} has no featured collection`;
|
||||
|
||||
if (user.lastFetchedAt && Date.now() - user.lastFetchedAt.getTime() < 1000 * 60 * 60 * 24) {
|
||||
return `Skipping update-featured task: user ${task.userId} was recently updated`;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.apPersonService.updateFeatured(user);
|
||||
} catch (err) {
|
||||
if (err instanceof IdentifiableError) {
|
||||
if (err.id === errorCodes.userIsSuspended) return err.message;
|
||||
if (err.id === errorCodes.userIsDeleted) return err.message;
|
||||
if (err.id === errorCodes.noFeaturedCollection) return err.message;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +150,7 @@ export class BackgroundTaskProcessorService {
|
|||
const user = await this.cacheService.findOptionalUserById(task.userId);
|
||||
if (!user || user.isDeleted) return `Skipping update-user-tags task: user ${task.userId} has been deleted`;
|
||||
if (user.isSuspended) return `Skipping update-user-tags task: user ${task.userId} is suspended`;
|
||||
if (!user.uri) return `Skipping update-user-tags task: user ${task.userId} is local`;
|
||||
if (!isRemoteUser(user)) return `Skipping update-user-tags task: user ${task.userId} is local`;
|
||||
|
||||
await this.hashtagService.updateUsertags(user, user.tags);
|
||||
return 'ok';
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
private readonly cacheService: CacheService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps) => {
|
||||
const user = await this.cacheService.findRemoteUserById(ps.userId);
|
||||
const user = await this.cacheService.findRemoteUserById(ps.userId).catch(() => null);
|
||||
|
||||
if (!user) {
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
|
|
|
|||
|
|
@ -3,25 +3,33 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import type { MiRemoteUser } from '@/models/User.js';
|
||||
import type { MiInstance } from '@/models/Instance.js';
|
||||
import type { Resolver } from '@/core/activitypub/ApResolverService.js';
|
||||
import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
|
||||
import { MiUser } from '@/models/User.js';
|
||||
import { FetchInstanceMetadataService } from '@/core/FetchInstanceMetadataService.js';
|
||||
import { MiInstance } from '@/models/Instance.js';
|
||||
import { Resolver } from '@/core/activitypub/ApResolverService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { errorCodes, IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
|
||||
export class ImmediateApPersonService extends ApPersonService {
|
||||
public resolver?: Resolver;
|
||||
|
||||
@bindThis
|
||||
async updatePersonLazy(uriOrUser: string | MiUser): Promise<void> {
|
||||
async updatePersonLazy(uriOrUser: string | MiRemoteUser): Promise<void> {
|
||||
const userId = typeof(uriOrUser) === 'object' ? uriOrUser.id : uriOrUser;
|
||||
await this.updatePerson(userId, this.resolver);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
async updateFeaturedLazy(userOrId: string | MiUser): Promise<void> {
|
||||
await this.updateFeatured(userOrId, this.resolver);
|
||||
async updateFeaturedLazy(userOrId: string | MiRemoteUser): Promise<void> {
|
||||
await this.updateFeatured(userOrId, this.resolver).catch(err => {
|
||||
if (err instanceof IdentifiableError) {
|
||||
if (err.id === errorCodes.userIsSuspended) return;
|
||||
if (err.id === errorCodes.userIsDeleted) return;
|
||||
if (err.id === errorCodes.noFeaturedCollection) return;
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue