Skip to content

Commit

Permalink
fix(refresh): force assets to refresh via Lookup (#23)
Browse files Browse the repository at this point in the history
Previously it was entirely possible for `ReadAll` to be repeatedly
invoked without refreshing the assets, since `Lookup` only `.get`
instead of `.refresh()`.

Since there is a refresh threshold now, it is better to do a refresh
if the threshold has exceeded, to prevent issues with asset of similar
name being deleted and re-added, or if the asset is removed all
together, which can be detected at the filesystem level instead.

Also fix when status code is non-200 to return as error instead.

Allow the refresh threshold to be specified as arg, though it defaults
to the current 30 seconds.
  • Loading branch information
guangie88 authored May 8, 2020
1 parent ecbce69 commit 635515a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 43 deletions.
9 changes: 7 additions & 2 deletions ghafs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"fmt"
"io/ioutil"
"log"
"net/http"
Expand Down Expand Up @@ -61,7 +62,7 @@ func (r root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
}

func (r root) Lookup(ctx context.Context, name string) (fs.Node, error) {
releases, err := r.mgmt.releases.get()
releases, err := r.mgmt.releases.refresh()

if err != nil {
return nil, err
Expand Down Expand Up @@ -93,7 +94,7 @@ func (t tagDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
}

func (t tagDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
assets, err := t.assets.get()
assets, err := t.assets.refresh()

if err != nil {
return nil, err
Expand Down Expand Up @@ -128,6 +129,10 @@ func (f assetFile) ReadAll(ctx context.Context) ([]byte, error) {
return nil, err
}

if resp.StatusCode != 200 {
return nil, fmt.Errorf("Status Code: %v, message: %v", resp.StatusCode, resp.Status)
}

log.Printf("Asset URL: %v, Content-Length: %v", f.asset.GetURL(), resp.ContentLength)

body, err := ioutil.ReadAll(resp.Body)
Expand Down
16 changes: 9 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/http"
"time"

"github.com/alexflint/go-arg"

Expand All @@ -15,19 +16,20 @@ import (
)

type args struct {
Mountpoint string `arg:"positional,required"`
Owner string `arg:"positional,required"`
Repo string `arg:"positional,required"`
AccessToken string `arg:"--token" help:"GitHub access token for authorization"`
AllowOther bool `arg:"--allow-other" help:"use FUSE allow_other mode (allow_root doesn't work, so not available)"`
Mountpoint string `arg:"positional,required"`
Owner string `arg:"positional,required"`
Repo string `arg:"positional,required"`
AccessToken string `arg:"--token" help:"GitHub access token for authorization"`
AllowOther bool `arg:"--allow-other" help:"use FUSE allow_other mode (allow_root doesn't work, so not available)"`
RefreshThreshold uint32 `arg:"--refresh" default:"30" help:"number of seconds that must elapsed before subsequent assets refresh can occur"`
}

func (args) Description() string {
return "GitHub Release Assets FUSE CLI"
}

func (args) Version() string {
return "ghafs 0.1.1"
return "ghafs 0.1.2"
}

func main() {
Expand All @@ -46,7 +48,7 @@ func main() {
}

client := github.NewClient(tc)
mgmt := makeReleaseMgmt(makeGhContext(ctx, client, args.Owner, args.Repo))
mgmt := makeReleaseMgmt(makeGhContext(ctx, client, args.Owner, args.Repo, time.Duration(args.RefreshThreshold)*time.Second))

mountOptions := []fuse.MountOption{
fuse.FSName("ghafs"),
Expand Down
43 changes: 9 additions & 34 deletions releaseAssets.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ import (
// https://developer.github.com/v3/#pagination
const PageLimit = 100

// LastUpdatedThreshold sets the period threshold to allow the next update to
// the items in seconds
const LastUpdatedThreshold = 30 * time.Second

// GhContext contains the necessary inputs to invoke the Gitub library
type GhContext struct {
ctx context.Context
client *github.Client
owner string
repo string
ctx context.Context
client *github.Client
owner string
repo string
refreshThreshold time.Duration
}

// ReleaseMgmt forms the root level to be able to generate the entire release
Expand Down Expand Up @@ -59,8 +56,8 @@ type AssetsWrap struct {
m sync.Mutex
}

func makeGhContext(ctx context.Context, client *github.Client, owner string, repo string) *GhContext {
return &GhContext{ctx, client, owner, repo}
func makeGhContext(ctx context.Context, client *github.Client, owner string, repo string, refreshThreshold time.Duration) *GhContext {
return &GhContext{ctx, client, owner, repo, refreshThreshold}
}

func makeReleaseMgmt(ghc *GhContext) *ReleaseMgmt {
Expand Down Expand Up @@ -118,7 +115,7 @@ func (w *ReleasesWrap) refreshImpl() (map[string]*Release, error) {
timeNow := time.Now()

// Adhere to the update threshold
if w.lastUpdated.Add(LastUpdatedThreshold).Before(timeNow) {
if w.lastUpdated.Add(w.ghc.refreshThreshold).Before(timeNow) {
releases, err := loopListReleases(w)

if err != nil {
Expand All @@ -141,17 +138,6 @@ func (w *ReleasesWrap) refresh() (map[string]*Release, error) {
return w.refreshImpl()
}

func (w *ReleasesWrap) get() (map[string]*Release, error) {
w.m.Lock()
defer w.m.Unlock()

if len(w.tagReleases) == 0 {
return w.refreshImpl()
}

return w.tagReleases, nil
}

func loopListReleaseAssets(w *AssetsWrap) ([]*github.ReleaseAsset, error) {
var assets []*github.ReleaseAsset

Expand Down Expand Up @@ -183,7 +169,7 @@ func (w *AssetsWrap) refreshImpl() ([]*github.ReleaseAsset, error) {
timeNow := time.Now()

// Adhere to the update threshold
if w.lastUpdated.Add(LastUpdatedThreshold).Before(timeNow) {
if w.lastUpdated.Add(w.ghc.refreshThreshold).Before(timeNow) {
assets, err := loopListReleaseAssets(w)

if err != nil {
Expand All @@ -202,14 +188,3 @@ func (w *AssetsWrap) refresh() ([]*github.ReleaseAsset, error) {
defer w.m.Unlock()
return w.refreshImpl()
}

func (w *AssetsWrap) get() ([]*github.ReleaseAsset, error) {
w.m.Lock()
defer w.m.Unlock()

if len(w.assets) == 0 {
return w.refreshImpl()
}

return w.assets, nil
}

0 comments on commit 635515a

Please sign in to comment.