Cache workspaces based on full path. (#1326)

As it stands, we recompute the workspace for the current directory
potentially many times during some CLI operations, most notably
`stack ls`. These changes add a simple cache based on the complete path
passed to `NewFrom`, and eliminate some lagginess in `stack ls` when
there are multiple stacks.

Another option is to calculate the current workspace once in the CLI and
then fetch it as necessary.
This commit is contained in:
Pat Gavlin 2018-05-07 15:35:58 -07:00 committed by GitHub
parent d1b49d25f8
commit a5e92b9497
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -11,6 +11,7 @@ import (
"os/user"
"path/filepath"
"strings"
"sync"
"github.com/pkg/errors"
"github.com/pulumi/pulumi/pkg/resource/config"
@ -32,6 +33,26 @@ type projectWorkspace struct {
repo *Repository // the repo this workspace is associated with.
}
var cache = make(map[string]W)
var cacheMutex sync.RWMutex
func loadFromCache(key string) (W, bool) {
cacheMutex.RLock()
defer cacheMutex.RUnlock()
w, ok := cache[key]
return w, ok
}
func upsertIntoCache(key string, w W) {
contract.Require(w != nil, "w")
cacheMutex.Lock()
defer cacheMutex.Unlock()
cache[key] = w
}
// New creates a new workspace using the current working directory.
func New() (W, error) {
cwd, err := os.Getwd()
@ -44,6 +65,16 @@ func New() (W, error) {
// NewFrom creates a new Pulumi workspace in the given directory. Requires a Pulumi.yaml file be present in the
// folder hierarchy between dir and the .pulumi folder.
func NewFrom(dir string) (W, error) {
absDir, err := filepath.Abs(dir)
if err != nil {
return nil, err
}
dir = absDir
if w, ok := loadFromCache(dir); ok {
return w, nil
}
repo, err := GetRepository(dir)
if err == ErrNoRepository {
repo = nil
@ -63,7 +94,7 @@ func NewFrom(dir string) (W, error) {
return nil, err
}
w := projectWorkspace{
w := &projectWorkspace{
name: proj.Name,
project: path,
repo: repo,
@ -78,7 +109,8 @@ func NewFrom(dir string) (W, error) {
w.settings.ConfigDeprecated = make(map[tokens.QName]config.Map)
}
return &w, nil
upsertIntoCache(dir, w)
return w, nil
}
func (pw *projectWorkspace) Settings() *Settings {