mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
feat(artwork): promote worker concurrency and external rate to real configs
The artwork worker's drain speed was governed by two hidden Dev flags, DevArtworkWorkerConcurrency and DevArtworkExternalRPS, both defaulting to 2. On a large library's one-time backfill the external rate limiter is the real ceiling: every art-less item waits on it before the (rate-limited) external lookup, so the drain crawls at ~RPS items/sec while local-art items are unaffected. Promote both to documented, supported options: ArtworkWorkerConcurrency (default 4) sets local-resolution parallelism, ArtworkExternalMaxRPS (default 2, 0 = unlimited) caps external-agent lookups to stay polite to Last.fm/Deezer/etc. Operators can now trade first-backfill speed against external-API rate limits. The old Dev names still map for backward compat.
This commit is contained in:
parent
9ce51cf575
commit
fc55e8bf16
@ -57,6 +57,8 @@ type configOptions struct {
|
||||
ImageCacheSize string
|
||||
AlbumPlayCountMode string
|
||||
EnableArtworkPrecache bool
|
||||
ArtworkWorkerConcurrency int
|
||||
ArtworkExternalMaxRPS int
|
||||
AutoImportPlaylists bool
|
||||
DefaultPlaylistPublicVisibility bool
|
||||
PlaylistsPath string
|
||||
@ -139,8 +141,6 @@ type configOptions struct {
|
||||
DevArtworkThrottleBacklogLimit int
|
||||
DevArtworkThrottleBacklogTimeout time.Duration
|
||||
DevArtworkThrottleBuffered bool
|
||||
DevArtworkWorkerConcurrency int
|
||||
DevArtworkExternalRPS int
|
||||
DevArtistInfoTimeToLive time.Duration
|
||||
DevAlbumInfoTimeToLive time.Duration
|
||||
DevExternalScanner bool
|
||||
@ -348,6 +348,8 @@ func Load(noConfigDump bool) {
|
||||
mapDeprecatedOption("CoverJpegQuality", "CoverArtQuality")
|
||||
mapDeprecatedOption("SimilarSongsMatchThreshold", "Matcher.FuzzyThreshold")
|
||||
mapDeprecatedOption("EnableTranscodingCancellation", "Transcoding.EnableCancellation")
|
||||
mapDeprecatedOption("DevArtworkWorkerConcurrency", "ArtworkWorkerConcurrency")
|
||||
mapDeprecatedOption("DevArtworkExternalRPS", "ArtworkExternalMaxRPS")
|
||||
|
||||
err := viper.Unmarshal(&Server, viper.DecodeHook(
|
||||
mapstructure.ComposeDecodeHookFunc(
|
||||
@ -902,8 +904,8 @@ func setViperDefaults() {
|
||||
viper.SetDefault("devartworkthrottlebackloglimit", consts.RequestThrottleBacklogLimit)
|
||||
viper.SetDefault("devartworkthrottlebacklogtimeout", consts.RequestThrottleBacklogTimeout)
|
||||
viper.SetDefault("devartworkthrottlebuffered", true)
|
||||
viper.SetDefault("devartworkworkerconcurrency", 2)
|
||||
viper.SetDefault("devartworkexternalrps", 2)
|
||||
viper.SetDefault("artworkworkerconcurrency", 4)
|
||||
viper.SetDefault("artworkexternalmaxrps", 2)
|
||||
viper.SetDefault("devartistinfotimetolive", consts.ArtistInfoTimeToLive)
|
||||
viper.SetDefault("devalbuminfotimetolive", consts.AlbumInfoTimeToLive)
|
||||
viper.SetDefault("devexternalscanner", true)
|
||||
|
||||
@ -43,8 +43,8 @@ type Worker struct {
|
||||
}
|
||||
|
||||
func NewWorker(ds model.DataStore, store *ImageStore, prov external.Provider, ffmpeg ffmpeg.FFmpeg) *Worker {
|
||||
rps := conf.Server.DevArtworkExternalRPS
|
||||
limit := rate.Inf
|
||||
rps := conf.Server.ArtworkExternalMaxRPS
|
||||
limit := rate.Inf // 0 or negative disables the external throttle
|
||||
if rps > 0 {
|
||||
limit = rate.Limit(rps)
|
||||
}
|
||||
@ -64,7 +64,7 @@ func NewWorker(ds model.DataStore, store *ImageStore, prov external.Provider, ff
|
||||
// leaked goroutines: each drain waits for its batch before the loop can return.
|
||||
func (w *Worker) Run(ctx context.Context) error {
|
||||
w.runCtx = ctx
|
||||
concurrency := max(1, conf.Server.DevArtworkWorkerConcurrency)
|
||||
concurrency := max(1, conf.Server.ArtworkWorkerConcurrency)
|
||||
ticker := time.NewTicker(workerPollInterval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
|
||||
@ -85,7 +85,7 @@ var _ = Describe("Worker", func() {
|
||||
ds.MockedAlbum = tests.CreateMockAlbumRepo()
|
||||
store = NewImageStore(GinkgoT().TempDir())
|
||||
conf.Server.CoverArtPriority = "cover.jpg, embedded"
|
||||
conf.Server.DevArtworkExternalRPS = 1000 // keep the limiter out of the way of behavior tests
|
||||
conf.Server.ArtworkExternalMaxRPS = 1000 // keep the limiter out of the way of behavior tests
|
||||
w = NewWorker(ds, store, prov, ffm)
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user