Cache refresh actor promise

This commit is contained in:
Chocobozzz 2021-06-09 13:34:40 +02:00
parent a6a12dae10
commit 4ead40e776
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
6 changed files with 49 additions and 15 deletions

View File

@ -138,10 +138,10 @@ export class CustomMarkupService {
const component = this.dynamicElementService.createElement(ButtonMarkupComponent) const component = this.dynamicElementService.createElement(ButtonMarkupComponent)
const model = { const model = {
theme: data.theme, theme: data.theme ?? 'primary',
href: data.href, href: data.href,
label: data.label, label: data.label,
blankTarget: this.buildBoolean(data.blankTarget) blankTarget: this.buildBoolean(data.blankTarget) ?? false
} }
this.dynamicElementService.setModel(component, model) this.dynamicElementService.setModel(component, model)

View File

@ -0,0 +1,21 @@
export class PromiseCache <A, R> {
private readonly running = new Map<string, Promise<R>>()
constructor (
private readonly fn: (arg: A) => Promise<R>,
private readonly keyBuilder: (arg: A) => string
) {
}
run (arg: A) {
const key = this.keyBuilder(arg)
if (this.running.has(key)) return this.running.get(key)
const p = this.fn(arg)
this.running.set(key, p)
return p.finally(() => this.running.delete(key))
}
}

View File

@ -56,7 +56,7 @@ async function getOrCreateAPActor (
if (actor.Account) (actor as MActorAccountChannelIdActor).Account.Actor = actor if (actor.Account) (actor as MActorAccountChannelIdActor).Account.Actor = actor
if (actor.VideoChannel) (actor as MActorAccountChannelIdActor).VideoChannel.Actor = actor if (actor.VideoChannel) (actor as MActorAccountChannelIdActor).VideoChannel.Actor = actor
const { actor: actorRefreshed, refreshed } = await refreshActorIfNeeded(actor, fetchType) const { actor: actorRefreshed, refreshed } = await refreshActorIfNeeded({ actor, fetchedType: fetchType })
if (!actorRefreshed) throw new Error('Actor ' + actor.url + ' does not exist anymore.') if (!actorRefreshed) throw new Error('Actor ' + actor.url + ' does not exist anymore.')
await scheduleOutboxFetchIfNeeded(actor, created, refreshed, updateCollections) await scheduleOutboxFetchIfNeeded(actor, created, refreshed, updateCollections)

View File

@ -1,4 +1,5 @@
import { logger, loggerTagsFactory } from '@server/helpers/logger' import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { PromiseCache } from '@server/helpers/promise-cache'
import { PeerTubeRequestError } from '@server/helpers/requests' import { PeerTubeRequestError } from '@server/helpers/requests'
import { ActorLoadByUrlType } from '@server/lib/model-loaders' import { ActorLoadByUrlType } from '@server/lib/model-loaders'
import { ActorModel } from '@server/models/actor/actor' import { ActorModel } from '@server/models/actor/actor'
@ -8,11 +9,30 @@ import { fetchRemoteActor } from './shared'
import { APActorUpdater } from './updater' import { APActorUpdater } from './updater'
import { getUrlFromWebfinger } from './webfinger' import { getUrlFromWebfinger } from './webfinger'
async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannelId> ( type RefreshResult <T> = Promise<{ actor: T | MActorFull, refreshed: boolean }>
actorArg: T,
type RefreshOptions <T> = {
actor: T
fetchedType: ActorLoadByUrlType fetchedType: ActorLoadByUrlType
): Promise<{ actor: T | MActorFull, refreshed: boolean }> { }
if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false }
const promiseCache = new PromiseCache(doRefresh, (options: RefreshOptions<MActorFull | MActorAccountChannelId>) => options.actor.url)
function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannelId> (options: RefreshOptions<T>): RefreshResult <T> {
const actorArg = options.actor
if (!actorArg.isOutdated()) return Promise.resolve({ actor: actorArg, refreshed: false })
return promiseCache.run(options)
}
export {
refreshActorIfNeeded
}
// ---------------------------------------------------------------------------
async function doRefresh <T extends MActorFull | MActorAccountChannelId> (options: RefreshOptions<T>): RefreshResult <MActorFull> {
const { actor: actorArg, fetchedType } = options
// We need more attributes // We need more attributes
const actor = fetchedType === 'all' const actor = fetchedType === 'all'
@ -52,12 +72,6 @@ async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannel
} }
} }
export {
refreshActorIfNeeded
}
// ---------------------------------------------------------------------------
function getActorUrl (actor: MActorFull) { function getActorUrl (actor: MActorFull) {
return getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost()) return getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost())
.catch(err => { .catch(err => {

View File

@ -47,7 +47,7 @@ async function refreshActor (actorUrl: string) {
const actor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorUrl) const actor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorUrl)
if (actor) { if (actor) {
await refreshActorIfNeeded(actor, fetchType) await refreshActorIfNeeded({ actor, fetchedType: fetchType })
} }
} }

View File

@ -34,7 +34,6 @@ export type VideosListMarkupData = {
languageOneOf?: string // coma separated values languageOneOf?: string // coma separated values
onlyLocal?: string // boolean onlyLocal?: string // boolean
} }
export type ButtonMarkupData = { export type ButtonMarkupData = {