Added a new layer: engine (equivalent to use cases in Clean Architecture). Should make testing things easier

This commit is contained in:
Deluan 2016-03-07 10:57:32 -05:00
parent 56e9ad3def
commit 91c660c746
6 changed files with 91 additions and 39 deletions

View file

@ -1,23 +1,23 @@
package api
import (
"fmt"
"github.com/astaxie/beego"
"github.com/deluan/gosonic/api/responses"
"github.com/deluan/gosonic/consts"
"github.com/deluan/gosonic/domain"
"github.com/deluan/gosonic/engine"
"github.com/deluan/gosonic/utils"
"github.com/karlkfi/inject"
"strconv"
)
type GetIndexesController struct {
BaseAPIController
repo domain.ArtistIndexRepository
properties domain.PropertyRepository
browser engine.Browser
}
func (c *GetIndexesController) Prepare() {
inject.ExtractAssignable(utils.Graph, &c.repo)
inject.ExtractAssignable(utils.Graph, &c.browser)
inject.ExtractAssignable(utils.Graph, &c.properties)
}
@ -25,40 +25,28 @@ func (c *GetIndexesController) Prepare() {
func (c *GetIndexesController) Get() {
var err error
ifModifiedSince := c.Input().Get("ifModifiedSince")
if ifModifiedSince == "" {
ifModifiedSince = "0"
}
var ifModifiedSince int64
c.Ctx.Input.Bind(&ifModifiedSince, "ifModifiedSince")
res := responses.Indexes{}
res.IgnoredArticles = beego.AppConfig.String("ignoredArticles")
res.LastModified, err = c.properties.DefaultGet(consts.LastScan, "-1")
indexes, lastModified, err := c.browser.Indexes(utils.ToTime(ifModifiedSince))
if err != nil {
beego.Error("Error retrieving LastScan property:", err)
beego.Error("Error retrieving Indexes:", err)
c.SendError(responses.ERROR_GENERIC, "Internal Error")
}
i, _ := strconv.Atoi(ifModifiedSince)
l, _ := strconv.Atoi(res.LastModified)
res := responses.Indexes{
IgnoredArticles: beego.AppConfig.String("ignoredArticles"),
LastModified: fmt.Sprint(utils.ToMillis(lastModified)),
}
if l > i {
indexes, err := c.repo.GetAll()
if err != nil {
beego.Error("Error retrieving Indexes:", err)
c.SendError(responses.ERROR_GENERIC, "Internal Error")
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
}
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()

View file

@ -2,22 +2,22 @@ package api
import (
"github.com/deluan/gosonic/api/responses"
"github.com/deluan/gosonic/domain"
"github.com/deluan/gosonic/engine"
"github.com/deluan/gosonic/utils"
"github.com/karlkfi/inject"
)
type GetMusicFoldersController struct {
BaseAPIController
repo domain.MediaFolderRepository
browser engine.Browser
}
func (c *GetMusicFoldersController) Prepare() {
inject.ExtractAssignable(utils.Graph, &c.repo)
inject.ExtractAssignable(utils.Graph, &c.browser)
}
func (c *GetMusicFoldersController) Get() {
mediaFolderList, _ := c.repo.GetAll()
mediaFolderList, _ := c.browser.MediaFolders()
folders := make([]responses.MusicFolder, len(mediaFolderList))
for i, f := range mediaFolderList {
folders[i].Id = f.Id

View file

@ -2,15 +2,20 @@ package conf
import (
"github.com/deluan/gosonic/domain"
"github.com/deluan/gosonic/engine"
"github.com/deluan/gosonic/persistence"
"github.com/deluan/gosonic/utils"
)
func init() {
utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository)
utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository)
utils.DefineSingleton(new(domain.MediaFolderRepository), persistence.NewMediaFolderRepository)
// Persistence
ir := utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository)
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.AlbumRepository), persistence.NewAlbumRepository)
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
View 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
}

View file

@ -11,7 +11,7 @@ var (
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)
provider := inject.NewProvider(constructor, args...)
@ -21,6 +21,7 @@ func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface
definitions[typ] = ptr
}
Graph.Define(ptr, provider)
return ptr
}
func init() {

11
utils/time.go Normal file
View 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)
}