Skip to content

Commit 86e7b3e

Browse files
committed
Speed up Artifactory queries
- Get the directory listing in one query. - Run the manifest queries in parallel. - Cache list. - Cache manifests. - Seed cache on startup.
1 parent 763f0f5 commit 86e7b3e

File tree

10 files changed

+246
-93
lines changed

10 files changed

+246
-93
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,5 @@ update the changelog as part of your PR.
170170

171171
- Bulk add.
172172
- Bulk add from one Artifactory repository to another (or to itself).
173+
- Optional database to speed up queries.
173174
- Progress indicators when adding/removing extensions.

api/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func (api *API) extensionQuery(rw http.ResponseWriter, r *http.Request) {
197197
return
198198
}
199199

200-
api.Logger.Debug(ctx, "Got extensions for filter",
200+
api.Logger.Debug(ctx, "got extensions for filter",
201201
slog.F("filter", filter),
202202
slog.F("count", count))
203203

cli/add.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func add() *cobra.Command {
4242
logger = logger.Leveled(slog.LevelDebug)
4343
}
4444

45-
store, err := storage.NewStorage(&storage.Options{
45+
store, err := storage.NewStorage(ctx, &storage.Options{
4646
Artifactory: artifactory,
4747
ExtDir: extdir,
4848
Logger: logger,
@@ -85,7 +85,7 @@ func add() *cobra.Command {
8585
}
8686

8787
depCount := len(deps)
88-
id := storage.ExtensionID(manifest)
88+
id := storage.ExtensionIDFromManifest(manifest)
8989
summary := []string{
9090
fmt.Sprintf("Unpacked %s to %s", id, location),
9191
fmt.Sprintf("%s has %s", id, util.Plural(depCount, "dependency", "dependencies")),

cli/remove.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func remove() *cobra.Command {
4646
logger = logger.Leveled(slog.LevelDebug)
4747
}
4848

49-
store, err := storage.NewStorage(&storage.Options{
49+
store, err := storage.NewStorage(ctx, &storage.Options{
5050
Artifactory: artifactory,
5151
ExtDir: extdir,
5252
Logger: logger,

cli/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func server() *cobra.Command {
5252
logger = logger.Leveled(slog.LevelDebug)
5353
}
5454

55-
store, err := storage.NewStorage(&storage.Options{
55+
store, err := storage.NewStorage(ctx, &storage.Options{
5656
Artifactory: artifactory,
5757
ExtDir: extdir,
5858
Logger: logger,
@@ -73,7 +73,7 @@ func server() *cobra.Command {
7373
if !valid {
7474
return xerrors.New("must be listening on tcp")
7575
}
76-
logger.Info(ctx, "Starting API server", slog.F("address", tcpAddr))
76+
logger.Info(ctx, "Started API server", slog.F("address", tcpAddr))
7777

7878
// Always no database for now.
7979
database := &database.NoDB{

database/nodb.go

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ package database
22

33
import (
44
"context"
5+
"errors"
56
"net/url"
67
"os"
78
"path"
89
"sort"
910
"strings"
11+
"time"
1012

1113
"github.com/lithammer/fuzzysearch/fuzzy"
14+
"golang.org/x/sync/errgroup"
1215

1316
"cdr.dev/slog"
1417

@@ -52,6 +55,7 @@ func (db *NoDB) GetExtensionAssetPath(ctx context.Context, asset *Asset, baseURL
5255
func (db *NoDB) GetExtensions(ctx context.Context, filter Filter, flags Flag, baseURL url.URL) ([]*Extension, int, error) {
5356
vscodeExts := []*noDBExtension{}
5457

58+
start := time.Now()
5559
err := db.Storage.WalkExtensions(ctx, func(manifest *storage.VSIXManifest, versions []string) error {
5660
vscodeExt := convertManifestToExtension(manifest)
5761
if matched, distances := getMatches(vscodeExt, filter); matched {
@@ -66,9 +70,22 @@ func (db *NoDB) GetExtensions(ctx context.Context, filter Filter, flags Flag, ba
6670
}
6771

6872
total := len(vscodeExts)
73+
db.Logger.Debug(ctx, "walk extensions", slog.F("took", time.Since(start)), slog.F("count", total))
74+
75+
start = time.Now()
6976
sortExtensions(vscodeExts, filter)
77+
db.Logger.Debug(ctx, "sort extensions", slog.F("took", time.Since(start)))
78+
79+
start = time.Now()
7080
vscodeExts = paginateExtensions(vscodeExts, filter)
71-
db.handleFlags(ctx, vscodeExts, flags, baseURL)
81+
db.Logger.Debug(ctx, "paginate extensions", slog.F("took", time.Since(start)))
82+
83+
start = time.Now()
84+
err = db.handleFlags(ctx, vscodeExts, flags, baseURL)
85+
if err != nil {
86+
return nil, 0, err
87+
}
88+
db.Logger.Debug(ctx, "handle flags", slog.F("took", time.Since(start)))
7289

7390
convertedExts := []*Extension{}
7491
for _, ext := range vscodeExts {
@@ -250,7 +267,8 @@ func paginateExtensions(exts []*noDBExtension, filter Filter) []*noDBExtension {
250267
return exts[start:end]
251268
}
252269

253-
func (db *NoDB) handleFlags(ctx context.Context, exts []*noDBExtension, flags Flag, baseURL url.URL) {
270+
func (db *NoDB) handleFlags(ctx context.Context, exts []*noDBExtension, flags Flag, baseURL url.URL) error {
271+
var eg errgroup.Group
254272
for _, ext := range exts {
255273
// Files, properties, and asset URIs are part of versions so if they are set
256274
// assume we also want to include versions.
@@ -259,7 +277,17 @@ func (db *NoDB) handleFlags(ctx context.Context, exts []*noDBExtension, flags Fl
259277
flags&IncludeVersionProperties != 0 ||
260278
flags&IncludeLatestVersionOnly != 0 ||
261279
flags&IncludeAssetURI != 0 {
262-
ext.Versions = db.getVersions(ctx, ext, flags, baseURL)
280+
// Depending on the storage mechanism fetching a manifest can be very
281+
// slow so run the requests in parallel.
282+
ext := ext
283+
eg.Go(func() error {
284+
versions, err := db.getVersions(ctx, ext, flags, baseURL)
285+
if err != nil {
286+
return err
287+
}
288+
ext.Versions = versions
289+
return nil
290+
})
263291
}
264292

265293
// TODO: This does not seem to be included in any interfaces so no idea
@@ -279,9 +307,10 @@ func (db *NoDB) handleFlags(ctx context.Context, exts []*noDBExtension, flags Fl
279307
// if flags&IncludeStatistics != 0 {}
280308
// if flags&Unpublished != 0 {}
281309
}
310+
return eg.Wait()
282311
}
283312

284-
func (db *NoDB) getVersions(ctx context.Context, ext *noDBExtension, flags Flag, baseURL url.URL) []ExtVersion {
313+
func (db *NoDB) getVersions(ctx context.Context, ext *noDBExtension, flags Flag, baseURL url.URL) ([]ExtVersion, error) {
285314
ctx = slog.With(ctx,
286315
slog.F("publisher", ext.Publisher.PublisherName),
287316
slog.F("extension", ext.Name))
@@ -295,8 +324,10 @@ func (db *NoDB) getVersions(ctx context.Context, ext *noDBExtension, flags Flag,
295324
for _, versionStr := range versionStrs {
296325
ctx := slog.With(ctx, slog.F("version", versionStr))
297326
manifest, err := db.Storage.Manifest(ctx, ext.Publisher.PublisherName, ext.Name, versionStr)
298-
if err != nil {
299-
db.Logger.Error(ctx, "Unable to parse version manifest", slog.Error(err))
327+
if err != nil && errors.Is(err, context.Canceled) {
328+
return nil, err
329+
} else if err != nil {
330+
db.Logger.Error(ctx, "Unable to read version manifest", slog.Error(err))
300331
continue
301332
}
302333

@@ -354,7 +385,7 @@ func (db *NoDB) getVersions(ctx context.Context, ext *noDBExtension, flags Flag,
354385

355386
versions = append(versions, version)
356387
}
357-
return versions
388+
return versions, nil
358389
}
359390

360391
// noDBExtension adds some properties for internally filtering.

0 commit comments

Comments
 (0)