1
Fork 0
photoview/api/scanner/scanner_task/scanner_task.go

103 lines
3.4 KiB
Go
Raw Normal View History

2022-02-14 23:57:45 +01:00
package scanner_task
import (
"context"
"database/sql"
2022-07-08 17:44:03 +02:00
"flag"
2022-02-14 23:57:45 +01:00
"io/fs"
"github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner/media_encoding"
"github.com/photoview/photoview/api/scanner/scanner_cache"
"gorm.io/gorm"
)
// ScannerTask is an interface for a task to be performed as a part of the scanner pipeline
type ScannerTask interface {
// BeforeScanAlbum will run at the beginning of the scan task.
// New values can be stored in the returned TaskContext that will live throughout the lifetime of the task.
BeforeScanAlbum(ctx TaskContext) (TaskContext, error)
// AfterScanAlbum will run at the end of the scan task.
AfterScanAlbum(ctx TaskContext, changedMedia []*models.Media, albumMedia []*models.Media) error
// MediaFound will run for each media file found on the filesystem.
// It will run even when the media is already present in the database.
// If the returned skip value is true, the media will be skipped and further steps will not be executed for the given file.
2022-02-14 23:57:45 +01:00
MediaFound(ctx TaskContext, fileInfo fs.FileInfo, mediaPath string) (skip bool, err error)
// AfterMediaFound will run each media file after is has been saved to the database, but not processed yet.
// It will run even when the media is already present in the database, in that case `newMedia` will be true.
2022-02-14 23:57:45 +01:00
AfterMediaFound(ctx TaskContext, media *models.Media, newMedia bool) error
BeforeProcessMedia(ctx TaskContext, mediaData *media_encoding.EncodeMediaData) (TaskContext, error)
ProcessMedia(ctx TaskContext, mediaData *media_encoding.EncodeMediaData, mediaCachePath string) (updatedURLs []*models.MediaURL, err error)
AfterProcessMedia(ctx TaskContext, mediaData *media_encoding.EncodeMediaData, updatedURLs []*models.MediaURL, mediaIndex int, mediaTotal int) error
2022-02-14 23:57:45 +01:00
}
type TaskContext struct {
ctx context.Context
}
func NewTaskContext(parent context.Context, db *gorm.DB, album *models.Album, cache *scanner_cache.AlbumScannerCache) TaskContext {
ctx := TaskContext{ctx: parent}
ctx = ctx.WithValue(taskCtxKeyAlbum, album)
ctx = ctx.WithValue(taskCtxKeyAlbumCache, cache)
ctx = ctx.WithDB(db)
2022-02-14 23:57:45 +01:00
return ctx
2022-02-14 23:57:45 +01:00
}
type taskCtxKeyType string
const (
taskCtxKeyAlbum taskCtxKeyType = "task_album"
taskCtxKeyAlbumCache taskCtxKeyType = "task_album_cache"
taskCtxKeyDatabase taskCtxKeyType = "task_database"
)
func (c TaskContext) GetAlbum() *models.Album {
return c.ctx.Value(taskCtxKeyAlbum).(*models.Album)
}
func (c TaskContext) GetCache() *scanner_cache.AlbumScannerCache {
return c.ctx.Value(taskCtxKeyAlbumCache).(*scanner_cache.AlbumScannerCache)
}
func (c TaskContext) GetDB() *gorm.DB {
return c.ctx.Value(taskCtxKeyDatabase).(*gorm.DB)
}
func (c TaskContext) DatabaseTransaction(transFunc func(ctx TaskContext) error, opts ...*sql.TxOptions) error {
return c.GetDB().Transaction(func(tx *gorm.DB) error {
return transFunc(c.WithDB(tx))
}, opts...)
}
2022-02-14 23:57:45 +01:00
func (c TaskContext) WithValue(key, val interface{}) TaskContext {
return TaskContext{
ctx: context.WithValue(c.ctx, key, val),
}
}
func (c TaskContext) Value(key interface{}) interface{} {
return c.ctx.Value(key)
}
func (c TaskContext) WithDB(db *gorm.DB) TaskContext {
2022-07-08 17:44:03 +02:00
// Allow db to be nil in tests
if db == nil && flag.Lookup("test.v") != nil {
return c
}
return c.WithValue(taskCtxKeyDatabase, db.WithContext(c.ctx))
}
func (c TaskContext) Done() <-chan struct{} {
return c.ctx.Done()
}
func (c TaskContext) Err() error {
return c.ctx.Err()
}