0.2.64 update

This commit is contained in:
ponzischeme89
2026-08-15 09:23:26 +12:00
parent a2ca7e8061
commit d5d47473a2
90 changed files with 9188 additions and 451 deletions
+51 -2
View File
@@ -22,6 +22,7 @@ import (
"github.com/ponzischeme89/memby/server/internal/buildinfo"
"github.com/ponzischeme89/memby/server/internal/cache"
"github.com/ponzischeme89/memby/server/internal/config"
"github.com/ponzischeme89/memby/server/internal/credits"
"github.com/ponzischeme89/memby/server/internal/emby"
"github.com/ponzischeme89/memby/server/internal/foryou"
"github.com/ponzischeme89/memby/server/internal/integrations"
@@ -175,6 +176,53 @@ func run(log *slog.Logger, events *logging.Buffer) error {
})
}
// Credits discovery. Deliberately built here rather than inside the API server, because
// it owns a long-running worker and a queue whose lifetime is the process's — the server
// only reads its markers and feeds it the two live signals it already receives.
creditsLoad := credits.NewPlaybackLoad()
var creditsService *credits.Service
if cfg.CreditsEnabled {
sampler := &credits.Sampler{Binary: cfg.CreditsFFmpeg}
var detector credits.Detector
if sampler.Available() {
detector = &credits.VisualDetector{Sampler: sampler}
} else {
// No decoder in the image is a deliberate deployment, not a fault. The subsystem
// still runs and still writes markers, on the household's own stop positions —
// which cost no media access at all and, on a well-watched show, agree more
// closely than any single reading of the picture.
log.Warn("credits: ffmpeg not found; running on behavioural evidence only")
}
database := credits.Postgres{Store: st}
creditsConfig := credits.Config{
PrefetchEpisodes: cfg.CreditsPrefetchEpisodes,
MaxPrefetchEpisodes: cfg.CreditsMaxPrefetch,
QueueLimit: cfg.CreditsQueueLimit,
StrongWindow: credits.DefaultConfig().StrongWindow,
UsefulWindow: credits.DefaultConfig().UsefulWindow,
WeakWindow: credits.DefaultConfig().WeakWindow,
}
creditsService = credits.New(credits.Deps{
Repository: database,
Resolver: credits.NewEmbyResolver(embyClient, emby.Credentials{
UserID: cfg.SyncUserID, Token: cfg.SyncAPIKey,
DeviceID: "memby-credits", DeviceName: "MbyGateway Credits",
Gateway: true,
}),
Source: &credits.TracearrSource{DB: database, Cfg: creditsConfig},
Detector: detector,
Behaviour: database,
Load: creditsLoad,
Log: log,
Config: creditsConfig,
})
go creditsService.Run(ctx)
log.Info("credits detection enabled",
"prefetch", creditsConfig.PrefetchEpisodes,
"queue_limit", creditsConfig.QueueLimit,
"visual", detector != nil)
}
// The administrative event bus, the integration dispatcher that subscribes to it and
// the scheduler that publishes into it are built before the server, because the server
// takes all three: a handler that could not publish would have to check for nil at
@@ -195,6 +243,8 @@ func run(log *slog.Logger, events *logging.Buffer) error {
Radarr: radarrClient,
Bazarr: bazarrClient,
MDBList: mdblistClient,
Credits: creditsService,
CreditsLoad: creditsLoad,
Syncer: syncer,
Log: log,
Events: events,
@@ -207,6 +257,7 @@ func run(log *slog.Logger, events *logging.Buffer) error {
// Registration is separate from construction so the task list reads as a declaration
// of what the gateway does in the background rather than as more wiring in here.
server.RegisterHousekeeping(sched)
server.RegisterCreditsTasks(sched)
sched.Start(ctx)
// Installed after the server exists, because both halves of a finished import are
@@ -348,5 +399,3 @@ func openStore(ctx context.Context, databaseURL string, log *slog.Logger) (*stor
}
return nil, lastErr
}