package server import ( "sync" "sync/atomic" "time" "github.com/gin-gonic/gin" "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/pkg/clean" ) var ( extInit sync.Once extMutex sync.Mutex extensions atomic.Value ) // Register registers a new package extension. func Register(name string, init func(router *gin.Engine, conf *config.Config) error) { extMutex.Lock() h, _ := extensions.Load().(Extensions) extensions.Store(append(h, Extension{name: name, init: init})) extMutex.Unlock() } // Ext returns all registered package extensions. func Ext() (ext Extensions) { extMutex.Lock() ext, _ = extensions.Load().(Extensions) extMutex.Unlock() return ext } // Extension represents a named package extension with callbacks. type Extension struct { name string init func(router *gin.Engine, conf *config.Config) error } // Extensions represents a list of package extensions. type Extensions []Extension // Init initializes the registered extensions. func (ext Extensions) Init(router *gin.Engine, conf *config.Config) { extInit.Do(func() { for _, e := range ext { start := time.Now() if err := e.init(router, conf); err != nil { log.Warnf("server: %s in %s extension [%s]", err, clean.Log(e.name), time.Since(start)) } else { log.Infof("server: %s extension loaded [%s]", clean.Log(e.name), time.Since(start)) } } }) }