diff --git a/.gopmfile b/.gopmfile index 40018f564..58024ba72 100644 --- a/.gopmfile +++ b/.gopmfile @@ -9,6 +9,7 @@ github.com/smartystreets/goconvey = commit:899ed5a github.com/karlkfi/inject = commit:fe06da2 github.com/dhowden/tag = commit:bccc91e github.com/nfnt/resize = commit:4d93a29 +github.com/deluan/gomate = [res] include = conf diff --git a/.travis.yml b/.travis.yml index 8b30b9446..6e8f2f730 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ install: - go get github.com/smartystreets/goconvey - go get github.com/dhowden/tag - go get github.com/nfnt/resize + - go get github.com/deluan/gomate script: - go test ./... -v diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go index 2ef02d164..e899b33ed 100644 --- a/conf/inject_definitions.go +++ b/conf/inject_definitions.go @@ -1,10 +1,13 @@ package conf import ( + "github.com/deluan/gomate" "github.com/deluan/gosonic/domain" "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/persistence" "github.com/deluan/gosonic/utils" + + "github.com/deluan/gosonic/scanner" ) func init() { @@ -22,4 +25,11 @@ func init() { utils.DefineSingleton(new(engine.ListGenerator), engine.NewListGenerator) utils.DefineSingleton(new(engine.Cover), engine.NewCover) utils.DefineSingleton(new(engine.Playlists), engine.NewPlaylists) + utils.DefineSingleton(new(engine.Search), engine.NewSearch) + + // Other dependencies + utils.DefineSingleton(new(scanner.Scanner), scanner.NewItunesScanner) + utils.DefineSingleton(new(gomate.Indexer), func() gomate.Indexer { + return gomate.NewIndexer(gomate.NewLedisEmbeddedDB(persistence.Db())) + }) } diff --git a/engine/search.go b/engine/search.go new file mode 100644 index 000000000..aea2ae14b --- /dev/null +++ b/engine/search.go @@ -0,0 +1,29 @@ +package engine + +import ( + "strings" + + "github.com/deluan/gomate" + "github.com/deluan/gosonic/domain" +) + +type Search interface { + IndexArtist(ar *domain.Artist) error + //IndexAlbum(al domain.Album) error + //IndexMediaFile(mf domain.MediaFile) error +} + +type search struct { + artistRepo domain.ArtistRepository + albumRepo domain.AlbumRepository + mfileRepo domain.MediaFileRepository + indexer gomate.Indexer +} + +func NewSearch(ar domain.ArtistRepository, alr domain.AlbumRepository, mr domain.MediaFileRepository, idx gomate.Indexer) Search { + return search{ar, alr, mr, idx} +} + +func (s search) IndexArtist(ar *domain.Artist) error { + return s.indexer.Index(ar.Id, strings.ToLower(ar.Name)) +} diff --git a/persistence/ledis_utils.go b/persistence/ledis.go similarity index 95% rename from persistence/ledis_utils.go rename to persistence/ledis.go index 7b1f0fe3e..bf2cd00c6 100644 --- a/persistence/ledis_utils.go +++ b/persistence/ledis.go @@ -1,10 +1,11 @@ package persistence import ( + "sync" + "github.com/astaxie/beego" "github.com/siddontang/ledisdb/config" "github.com/siddontang/ledisdb/ledis" - "sync" ) var ( @@ -13,7 +14,7 @@ var ( once sync.Once ) -func db() *ledis.DB { +func Db() *ledis.DB { once.Do(func() { config := config.NewConfigDefault() config.DataDir = beego.AppConfig.String("dbPath") @@ -29,6 +30,6 @@ func db() *ledis.DB { } func dropDb() { - db() + Db() _ledisInstance.FlushAll() } diff --git a/persistence/ledis_repository.go b/persistence/ledis_repository.go index 7edd2a0b3..d94207455 100644 --- a/persistence/ledis_repository.go +++ b/persistence/ledis_repository.go @@ -41,13 +41,13 @@ func (r *ledisRepository) NewId(fields ...string) string { } func (r *ledisRepository) CountAll() (int64, error) { - size, err := db().ZCard([]byte(r.table + "s:all")) + size, err := Db().ZCard([]byte(r.table + "s:all")) return size, err } func (r *ledisRepository) getAllIds() (map[string]bool, error) { m := make(map[string]bool) - pairs, err := db().ZRange([]byte(r.table+"s:all"), 0, -1) + pairs, err := Db().ZRange([]byte(r.table+"s:all"), 0, -1) if err != nil { return m, err } @@ -66,7 +66,7 @@ func (r *ledisRepository) DeleteAll(ids map[string]bool) error { // Delete from parent:parentId:table (ZSet) if r.parentTable != "" { parentKey := []byte(fmt.Sprintf("%s:%s:%s", r.table, id, r.parentIdField)) - pid, err := db().Get(parentKey) + pid, err := Db().Get(parentKey) var parentId string if err := json.Unmarshal(pid, &parentId); err != nil { return err @@ -75,7 +75,7 @@ func (r *ledisRepository) DeleteAll(ids map[string]bool) error { return err } parentKey = []byte(fmt.Sprintf("%s:%s:%ss", r.parentTable, parentId, r.table)) - if _, err := db().ZRem(parentKey, []byte(id)); err != nil { + if _, err := Db().ZRem(parentKey, []byte(id)); err != nil { return err } } @@ -90,19 +90,19 @@ func (r *ledisRepository) DeleteAll(ids map[string]bool) error { } // Delete from table:all (ZSet) - _, err := db().ZRem([]byte(allKey), keys...) + _, err := Db().ZRem([]byte(allKey), keys...) return err } func (r *ledisRepository) deleteRecord(id string) error { keys := r.getFieldKeys(id) - _, err := db().Del(keys...) + _, err := Db().Del(keys...) return err } func (r *ledisRepository) Exists(id string) (bool, error) { - res, _ := db().ZScore([]byte(r.table+"s:all"), []byte(id)) + res, _ := Db().ZScore([]byte(r.table+"s:all"), []byte(id)) return res != ledis.InvalidScore, nil } @@ -117,19 +117,19 @@ func (r *ledisRepository) saveOrUpdate(id string, entity interface{}) error { for f, v := range h { key := recordPrefix + f value, _ := json.Marshal(v) - if err := db().Set([]byte(key), value); err != nil { + if err := Db().Set([]byte(key), value); err != nil { return err } } sid := ledis.ScorePair{0, []byte(id)} - if _, err = db().ZAdd([]byte(allKey), sid); err != nil { + if _, err = Db().ZAdd([]byte(allKey), sid); err != nil { return err } if parentCollectionKey := r.getParentRelationKey(entity); parentCollectionKey != "" { - _, err = db().ZAdd([]byte(parentCollectionKey), sid) + _, err = Db().ZAdd([]byte(parentCollectionKey), sid) } return nil } @@ -184,7 +184,7 @@ func (r *ledisRepository) readEntity(id string) (interface{}, error) { fieldKeys := r.getFieldKeys(id) - res, err := db().MGet(fieldKeys...) + res, err := Db().MGet(fieldKeys...) if err != nil { return nil, err } @@ -229,7 +229,7 @@ func (r *ledisRepository) loadFromSet(setName string, entities interface{}, qo . if o.SortBy != "" { sortKey = []byte(fmt.Sprintf("%s:*:%s", r.table, o.SortBy)) } - response, err := db().XZSort([]byte(setName), o.Offset, o.Size, o.Alpha, o.Desc, sortKey, r.getFieldKeys("*")) + response, err := Db().XZSort([]byte(setName), o.Offset, o.Size, o.Alpha, o.Desc, sortKey, r.getFieldKeys("*")) if err != nil { return err } diff --git a/scanner/importer.go b/scanner/importer.go index 8174cef6e..6103eac40 100644 --- a/scanner/importer.go +++ b/scanner/importer.go @@ -10,7 +10,6 @@ import ( "github.com/deluan/gosonic/consts" "github.com/deluan/gosonic/domain" "github.com/deluan/gosonic/engine" - "github.com/deluan/gosonic/persistence" "github.com/deluan/gosonic/utils" ) @@ -26,16 +25,16 @@ type tempIndex map[string]domain.ArtistInfo func StartImport() { go func() { - i := &Importer{ - scanner: &ItunesScanner{}, - mediaFolder: beego.AppConfig.String("musicFolder"), - mfRepo: persistence.NewMediaFileRepository(), - albumRepo: persistence.NewAlbumRepository(), - artistRepo: persistence.NewArtistRepository(), - idxRepo: persistence.NewArtistIndexRepository(), - plsRepo: persistence.NewPlaylistRepository(), - propertyRepo: persistence.NewPropertyRepository(), - } + // TODO Move all to DI + i := &Importer{mediaFolder: beego.AppConfig.String("musicFolder")} + utils.ResolveDependency(&i.mfRepo) + utils.ResolveDependency(&i.albumRepo) + utils.ResolveDependency(&i.artistRepo) + utils.ResolveDependency(&i.idxRepo) + utils.ResolveDependency(&i.plsRepo) + utils.ResolveDependency(&i.propertyRepo) + utils.ResolveDependency(&i.search) + utils.ResolveDependency(&i.scanner) i.Run() }() } @@ -50,6 +49,7 @@ type Importer struct { idxRepo domain.ArtistIndexRepository plsRepo domain.PlaylistRepository propertyRepo engine.PropertyRepository + search engine.Search lastScan time.Time } @@ -124,6 +124,9 @@ func (i *Importer) importLibrary() (err error) { if err := i.artistRepo.Put(ar); err != nil { beego.Error(err) } + if err := i.search.IndexArtist(ar); err != nil { + beego.Error("Error indexing artist:", err) + } i.collectIndex(indexGroups, ar, artistIndex) } diff --git a/scanner/itunes_scanner.go b/scanner/itunes_scanner.go index 8508f017c..eba006b35 100644 --- a/scanner/itunes_scanner.go +++ b/scanner/itunes_scanner.go @@ -31,6 +31,10 @@ type ItunesScanner struct { lastModifiedSince time.Time } +func NewItunesScanner() *ItunesScanner { + return &ItunesScanner{} +} + type plsRelation struct { pID string parentPID string diff --git a/utils/graph.go b/utils/graph.go index b580f19bb..881e40288 100644 --- a/utils/graph.go +++ b/utils/graph.go @@ -25,6 +25,10 @@ func DefineSingleton(ptr interface{}, constructor interface{}) interface{} { return ptr } +func ResolveDependency(ptr interface{}) { + inject.ExtractAssignable(Graph, ptr) +} + func init() { definitions = make(map[reflect.Type]interface{}) Graph = inject.NewGraph()