Cache refresh actor promise
This commit is contained in:
parent
a6a12dae10
commit
4ead40e776
6 changed files with 49 additions and 15 deletions
|
@ -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)
|
||||||
|
|
||||||
|
|
21
server/helpers/promise-cache.ts
Normal file
21
server/helpers/promise-cache.ts
Normal 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))
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
Loading…
Reference in a new issue