-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: invalidate persisted cache #635
Changes from all commits
74ac419
de58d32
46f6ad0
63b5ca5
4744822
924c518
d2d0c51
6f6d519
b5179aa
65e8112
b03b1fe
dcebbbe
d65a7a0
1c76bbb
80905b4
43f1ddc
72293eb
ad6c284
b175226
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -174,18 +174,17 @@ func (w *Workspace) ScanWorkspace(ctx context.Context) { | |
|
||
// ChangeWorkspaceFolders clears the "Removed" folders, adds the "New" folders, | ||
// and starts an automatic scan if auto-scans are enabled. | ||
func (w *Workspace) ChangeWorkspaceFolders(ctx context.Context, params types.DidChangeWorkspaceFoldersParams) { | ||
func (w *Workspace) ChangeWorkspaceFolders(params types.DidChangeWorkspaceFoldersParams) []*Folder { | ||
for _, folder := range params.Event.Removed { | ||
w.RemoveFolder(uri.PathFromUri(folder.Uri)) | ||
} | ||
|
||
var changedWorkspaceFolders []*Folder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is to avoid triggering scan before initializing the persister. |
||
for _, folder := range params.Event.Added { | ||
f := NewFolder(w.c, uri.PathFromUri(folder.Uri), folder.Name, w.scanner, w.hoverService, w.scanNotifier, w.notifier, w.scanPersister) | ||
w.AddFolder(f) | ||
if config.CurrentConfig().IsAutoScanEnabled() { | ||
f.ScanFolder(ctx) | ||
} | ||
changedWorkspaceFolders = append(changedWorkspaceFolders, f) | ||
} | ||
return changedWorkspaceFolders | ||
} | ||
|
||
func (w *Workspace) Clear() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,7 +73,7 @@ func Test_TrustFoldersAndScan_shouldAddFoldersToTrustedFoldersAndTriggerScan(t * | |
}, time.Second, time.Millisecond, "scanner should be called after trust is granted") | ||
} | ||
|
||
func Test_AddAndRemoveFoldersAndTriggerScan(t *testing.T) { | ||
func Test_AddAndRemoveFoldersAndReturnFolderList(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where do you test the extracted trigger scan path now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in server_test Test_workspaceDidChangeWorkspaceFolders_shouldProcessChanges it checks if folder.Scanned() |
||
c := testutil.UnitTest(t) | ||
const trustedDummy = "trustedDummy" | ||
const untrustedDummy = "untrustedDummy" | ||
|
@@ -101,14 +101,10 @@ func Test_AddAndRemoveFoldersAndTriggerScan(t *testing.T) { | |
}, | ||
}} | ||
|
||
w.ChangeWorkspaceFolders(context.Background(), params) | ||
|
||
folderList := w.ChangeWorkspaceFolders(params) | ||
assert.Nil(t, w.GetFolderContaining(toBeRemoved)) | ||
|
||
// one call for one trusted folder | ||
assert.Eventually(t, func() bool { | ||
return sc.Calls() == 1 | ||
}, time.Second, time.Millisecond, "scanner should be called after trust is granted") | ||
assert.Len(t, folderList, 2) | ||
} | ||
|
||
func Test_Get(t *testing.T) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* © 2024 Snyk Limited | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package persistence | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"time" | ||
|
||
"github.com/snyk/snyk-ls/domain/snyk" | ||
"github.com/snyk/snyk-ls/internal/product" | ||
"github.com/snyk/snyk-ls/internal/vcs" | ||
) | ||
|
||
func (g *GitPersistenceProvider) persistToDisk(cacheDir string, folderHashedPath hashedFolderPath, commitHash string, p product.Product, inputToCache []snyk.Issue) error { | ||
filePath := getLocalFilePath(cacheDir, folderHashedPath, commitHash, p) | ||
data, err := json.Marshal(inputToCache) | ||
if err != nil { | ||
return err | ||
} | ||
g.logger.Debug().Msg("persisting scan results in file " + filePath) | ||
return os.WriteFile(filePath, data, 0644) | ||
} | ||
|
||
func (g *GitPersistenceProvider) getPersistedFiles(cacheDir string) (persistedFiles []string, err error) { | ||
entries, err := os.ReadDir(cacheDir) | ||
if err != nil { | ||
return persistedFiles, err | ||
} | ||
|
||
for _, entry := range entries { | ||
fileName := entry.Name() | ||
if !strings.HasSuffix(fileName, ".json") { | ||
continue | ||
} | ||
s := strings.Split(fileName, ".") | ||
if len(s) == 5 { | ||
persistedFiles = append(persistedFiles, fileName) | ||
} | ||
} | ||
return persistedFiles, nil | ||
} | ||
|
||
func (g *GitPersistenceProvider) ensureCacheDirExists(folderPath string) (string, error) { | ||
g.logger.Debug().Msg("attempting to determine .git folder path") | ||
cacheDir, err := g.snykCacheDir(folderPath) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
if _, err = os.Stat(cacheDir); os.IsNotExist(err) { | ||
err = os.Mkdir(cacheDir, 0700) | ||
if err != nil { | ||
return "", err | ||
} | ||
} | ||
return cacheDir, nil | ||
} | ||
|
||
func (g *GitPersistenceProvider) snykCacheDir(folderPath string) (string, error) { | ||
gitFolder, err := vcs.GitRepoFolderPath(g.logger, folderPath) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
cacheDir := filepath.Join(gitFolder, CacheFolder) | ||
|
||
return cacheDir, nil | ||
} | ||
|
||
func getLocalFilePath(cacheDir string, folderPathHash hashedFolderPath, commitHash string, p product.Product) string { | ||
productName := p.ToProductCodename() | ||
return filepath.Join(cacheDir, fmt.Sprintf("%s.%s.%s.%s.json", SchemaVersion, folderPathHash, commitHash, productName)) | ||
} | ||
|
||
func (g *GitPersistenceProvider) snapshotExistsOnDisk(cacheDir string, hash hashedFolderPath, commitHash string, p product.Product) bool { | ||
filePath := getLocalFilePath(cacheDir, hash, commitHash, p) | ||
if _, err := os.Stat(filePath); os.IsNotExist(err) { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
func (g *GitPersistenceProvider) deleteFile(fullPath string) error { | ||
g.logger.Debug().Msgf("deleting cached scan file %s", fullPath) | ||
err := os.Remove(fullPath) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (g *GitPersistenceProvider) isExpired(schemaVersion string, fullFilePath string) bool { | ||
// if file has incorrect schema we just delete it | ||
if schemaVersion != SchemaVersion { | ||
return true | ||
} | ||
|
||
// Check last modified date | ||
fileInfo, err := os.Stat(fullFilePath) | ||
if err != nil { | ||
g.logger.Error().Err(err).Msg("couldn't stat file " + fullFilePath) | ||
return true | ||
} | ||
|
||
// If elapsed time is > ExpirationInSeconds, delete the file | ||
if time.Since(fileInfo.ModTime()) > time.Duration(ExpirationInSeconds)*time.Second { | ||
return true | ||
} | ||
|
||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i moved the persister init logic to the folder handlers
This refactoring here was to make sure that the persister is initialized before a new f.ScanFolder is triggered for the new added folder