Files

74 lines
2.8 KiB
Go
Raw Permalink Normal View History

package metadata
import (
"context"
"sort"
"sync"
)
// Built-in host metadata providers are registered as data: one reserved
// plugin_installations row (kind='builtin', plugin_id='silo.builtin') carries
// ordinary plugin_capabilities rows, so the chain store, seeding, defaults
// endpoint, and admin UI all work unchanged. This file is the single
// in-process registration point mapping those capability ids to provider
// constructors: buildProviders returns the registered provider instead of a
// gRPC PluginProvider when the resolved entry's installation is a builtin.
//
// Providers self-register from their package's init (e.g. internal/metadata/nfo)
// to avoid an import cycle — this package defines the Provider interfaces the
// builtin packages implement. cmd/silo blank-imports each builtin package.
// Activating a future builtin (e.g. xattr) is a registration call plus a
// capability row in a migration.
// IdentityHintProvider is the narrow contract a built-in local provider
// implements to contribute trusted identity hints (tmdb/imdb/tvdb ids parsed
// from curated sidecar files) before Phase-1 search. Hints anchor candidate
// selection through the trusted-hint machinery, unlocking remote enrichment
// by ID even when remote search-by-title returns nothing.
type IdentityHintProvider interface {
IdentityHints(ctx context.Context, query SearchQuery) map[string]string
}
var (
builtinProvidersMu sync.RWMutex
builtinProviders = map[string]func() Provider{}
)
// RegisterBuiltinProvider registers the constructor for a built-in provider
// under its plugin_capabilities capability_id. Later registrations for the
// same capability id replace earlier ones.
func RegisterBuiltinProvider(capabilityID string, construct func() Provider) {
// Registration only happens from package init(); empty id or nil constructor
// is a programmer error that would silently disable a provider, so fail loud.
if capabilityID == "" || construct == nil {
panic("metadata: RegisterBuiltinProvider requires a non-empty capabilityID and non-nil constructor")
}
builtinProvidersMu.Lock()
builtinProviders[capabilityID] = construct
builtinProvidersMu.Unlock()
}
// BuiltinCapabilityIDs returns the registered builtin capability ids, sorted.
func BuiltinCapabilityIDs() []string {
builtinProvidersMu.RLock()
ids := make([]string, 0, len(builtinProviders))
for id := range builtinProviders {
ids = append(ids, id)
}
builtinProvidersMu.RUnlock()
sort.Strings(ids)
return ids
}
// builtinProvider constructs the registered in-process provider for a builtin
// capability id.
func builtinProvider(capabilityID string) (Provider, bool) {
builtinProvidersMu.RLock()
construct, ok := builtinProviders[capabilityID]
builtinProvidersMu.RUnlock()
if !ok {
return nil, false
}
return construct(), true
}