mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 13:07:36 +03:00
Added a new layer: engine (equivalent to use cases in Clean Architecture). Should make testing things easier
This commit is contained in:
parent
56e9ad3def
commit
91c660c746
6 changed files with 91 additions and 39 deletions
|
@ -1,23 +1,23 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
"github.com/deluan/gosonic/api/responses"
|
"github.com/deluan/gosonic/api/responses"
|
||||||
"github.com/deluan/gosonic/consts"
|
|
||||||
"github.com/deluan/gosonic/domain"
|
"github.com/deluan/gosonic/domain"
|
||||||
|
"github.com/deluan/gosonic/engine"
|
||||||
"github.com/deluan/gosonic/utils"
|
"github.com/deluan/gosonic/utils"
|
||||||
"github.com/karlkfi/inject"
|
"github.com/karlkfi/inject"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetIndexesController struct {
|
type GetIndexesController struct {
|
||||||
BaseAPIController
|
BaseAPIController
|
||||||
repo domain.ArtistIndexRepository
|
|
||||||
properties domain.PropertyRepository
|
properties domain.PropertyRepository
|
||||||
|
browser engine.Browser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GetIndexesController) Prepare() {
|
func (c *GetIndexesController) Prepare() {
|
||||||
inject.ExtractAssignable(utils.Graph, &c.repo)
|
inject.ExtractAssignable(utils.Graph, &c.browser)
|
||||||
inject.ExtractAssignable(utils.Graph, &c.properties)
|
inject.ExtractAssignable(utils.Graph, &c.properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,40 +25,28 @@ func (c *GetIndexesController) Prepare() {
|
||||||
func (c *GetIndexesController) Get() {
|
func (c *GetIndexesController) Get() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
ifModifiedSince := c.Input().Get("ifModifiedSince")
|
var ifModifiedSince int64
|
||||||
if ifModifiedSince == "" {
|
c.Ctx.Input.Bind(&ifModifiedSince, "ifModifiedSince")
|
||||||
ifModifiedSince = "0"
|
|
||||||
}
|
|
||||||
|
|
||||||
res := responses.Indexes{}
|
indexes, lastModified, err := c.browser.Indexes(utils.ToTime(ifModifiedSince))
|
||||||
res.IgnoredArticles = beego.AppConfig.String("ignoredArticles")
|
|
||||||
|
|
||||||
res.LastModified, err = c.properties.DefaultGet(consts.LastScan, "-1")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("Error retrieving LastScan property:", err)
|
beego.Error("Error retrieving Indexes:", err)
|
||||||
c.SendError(responses.ERROR_GENERIC, "Internal Error")
|
c.SendError(responses.ERROR_GENERIC, "Internal Error")
|
||||||
}
|
}
|
||||||
|
|
||||||
i, _ := strconv.Atoi(ifModifiedSince)
|
res := responses.Indexes{
|
||||||
l, _ := strconv.Atoi(res.LastModified)
|
IgnoredArticles: beego.AppConfig.String("ignoredArticles"),
|
||||||
|
LastModified: fmt.Sprint(utils.ToMillis(lastModified)),
|
||||||
|
}
|
||||||
|
|
||||||
if l > i {
|
res.Index = make([]responses.Index, len(indexes))
|
||||||
indexes, err := c.repo.GetAll()
|
for i, idx := range indexes {
|
||||||
if err != nil {
|
res.Index[i].Name = idx.Id
|
||||||
beego.Error("Error retrieving Indexes:", err)
|
res.Index[i].Artists = make([]responses.Artist, len(idx.Artists))
|
||||||
c.SendError(responses.ERROR_GENERIC, "Internal Error")
|
for j, a := range idx.Artists {
|
||||||
|
res.Index[i].Artists[j].Id = a.ArtistId
|
||||||
|
res.Index[i].Artists[j].Name = a.Artist
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Index = make([]responses.Index, len(indexes))
|
|
||||||
for i, idx := range indexes {
|
|
||||||
res.Index[i].Name = idx.Id
|
|
||||||
res.Index[i].Artists = make([]responses.Artist, len(idx.Artists))
|
|
||||||
for j, a := range idx.Artists {
|
|
||||||
res.Index[i].Artists[j].Id = a.ArtistId
|
|
||||||
res.Index[i].Artists[j].Name = a.Artist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response := c.NewEmpty()
|
response := c.NewEmpty()
|
||||||
|
|
|
@ -2,22 +2,22 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/deluan/gosonic/api/responses"
|
"github.com/deluan/gosonic/api/responses"
|
||||||
"github.com/deluan/gosonic/domain"
|
"github.com/deluan/gosonic/engine"
|
||||||
"github.com/deluan/gosonic/utils"
|
"github.com/deluan/gosonic/utils"
|
||||||
"github.com/karlkfi/inject"
|
"github.com/karlkfi/inject"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetMusicFoldersController struct {
|
type GetMusicFoldersController struct {
|
||||||
BaseAPIController
|
BaseAPIController
|
||||||
repo domain.MediaFolderRepository
|
browser engine.Browser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GetMusicFoldersController) Prepare() {
|
func (c *GetMusicFoldersController) Prepare() {
|
||||||
inject.ExtractAssignable(utils.Graph, &c.repo)
|
inject.ExtractAssignable(utils.Graph, &c.browser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GetMusicFoldersController) Get() {
|
func (c *GetMusicFoldersController) Get() {
|
||||||
mediaFolderList, _ := c.repo.GetAll()
|
mediaFolderList, _ := c.browser.MediaFolders()
|
||||||
folders := make([]responses.MusicFolder, len(mediaFolderList))
|
folders := make([]responses.MusicFolder, len(mediaFolderList))
|
||||||
for i, f := range mediaFolderList {
|
for i, f := range mediaFolderList {
|
||||||
folders[i].Id = f.Id
|
folders[i].Id = f.Id
|
||||||
|
|
|
@ -2,15 +2,20 @@ package conf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/deluan/gosonic/domain"
|
"github.com/deluan/gosonic/domain"
|
||||||
|
"github.com/deluan/gosonic/engine"
|
||||||
"github.com/deluan/gosonic/persistence"
|
"github.com/deluan/gosonic/persistence"
|
||||||
"github.com/deluan/gosonic/utils"
|
"github.com/deluan/gosonic/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository)
|
// Persistence
|
||||||
utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository)
|
ir := utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository)
|
||||||
utils.DefineSingleton(new(domain.MediaFolderRepository), persistence.NewMediaFolderRepository)
|
pr := utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository)
|
||||||
|
mfr := utils.DefineSingleton(new(domain.MediaFolderRepository), persistence.NewMediaFolderRepository)
|
||||||
utils.DefineSingleton(new(domain.ArtistRepository), persistence.NewArtistRepository)
|
utils.DefineSingleton(new(domain.ArtistRepository), persistence.NewArtistRepository)
|
||||||
utils.DefineSingleton(new(domain.AlbumRepository), persistence.NewAlbumRepository)
|
utils.DefineSingleton(new(domain.AlbumRepository), persistence.NewAlbumRepository)
|
||||||
utils.DefineSingleton(new(domain.MediaFileRepository), persistence.NewMediaFileRepository)
|
utils.DefineSingleton(new(domain.MediaFileRepository), persistence.NewMediaFileRepository)
|
||||||
|
|
||||||
|
// Engine (Use cases)
|
||||||
|
utils.DefineSingleton(new(engine.Browser), engine.NewBrowser, pr, mfr, ir)
|
||||||
}
|
}
|
||||||
|
|
47
engine/browser.go
Normal file
47
engine/browser.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package engine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/deluan/gosonic/consts"
|
||||||
|
"github.com/deluan/gosonic/domain"
|
||||||
|
"github.com/deluan/gosonic/utils"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Browser interface {
|
||||||
|
MediaFolders() (domain.MediaFolders, error)
|
||||||
|
Indexes(ifModifiedSince time.Time) (domain.ArtistIndexes, time.Time, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBrowser(propRepo domain.PropertyRepository, folderRepo domain.MediaFolderRepository, indexRepo domain.ArtistIndexRepository) Browser {
|
||||||
|
return browser{propRepo, folderRepo, indexRepo}
|
||||||
|
}
|
||||||
|
|
||||||
|
type browser struct {
|
||||||
|
propRepo domain.PropertyRepository
|
||||||
|
folderRepo domain.MediaFolderRepository
|
||||||
|
indexRepo domain.ArtistIndexRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b browser) MediaFolders() (domain.MediaFolders, error) {
|
||||||
|
return b.folderRepo.GetAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b browser) Indexes(ifModifiedSince time.Time) (domain.ArtistIndexes, time.Time, error) {
|
||||||
|
l, err := b.propRepo.DefaultGet(consts.LastScan, "-1")
|
||||||
|
ms, _ := strconv.ParseInt(l, 10, 64)
|
||||||
|
lastModified := utils.ToTime(ms)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return domain.ArtistIndexes{}, time.Time{}, errors.New(fmt.Sprintf("Error retrieving LastScan property: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if lastModified.After(ifModifiedSince) {
|
||||||
|
indexes, err := b.indexRepo.GetAll()
|
||||||
|
return indexes, lastModified, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ArtistIndexes{}, lastModified, nil
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ var (
|
||||||
definitions map[reflect.Type]interface{}
|
definitions map[reflect.Type]interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface{}) {
|
func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface{}) interface{} {
|
||||||
typ := reflect.TypeOf(ptr)
|
typ := reflect.TypeOf(ptr)
|
||||||
provider := inject.NewProvider(constructor, args...)
|
provider := inject.NewProvider(constructor, args...)
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface
|
||||||
definitions[typ] = ptr
|
definitions[typ] = ptr
|
||||||
}
|
}
|
||||||
Graph.Define(ptr, provider)
|
Graph.Define(ptr, provider)
|
||||||
|
return ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
11
utils/time.go
Normal file
11
utils/time.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func ToTime(millis int64) time.Time {
|
||||||
|
return time.Unix(0, millis*int64(time.Millisecond))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToMillis(t time.Time) int64 {
|
||||||
|
return t.UnixNano() / int64(time.Millisecond)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue