Implement file cache through artifact cache
This commit is contained in:
parent
872752d3ef
commit
9f9efa18c0
4 changed files with 118 additions and 14 deletions
|
@ -92,5 +92,5 @@ func (h *HeartbeatHandler) Register(mux *http.ServeMux) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HeartbeatHandler) heartbeat(w http.ResponseWriter, r *http.Request) {
|
func (h *HeartbeatHandler) heartbeat(w http.ResponseWriter, r *http.Request) {
|
||||||
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotFound = errors.New("file not found")
|
ErrNotFound = errors.New("artifact not found")
|
||||||
ErrWriteLocked = errors.New("file is locked for write")
|
ErrWriteLocked = errors.New("artifact is locked for write")
|
||||||
ErrReadLocked = errors.New("file is locked for read")
|
ErrReadLocked = errors.New("artifact is locked for read")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
|
|
|
@ -2,11 +2,12 @@ package filecache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,33 +17,95 @@ var (
|
||||||
ErrReadLocked = errors.New("file is locked for read")
|
ErrReadLocked = errors.New("file is locked for read")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const fileName = "file"
|
||||||
|
|
||||||
|
func convertErr(err error) error {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, artifact.ErrNotFound):
|
||||||
|
return ErrNotFound
|
||||||
|
case errors.Is(err, artifact.ErrWriteLocked):
|
||||||
|
return ErrWriteLocked
|
||||||
|
case errors.Is(err, artifact.ErrReadLocked):
|
||||||
|
return ErrReadLocked
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
rootDir string
|
cache *artifact.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(rootDir string) (*Cache, error) {
|
func New(rootDir string) (*Cache, error) {
|
||||||
if err := os.MkdirAll(rootDir, 0777); err != nil {
|
cache, err := artifact.NewCache(rootDir)
|
||||||
return nil, fmt.Errorf("error creating filecache: %w", err)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &Cache{rootDir: rootDir}
|
c := &Cache{cache: cache}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) Range(fileFn func(file build.ID) error) error {
|
func (c *Cache) Range(fileFn func(file build.ID) error) error {
|
||||||
panic("implement me")
|
return c.cache.Range(fileFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) Remove(file build.ID) error {
|
func (c *Cache) Remove(file build.ID) error {
|
||||||
panic("implement me")
|
return convertErr(c.cache.Remove(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) Write(file build.ID) (w io.WriteCloser, abort func(), err error) {
|
type fileWriter struct {
|
||||||
panic("implement me")
|
f *os.File
|
||||||
|
commit func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fileWriter) Write(p []byte) (int, error) {
|
||||||
|
return f.f.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fileWriter) Close() error {
|
||||||
|
closeErr := f.f.Close()
|
||||||
|
commitErr := f.commit()
|
||||||
|
|
||||||
|
if closeErr != nil {
|
||||||
|
return closeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return commitErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) Write(file build.ID) (w io.WriteCloser, abort func() error, err error) {
|
||||||
|
path, commit, abortDir, err := c.cache.Create(file)
|
||||||
|
if err != nil {
|
||||||
|
err = convertErr(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(filepath.Join(path, fileName))
|
||||||
|
if err != nil {
|
||||||
|
_ = abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w = &fileWriter{f: f, commit: commit}
|
||||||
|
abort = func() error {
|
||||||
|
closeErr := f.Close()
|
||||||
|
abortErr := abortDir()
|
||||||
|
|
||||||
|
if closeErr != nil {
|
||||||
|
return closeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return abortErr
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) Get(file build.ID) (path string, unlock func(), err error) {
|
func (c *Cache) Get(file build.ID) (path string, unlock func(), err error) {
|
||||||
panic("implement me")
|
root, unlock, err := c.cache.Get(file)
|
||||||
|
path = filepath.Join(root, fileName)
|
||||||
|
err = convertErr(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(c *Cache) http.Handler {
|
func NewHandler(c *Cache) http.Handler {
|
||||||
|
|
41
distbuild/pkg/filecache/filecache_test.go
Normal file
41
distbuild/pkg/filecache/filecache_test.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package filecache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFileCache(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir("", "filecache")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cache, err := New(tmpDir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, abort, err := cache.Write(build.ID{01})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, abort())
|
||||||
|
|
||||||
|
_, _, err = cache.Get(build.ID{01})
|
||||||
|
require.Truef(t, errors.Is(err, ErrNotFound), "real error: %v", err)
|
||||||
|
|
||||||
|
f, _, err := cache.Write(build.ID{02})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = f.Write([]byte("foo bar"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, f.Close())
|
||||||
|
|
||||||
|
path, unlock, err := cache.Get(build.ID{02})
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer unlock()
|
||||||
|
|
||||||
|
content, err := ioutil.ReadFile(path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []byte("foo bar"), content)
|
||||||
|
}
|
Loading…
Reference in a new issue