From 9a6ceda00352f142deef2699a86287454dc83816 Mon Sep 17 00:00:00 2001 From: Umputun Date: Mon, 10 Sep 2018 12:38:00 -0500 Subject: [PATCH] add migrator between avatar stores --- backend/app/store/avatar/gridfs.go | 2 ++ backend/app/store/avatar/localfs.go | 2 ++ backend/app/store/avatar/store.go | 22 +++++++++++++ backend/app/store/avatar/store_test.go | 44 ++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/backend/app/store/avatar/gridfs.go b/backend/app/store/avatar/gridfs.go index eb067b1c..5bbe3eb1 100644 --- a/backend/app/store/avatar/gridfs.go +++ b/backend/app/store/avatar/gridfs.go @@ -97,6 +97,8 @@ func (gf *GridFS) Remove(avatar string) error { }) } +// List all avatars (ids) on gfs +// note: id includes .image suffix func (gf *GridFS) List() (ids []string, err error) { type gfsFile struct { diff --git a/backend/app/store/avatar/localfs.go b/backend/app/store/avatar/localfs.go index 6bcae627..dd70acad 100644 --- a/backend/app/store/avatar/localfs.go +++ b/backend/app/store/avatar/localfs.go @@ -97,6 +97,8 @@ func (fs *LocalFS) Remove(avatar string) error { return os.Remove(avFile) } +// List all avatars (ids) on local file system +// note: id includes .image suffix func (fs *LocalFS) List() (ids []string, err error) { err = filepath.Walk(fs.storePath, func(path string, info os.FileInfo, err error) error { diff --git a/backend/app/store/avatar/store.go b/backend/app/store/avatar/store.go index 0a5b5c94..add4c83c 100644 --- a/backend/app/store/avatar/store.go +++ b/backend/app/store/avatar/store.go @@ -35,6 +35,28 @@ type Store interface { } +// Migrate avatars between stores +func Migrate(dst Store, src Store) (int, error) { + ids, err := src.List() + if err != nil { + return 0, err + } + for _, id := range ids { + srcReader, _, err := src.Get(id) + if err != nil { + log.Printf("[WARN] can't get reader for avatar %s", id) + continue + } + if _, err = dst.Put(id, srcReader); err != nil { + log.Printf("[WARN] can't put avatar %s", id) + } + if err = srcReader.Close(); err != nil { + log.Printf("[WARN] failed to close avatar %s", id) + } + } + return len(ids), nil +} + // resize an image of supported format (PNG, JPG, GIF) to the size of "limit" px of the biggest side // (width or height) preserving aspect ratio. // Returns original reader if resizing is not needed or failed. diff --git a/backend/app/store/avatar/store_test.go b/backend/app/store/avatar/store_test.go index a0cac0c9..377af11a 100644 --- a/backend/app/store/avatar/store_test.go +++ b/backend/app/store/avatar/store_test.go @@ -5,6 +5,8 @@ import ( "image" "io" "io/ioutil" + "os" + "sort" "strings" "testing" @@ -63,3 +65,45 @@ func TestAvatarStore_resize(t *testing.T) { assert.Equalf(t, c.hr, bounds.Dy(), "file %s", c.file) } } + +func TestAvatarStore_Migrate(t *testing.T) { + // prep localfs + plocal := NewLocalFS("/tmp/avatars.test", 300) + err := os.MkdirAll("/tmp/avatars.test", 0700) + require.NoError(t, err) + defer os.RemoveAll("/tmp/avatars.test") + + // prep gridfs + pgfs, skip := prepGFStore(t) + if skip { + return + } + + // write to localfs + _, err = plocal.Put("user1", strings.NewReader("some picture bin data 1")) + require.Nil(t, err) + _, err = plocal.Put("user2", strings.NewReader("some picture bin data 2")) + require.Nil(t, err) + _, err = plocal.Put("user3", strings.NewReader("some picture bin data 3")) + require.Nil(t, err) + + // migrate and check reported count + count, err := Migrate(pgfs, plocal) + require.NoError(t, err) + assert.Equal(t, 3, count, "all 3 recs migrated") + + // list avatars + l, err := pgfs.List() + assert.NoError(t, err) + assert.Equal(t, 3, len(l), "3 avatars listed in destination store") + sort.Strings(l) + assert.Equal(t, []string{"0b7f849446d3383546d15a480966084442cd2193.image", "a1881c06eec96db9901c7bbfe41c42a3f08e9cb4.image", "b3daa77b4c04a9551b8781d03191fe098f325e67.image"}, l) + + // try to read one of migrated avatars + r, size, err := pgfs.Get("0b7f849446d3383546d15a480966084442cd2193.image") + assert.Nil(t, err) + assert.Equal(t, 23, size) + data, err := ioutil.ReadAll(r) + assert.Nil(t, err) + assert.Equal(t, "some picture bin data 3", string(data)) +}