From ba562229f237852ab087e0c838b1ef3fb8a5a41c Mon Sep 17 00:00:00 2001 From: Miguel Mota Date: Fri, 20 Apr 2018 14:53:18 -0700 Subject: [PATCH] hard cache Former-commit-id: cedd3a565c7f8a499500bc9445fa44a70cb1a895 [formerly cedd3a565c7f8a499500bc9445fa44a70cb1a895 [formerly e24f0272bac7c798381be585a83d40817c1648f6 [formerly 878ef53221b0b8614fc850546e78fa1ff7295979]]] Former-commit-id: 7f8ee8eec60d4fb0ebb73769c3d097fc39ccc2ec Former-commit-id: 250b98302b7454528741417201b3ecf389647016 [formerly 9b8aa21f0900d9549c217d78c6c25cf4c9374b6f] Former-commit-id: adfebc801b86ee03021eab460df6fa73915f666b --- Gopkg.lock | 8 +++++++- Gopkg.toml | 4 ++++ cointop/actions.go | 47 ++++++++++++++++++++++++++++++++++++++++++++ cointop/cache.go | 33 +++++++++++++++++++++++++++++++ cointop/cointop.go | 12 +++++++++++ cointop/config.go | 15 +------------- cointop/debug.go | 10 ++++++++++ cointop/list.go | 45 +++++++++++++++++++++++++++++++++++++++--- cointop/shortcuts.go | 42 --------------------------------------- cointop/util.go | 30 +++++++++++++++++++++++++++- 10 files changed, 185 insertions(+), 61 deletions(-) create mode 100644 cointop/actions.go create mode 100644 cointop/cache.go create mode 100644 cointop/debug.go diff --git a/Gopkg.lock b/Gopkg.lock index f2d2f6c..bae54ed 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -61,6 +61,12 @@ packages = ["."] revision = "3e24a7b6661e09b87a9f49d693034219f81602fa" +[[projects]] + name = "github.com/patrickmn/go-cache" + packages = ["."] + revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0" + version = "v2.1.0" + [[projects]] branch = "master" name = "go4.org" @@ -85,6 +91,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "8949d0a22e4e0c000e6c21a69eac0b147496e2b65320a4f5a63f966d54524473" + inputs-digest = "a379741758ab87277a2159f17b7f9741ece58d2f94b1c959191189f9100a6f29" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index f10fb78..5218fdc 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -48,3 +48,7 @@ [prune] go-tests = true unused-packages = true + +[[constraint]] + name = "github.com/patrickmn/go-cache" + version = "2.1.0" diff --git a/cointop/actions.go b/cointop/actions.go new file mode 100644 index 0000000..1aefdae --- /dev/null +++ b/cointop/actions.go @@ -0,0 +1,47 @@ +package cointop + +func actionsMap() map[string]bool { + return map[string]bool{ + "first_page": true, + "help": true, + "last_page": true, + "move_to_page_first_row": true, + "move_to_page_last_row": true, + "move_to_page_visible_first_row": true, + "move_to_page_visible_last_row": true, + "move_to_page_visible_middle_row": true, + "move_up": true, + "move_down": true, + "next_page": true, + "open_link": true, + "page_down": true, + "page_up": true, + "previous_page": true, + "quit": true, + "refresh": true, + "sort_column_1h_change": true, + "sort_column_24h_change": true, + "sort_column_24h_volume": true, + "sort_column_7d_change": true, + "sort_column_asc": true, + "sort_column_available_supply": true, + "sort_column_desc": true, + "sort_column_last_updated": true, + "sort_column_market_cap": true, + "sort_column_name": true, + "sort_column_price": true, + "sort_column_rank": true, + "sort_column_symbol": true, + "sort_column_total_supply": true, + "sort_left_column": true, + "sort_right_column": true, + "toggle_row_chart": true, + "open_search": true, + "toggle_favorite": true, + "toggle_show_favorites": true, + } +} + +func (ct *Cointop) actionExists(action string) bool { + return ct.actionsmap[action] +} diff --git a/cointop/cache.go b/cointop/cache.go new file mode 100644 index 0000000..16a000b --- /dev/null +++ b/cointop/cache.go @@ -0,0 +1,33 @@ +package cointop + +import ( + "encoding/json" + "fmt" + "io/ioutil" +) + +func (ct *Cointop) writeCache(data []byte) error { + path := ct.cachePath() + err := ioutil.WriteFile(path, data, 0644) + if err != nil { + return err + } + return nil +} + +func (ct *Cointop) readCache(i interface{}) (interface{}, bool, error) { + path := ct.cachePath() + b, err := ioutil.ReadFile(path) + if err != nil { + return nil, false, err + } + err = json.Unmarshal(b, &i) + if err != nil { + return nil, false, err + } + return i, true, nil +} + +func (ct *Cointop) cachePath() string { + return fmt.Sprintf("%v%v", ct.configDirPath(), "/.cache") +} diff --git a/cointop/cointop.go b/cointop/cointop.go index fd44e0e..d42a964 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -2,6 +2,7 @@ package cointop import ( "log" + "os" "sync" "time" @@ -9,6 +10,7 @@ import ( "github.com/miguelmota/cointop/pkg/api" "github.com/miguelmota/cointop/pkg/table" "github.com/miguelmota/cointop/pkg/termui" + "github.com/patrickmn/go-cache" ) // Cointop cointop @@ -34,16 +36,23 @@ type Cointop struct { forcerefresh chan bool selectedcoin *coin maxtablewidth int + actionsmap map[string]bool shortcutkeys map[string]string config config // toml config searchfield *gocui.View favorites map[string]bool filterByFavorites bool savemux sync.Mutex + cache *cache.Cache + debug bool } // Run runs cointop func Run() { + var debug bool + if os.Getenv("DEBUG") != "" { + debug = true + } ct := Cointop{ api: api.NewCMC(), refreshticker: time.NewTicker(1 * time.Minute), @@ -53,8 +62,11 @@ func Run() { perpage: 100, forcerefresh: make(chan bool), maxtablewidth: 175, + actionsmap: actionsMap(), shortcutkeys: defaultShortcuts(), favorites: map[string]bool{}, + cache: cache.New(1*time.Minute, 2*time.Minute), + debug: debug, } err := ct.setupConfig() if err != nil { diff --git a/cointop/config.go b/cointop/config.go index 97f3014..7100d81 100644 --- a/cointop/config.go +++ b/cointop/config.go @@ -5,7 +5,6 @@ import ( "fmt" "io/ioutil" "os" - "runtime" "strings" "github.com/BurntSushi/toml" @@ -152,11 +151,10 @@ func (ct *Cointop) configToToml() ([]byte, error) { } func (ct *Cointop) loadShortcutsFromConfig() error { - actionsmap := actionsMap() for k, ifc := range ct.config.Shortcuts { v, ok := ifc.(string) if ok { - if !actionsmap[v] { + if !ct.actionExists(v) { continue } if ct.shortcutkeys[k] == "" { @@ -167,14 +165,3 @@ func (ct *Cointop) loadShortcutsFromConfig() error { } return nil } - -func userHomeDir() string { - if runtime.GOOS == "windows" { - home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") - if home == "" { - home = os.Getenv("USERPROFILE") - } - return home - } - return os.Getenv("HOME") -} diff --git a/cointop/debug.go b/cointop/debug.go new file mode 100644 index 0000000..87be06a --- /dev/null +++ b/cointop/debug.go @@ -0,0 +1,10 @@ +package cointop + +import "log" + +func (ct *Cointop) debuglog(s string) { + if ct.debug { + // TODO: do status debug bar + log.Println(s) + } +} diff --git a/cointop/list.go b/cointop/list.go index 7dff707..af56d3a 100644 --- a/cointop/list.go +++ b/cointop/list.go @@ -1,10 +1,49 @@ package cointop +import ( + "encoding/json" + "time" + + types "github.com/miguelmota/cointop/pkg/api/types" +) + func (ct *Cointop) updateCoins() error { list := []*coin{} - allcoinsmap, err := ct.api.GetAllCoinData() - if err != nil { - return err + cachekey := "allcoinsmap" + + var err error + var allcoinsmap map[string]types.Coin + cached, found := ct.cache.Get(cachekey) + if found { + // cache hit + allcoinsmap, _ = cached.(map[string]types.Coin) + ct.debuglog("soft cache hit") + } else { + ifc, ok, _ := ct.readCache(&allcoinsmap) + if ok { + // hard cache hit + if ifc != nil { + ct.debuglog("hard cache hit") + } + } + } + + // cache miss + if allcoinsmap == nil { + ct.debuglog("cache miss") + allcoinsmap, err = ct.api.GetAllCoinData() + if err != nil { + return err + } + ct.cache.Set(cachekey, allcoinsmap, 10*time.Second) + b, err := json.Marshal(allcoinsmap) + if err != nil { + return err + } + err = ct.writeCache(b) + if err != nil { + return err + } } if len(ct.allcoinsmap) == 0 { diff --git a/cointop/shortcuts.go b/cointop/shortcuts.go index 576a20b..a38872a 100644 --- a/cointop/shortcuts.go +++ b/cointop/shortcuts.go @@ -1,47 +1,5 @@ package cointop -func actionsMap() map[string]bool { - return map[string]bool{ - "first_page": true, - "help": true, - "last_page": true, - "move_to_page_first_row": true, - "move_to_page_last_row": true, - "move_to_page_visible_first_row": true, - "move_to_page_visible_last_row": true, - "move_to_page_visible_middle_row": true, - "move_up": true, - "move_down": true, - "next_page": true, - "open_link": true, - "page_down": true, - "page_up": true, - "previous_page": true, - "quit": true, - "refresh": true, - "sort_column_1h_change": true, - "sort_column_24h_change": true, - "sort_column_24h_volume": true, - "sort_column_7d_change": true, - "sort_column_asc": true, - "sort_column_available_supply": true, - "sort_column_desc": true, - "sort_column_last_updated": true, - "sort_column_market_cap": true, - "sort_column_name": true, - "sort_column_price": true, - "sort_column_rank": true, - "sort_column_symbol": true, - "sort_column_total_supply": true, - "sort_left_column": true, - "sort_right_column": true, - "toggle_row_chart": true, - "open_search": true, - "toggle_favorite": true, - "toggle_show_favorites": true, - } -} - func defaultShortcuts() map[string]string { return map[string]string{ "up": "move_up", diff --git a/cointop/util.go b/cointop/util.go index 2186d0d..0d00b64 100644 --- a/cointop/util.go +++ b/cointop/util.go @@ -1,8 +1,36 @@ package cointop -import "github.com/miguelmota/cointop/pkg/open" +import ( + "bytes" + "encoding/gob" + "os" + "runtime" + + "github.com/miguelmota/cointop/pkg/open" +) func (ct *Cointop) openLink() error { open.URL(ct.rowLink()) return nil } + +func getBytes(key interface{}) ([]byte, error) { + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + err := enc.Encode(key) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func userHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } + return os.Getenv("HOME") +}