Expose additional interfaces in LimitedStore

Previously if a DataStore would be embedded as a TerminaterDataStore inside
a LimitedStore. This makes additional interfaces, such as GetReaderDataStore,
inaccessible since we are not able to cast a LimitedStore to
GetReaderDataStore. The solution was to manually expose the specific methods
although this is definitly not the nicest solution.
This commit is contained in:
Marius 2016-01-27 15:18:37 +01:00
parent ff11b6a274
commit 9cd15b2a0f
2 changed files with 69 additions and 0 deletions

View File

@ -12,10 +12,20 @@
// properly. Two tusd.FileStore instances using the same directory, for example. // properly. Two tusd.FileStore instances using the same directory, for example.
// In addition the limited store will keep a list of the uploads' IDs in memory // In addition the limited store will keep a list of the uploads' IDs in memory
// which may create a growing memory leak. // which may create a growing memory leak.
//
// While LimitedStore implements the GetReader, LockUpload, UnlockUpload,
// FinishUpload and ConcatUploads methods, it does not contain proper definitions
// for them. When invoked, the call will be passed to the underlying
// data store as long as it provides these methods. If not, either an error
// is returned or nothing happens (see the specific methods for more
// detailed information). The motivation behind this decision was, that this
// allows to expose the additional extensions implemented using the
// interfaces, such as GetReaderDataStore.
package limitedstore package limitedstore
import ( import (
"github.com/tus/tusd" "github.com/tus/tusd"
"io"
"sort" "sort"
"sync" "sync"
) )
@ -125,3 +135,55 @@ func (store *LimitedStore) ensureSpace(size int64) error {
return nil return nil
} }
// GetReader will pass the call to the underlying data store if it implements
// the tusd.GetReaderDataStore interface. Else tusd.ErrNotImplemented will be
// returned.
func (store *LimitedStore) GetReader(id string) (io.Reader, error) {
if s, ok := store.TerminaterDataStore.(tusd.GetReaderDataStore); ok {
return s.GetReader(id)
} else {
return nil, tusd.ErrNotImplemented
}
}
// LockUpload will pass the call to the underlying data store if it implements
// the tusd.LockerDataStore interface. Else this function simply returns nil.
func (store *LimitedStore) LockUpload(id string) error {
if s, ok := store.TerminaterDataStore.(tusd.LockerDataStore); ok {
return s.LockUpload(id)
}
return nil
}
// UnlockUpload will pass the call to the underlying data store if it implements
// the tusd.LockerDataStore interface. Else this function simply returns nil.
func (store *LimitedStore) UnlockUpload(id string) error {
if s, ok := store.TerminaterDataStore.(tusd.LockerDataStore); ok {
return s.UnlockUpload(id)
}
return nil
}
// FinishUpload will pass the call to the underlying data store if it implements
// the tusd.FinisherDataStore interface. Else this function simply returns nil.
func (store *LimitedStore) FinishUpload(id string) error {
if s, ok := store.TerminaterDataStore.(tusd.FinisherDataStore); ok {
return s.FinishUpload(id)
}
return nil
}
// ConcatUploads will pass the call to the underlying data store if it implements
// the tusd.ConcaterDataStore interface. Else tusd.ErrNotImplemented will be
// returned.
func (store *LimitedStore) ConcatUploads(dest string, src []string) error {
if s, ok := store.TerminaterDataStore.(tusd.ConcaterDataStore); ok {
return s.ConcatUploads(dest, src)
} else {
return tusd.ErrNotImplemented
}
}

View File

@ -10,6 +10,13 @@ import (
"github.com/tus/tusd" "github.com/tus/tusd"
) )
var _ tusd.DataStore = &LimitedStore{}
var _ tusd.GetReaderDataStore = &LimitedStore{}
var _ tusd.TerminaterDataStore = &LimitedStore{}
var _ tusd.LockerDataStore = &LimitedStore{}
var _ tusd.ConcaterDataStore = &LimitedStore{}
var _ tusd.FinisherDataStore = &LimitedStore{}
type dataStore struct { type dataStore struct {
t *assert.Assertions t *assert.Assertions
numCreatedUploads int numCreatedUploads int