mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Add filesystem based blob storage (#3187)
* Refactor transaction hooks. Add preCommit * Add BlobStore * Use blobStore for tag images * Use blobStore for studio images * Use blobStore for performer images * Use blobStore for scene covers * Don't generate screenshots in legacy directory * Run post-hooks outside original transaction * Use blobStore for movie images * Remove unnecessary DestroyImage methods * Add missing filter for scene cover * Add covers to generate options * Add generate cover option to UI * Add screenshot migration * Delete thumb files as part of screenshot migration
This commit is contained in:
@@ -11,9 +11,10 @@ const (
|
||||
)
|
||||
|
||||
type hookManager struct {
|
||||
postCommitHooks []TxnFunc
|
||||
postRollbackHooks []TxnFunc
|
||||
postCompleteHooks []TxnFunc
|
||||
preCommitHooks []TxnFunc
|
||||
postCommitHooks []MustFunc
|
||||
postRollbackHooks []MustFunc
|
||||
postCompleteHooks []MustFunc
|
||||
}
|
||||
|
||||
func (m *hookManager) register(ctx context.Context) context.Context {
|
||||
@@ -28,39 +29,55 @@ func hookManagerCtx(ctx context.Context) *hookManager {
|
||||
return m
|
||||
}
|
||||
|
||||
func executeHooks(ctx context.Context, hooks []TxnFunc) {
|
||||
func executeHooks(ctx context.Context, hooks []TxnFunc) error {
|
||||
// we need to return the first error
|
||||
for _, h := range hooks {
|
||||
// ignore errors
|
||||
_ = h(ctx)
|
||||
if err := h(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func executeMustHooks(ctx context.Context, hooks []MustFunc) {
|
||||
for _, h := range hooks {
|
||||
h(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func executePostCommitHooks(ctx context.Context, outerCtx context.Context) {
|
||||
m := hookManagerCtx(ctx)
|
||||
executeHooks(outerCtx, m.postCommitHooks)
|
||||
func (m *hookManager) executePostCommitHooks(ctx context.Context) {
|
||||
executeMustHooks(ctx, m.postCommitHooks)
|
||||
}
|
||||
|
||||
func executePostRollbackHooks(ctx context.Context, outerCtx context.Context) {
|
||||
m := hookManagerCtx(ctx)
|
||||
executeHooks(outerCtx, m.postRollbackHooks)
|
||||
func (m *hookManager) executePostRollbackHooks(ctx context.Context) {
|
||||
executeMustHooks(ctx, m.postRollbackHooks)
|
||||
}
|
||||
|
||||
func executePostCompleteHooks(ctx context.Context, outerCtx context.Context) {
|
||||
m := hookManagerCtx(ctx)
|
||||
executeHooks(outerCtx, m.postCompleteHooks)
|
||||
func (m *hookManager) executePreCommitHooks(ctx context.Context) error {
|
||||
return executeHooks(ctx, m.preCommitHooks)
|
||||
}
|
||||
|
||||
func AddPostCommitHook(ctx context.Context, hook TxnFunc) {
|
||||
func (m *hookManager) executePostCompleteHooks(ctx context.Context) {
|
||||
executeMustHooks(ctx, m.postCompleteHooks)
|
||||
}
|
||||
|
||||
func AddPreCommitHook(ctx context.Context, hook TxnFunc) {
|
||||
m := hookManagerCtx(ctx)
|
||||
m.preCommitHooks = append(m.preCommitHooks, hook)
|
||||
}
|
||||
|
||||
func AddPostCommitHook(ctx context.Context, hook MustFunc) {
|
||||
m := hookManagerCtx(ctx)
|
||||
m.postCommitHooks = append(m.postCommitHooks, hook)
|
||||
}
|
||||
|
||||
func AddPostRollbackHook(ctx context.Context, hook TxnFunc) {
|
||||
func AddPostRollbackHook(ctx context.Context, hook MustFunc) {
|
||||
m := hookManagerCtx(ctx)
|
||||
m.postRollbackHooks = append(m.postRollbackHooks, hook)
|
||||
}
|
||||
|
||||
func AddPostCompleteHook(ctx context.Context, hook TxnFunc) {
|
||||
func AddPostCompleteHook(ctx context.Context, hook MustFunc) {
|
||||
m := hookManagerCtx(ctx)
|
||||
m.postCompleteHooks = append(m.postCompleteHooks, hook)
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ type DatabaseProvider interface {
|
||||
WithDatabase(ctx context.Context) (context.Context, error)
|
||||
}
|
||||
|
||||
type DatabaseProviderManager interface {
|
||||
DatabaseProvider
|
||||
Manager
|
||||
}
|
||||
|
||||
// TxnFunc is a function that is used in transaction hooks.
|
||||
// It should return an error if something went wrong.
|
||||
type TxnFunc func(ctx context.Context) error
|
||||
|
||||
// MustFunc is a function that is used in transaction hooks.
|
||||
// It does not return an error.
|
||||
type MustFunc func(ctx context.Context)
|
||||
|
||||
// WithTxn executes fn in a transaction. If fn returns an error then
|
||||
// the transaction is rolled back. Otherwise it is committed.
|
||||
// Transaction is exclusive. Only one thread may run a transaction
|
||||
@@ -51,35 +52,44 @@ func WithReadTxn(ctx context.Context, m Manager, fn TxnFunc) error {
|
||||
return withTxn(ctx, m, fn, exclusive, execComplete)
|
||||
}
|
||||
|
||||
func withTxn(outerCtx context.Context, m Manager, fn TxnFunc, exclusive bool, execCompleteOnLocked bool) error {
|
||||
ctx, err := begin(outerCtx, m, exclusive)
|
||||
func withTxn(ctx context.Context, m Manager, fn TxnFunc, exclusive bool, execCompleteOnLocked bool) error {
|
||||
// post-hooks should be executed with the outside context
|
||||
txnCtx, err := begin(ctx, m, exclusive)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hookMgr := hookManagerCtx(txnCtx)
|
||||
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
// a panic occurred, rollback and repanic
|
||||
rollback(ctx, outerCtx, m)
|
||||
rollback(txnCtx, m)
|
||||
panic(p)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// something went wrong, rollback
|
||||
rollback(ctx, outerCtx, m)
|
||||
rollback(txnCtx, m)
|
||||
|
||||
// execute post-hooks with outside context
|
||||
hookMgr.executePostRollbackHooks(ctx)
|
||||
|
||||
if execCompleteOnLocked || !m.IsLocked(err) {
|
||||
executePostCompleteHooks(ctx, outerCtx)
|
||||
hookMgr.executePostCompleteHooks(ctx)
|
||||
}
|
||||
} else {
|
||||
// all good, commit
|
||||
err = commit(ctx, outerCtx, m)
|
||||
executePostCompleteHooks(ctx, outerCtx)
|
||||
err = commit(txnCtx, m)
|
||||
|
||||
// execute post-hooks with outside context
|
||||
hookMgr.executePostCommitHooks(ctx)
|
||||
hookMgr.executePostCompleteHooks(ctx)
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
err = fn(ctx)
|
||||
err = fn(txnCtx)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -96,21 +106,23 @@ func begin(ctx context.Context, m Manager, exclusive bool) (context.Context, err
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func commit(ctx context.Context, outerCtx context.Context, m Manager) error {
|
||||
func commit(ctx context.Context, m Manager) error {
|
||||
hookMgr := hookManagerCtx(ctx)
|
||||
if err := hookMgr.executePreCommitHooks(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.Commit(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
executePostCommitHooks(ctx, outerCtx)
|
||||
return nil
|
||||
}
|
||||
|
||||
func rollback(ctx context.Context, outerCtx context.Context, m Manager) {
|
||||
func rollback(ctx context.Context, m Manager) {
|
||||
if err := m.Rollback(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
executePostRollbackHooks(ctx, outerCtx)
|
||||
}
|
||||
|
||||
// WithDatabase executes fn with the context provided by p.WithDatabase.
|
||||
|
||||
Reference in New Issue
Block a user