Skip to content

Commit c6146e0

Browse files
committed
Cache cloud-api response for 24h to improve responsiveness
1 parent 571852e commit c6146e0

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

Diff for: commands/board/list.go

+35-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/arduino/arduino-cli/arduino/discovery"
3333
"github.com/arduino/arduino-cli/arduino/httpclient"
3434
"github.com/arduino/arduino-cli/commands"
35+
"github.com/arduino/arduino-cli/inventory"
3536
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3637
"github.com/pkg/errors"
3738
"github.com/sirupsen/logrus"
@@ -50,6 +51,39 @@ var (
5051
validVidPid = regexp.MustCompile(`0[xX][a-fA-F\d]{4}`)
5152
)
5253

54+
func cachedApiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
55+
var resp []*rpc.BoardListItem
56+
57+
cacheKey := fmt.Sprintf("cache.builder-api.v3/boards/byvid/pid/%s/%s", vid, pid)
58+
if cachedResp := inventory.Store.GetString(cacheKey + ".data"); cachedResp != "" {
59+
ts := inventory.Store.GetTime(cacheKey + ".ts")
60+
if time.Since(ts) < time.Hour*24 {
61+
// Use cached response
62+
if cachedResp == "ErrNotFound" {
63+
return nil, ErrNotFound
64+
}
65+
if err := json.Unmarshal([]byte(cachedResp), &resp); err == nil {
66+
return resp, nil
67+
}
68+
}
69+
}
70+
71+
resp, err := apiByVidPid(vid, pid) // Perform API requrest
72+
73+
if err == ErrNotFound {
74+
inventory.Store.Set(cacheKey+".data", "ErrNotFound")
75+
inventory.Store.Set(cacheKey+".ts", time.Now())
76+
inventory.WriteStore()
77+
} else if err == nil {
78+
if cachedResp, err := json.Marshal(resp); err == nil {
79+
inventory.Store.Set(cacheKey+".data", string(cachedResp))
80+
inventory.Store.Set(cacheKey+".ts", time.Now())
81+
inventory.WriteStore()
82+
}
83+
}
84+
return resp, err
85+
}
86+
5387
func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
5488
// ensure vid and pid are valid before hitting the API
5589
if !validVidPid.MatchString(vid) {
@@ -116,7 +150,7 @@ func identifyViaCloudAPI(port *discovery.Port) ([]*rpc.BoardListItem, error) {
116150
}
117151

118152
logrus.Debug("Querying builder API for board identification...")
119-
return apiByVidPid(id.Get("vid"), id.Get("pid"))
153+
return cachedApiByVidPid(id.Get("vid"), id.Get("pid"))
120154
}
121155

122156
// identify returns a list of boards checking first the installed platforms or the Cloud API

Diff for: inventory/inventory.go

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"os"
2121
"path/filepath"
22+
"sync"
2223

2324
"github.com/arduino/arduino-cli/i18n"
2425
"github.com/gofrs/uuid"
@@ -77,9 +78,14 @@ func generateInstallationData() error {
7778
return nil
7879
}
7980

81+
var writeStoreMux sync.Mutex
82+
8083
// WriteStore writes the current information from Store to configFilePath.
8184
// Returns err if it fails.
8285
func WriteStore() error {
86+
writeStoreMux.Lock()
87+
defer writeStoreMux.Unlock()
88+
8389
configPath := filepath.Dir(configFilePath)
8490

8591
// Create config dir if not present,

0 commit comments

Comments
 (0)