@@ -31,8 +31,9 @@ import (
31
31
// done so that clients accessing the content stored in RootDir/catalogName have
32
32
// atomic view of the content for a catalog.
33
33
type LocalDirV1 struct {
34
- RootDir string
35
- RootURL * url.URL
34
+ RootDir string
35
+ RootURL * url.URL
36
+ EnableQueryHandler bool
36
37
37
38
m sync.RWMutex
38
39
sf singleflight.Group
@@ -42,7 +43,7 @@ func (s *LocalDirV1) Store(ctx context.Context, catalog string, fsys fs.FS) erro
42
43
s .m .Lock ()
43
44
defer s .m .Unlock ()
44
45
45
- if features . CatalogdFeatureGate . Enabled ( features . APIV1QueryHandler ) {
46
+ if s . EnableQueryHandler {
46
47
return s .storeCatalogFileAndIndex (ctx , catalog , fsys )
47
48
}
48
49
return s .storeCatalogFile (ctx , catalog , fsys )
@@ -88,30 +89,33 @@ func (s *LocalDirV1) storeCatalogFileAndIndex(ctx context.Context, catalog strin
88
89
}
89
90
defer os .Remove (tmpIndexFile .Name ())
90
91
91
- pr , pw := io .Pipe ()
92
- mw := io .MultiWriter (tmpCatalogFile , pw )
92
+ metasChan := make (chan * declcfg.Meta )
93
93
eg , egCtx := errgroup .WithContext (ctx )
94
94
eg .Go (func () error {
95
+ defer close (metasChan )
95
96
if err := declcfg .WalkMetasFS (egCtx , fsys , func (path string , meta * declcfg.Meta , err error ) error {
96
97
if err != nil {
97
98
return err
98
99
}
99
- _ , err = mw .Write (meta .Blob )
100
+ _ , err = tmpCatalogFile .Write (meta .Blob )
100
101
if err != nil {
101
- return pw . CloseWithError ( err )
102
+ return err
102
103
}
104
+ select {
105
+ case <- egCtx .Done ():
106
+ return egCtx .Err ()
107
+ case metasChan <- meta :
108
+ }
109
+
103
110
return nil
104
111
}, declcfg .WithConcurrency (1 )); err != nil {
105
112
return fmt .Errorf ("error walking FBC root: %w" , err )
106
113
}
107
- return pw . CloseWithError ( tmpCatalogFile .Close () )
114
+ return tmpCatalogFile .Close ()
108
115
})
109
116
eg .Go (func () error {
110
- idx , err := newIndex (pr )
117
+ idx , err := newIndex (metasChan )
111
118
if err != nil {
112
- return pr .CloseWithError (err )
113
- }
114
- if err := pr .Close (); err != nil {
115
119
return err
116
120
}
117
121
enc := json .NewEncoder (tmpIndexFile )
@@ -142,7 +146,7 @@ func (s *LocalDirV1) Delete(catalog string) error {
142
146
var errs []error
143
147
errs = append (errs , os .RemoveAll (filepath .Join (s .RootDir , fmt .Sprintf ("%s.jsonl" , catalog ))))
144
148
145
- if features . CatalogdFeatureGate . Enabled ( features . APIV1QueryHandler ) {
149
+ if s . EnableQueryHandler {
146
150
errs = append (errs , os .RemoveAll (filepath .Join (s .RootDir , fmt .Sprintf ("%s.index.json" , catalog ))))
147
151
}
148
152
return errors .Join (errs ... )
@@ -158,7 +162,7 @@ func (s *LocalDirV1) StorageServerHandler() http.Handler {
158
162
v1AllPath := s .RootURL .JoinPath ("{catalog}" , "api" , "v1" , "all" ).Path
159
163
mux .Handle (v1AllPath , s .v1AllHandler ())
160
164
161
- if features . CatalogdFeatureGate . Enabled ( features . APIV1QueryHandler ) {
165
+ if s . EnableQueryHandler {
162
166
v1QueryPath := s .RootURL .JoinPath ("{catalog}" , "api" , "v1" , "query" ).Path
163
167
mux .Handle (v1QueryPath , s .v1QueryHandler ())
164
168
}
@@ -171,16 +175,11 @@ func (s *LocalDirV1) v1AllHandler() http.Handler {
171
175
defer s .m .RUnlock ()
172
176
173
177
catalog := r .PathValue ("catalog" )
178
+ w .Header ().Add ("Content-Type" , "application/jsonl" )
174
179
http .ServeFile (w , r , filepath .Join (s .RootDir , fmt .Sprintf ("%s.jsonl" , catalog )))
175
180
})
176
181
gzHandler := gzhttp .GzipHandler (catalogHandler )
177
-
178
- typeHandler := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
179
- w .Header ().Add ("Content-Type" , "application/jsonl" )
180
- gzHandler .ServeHTTP (w , r )
181
- })
182
-
183
- return newLoggingMiddleware (typeHandler )
182
+ return newLoggingMiddleware (gzHandler )
184
183
}
185
184
186
185
func (s * LocalDirV1 ) v1QueryHandler () http.Handler {
@@ -193,6 +192,13 @@ func (s *LocalDirV1) v1QueryHandler() http.Handler {
193
192
pkg := r .URL .Query ().Get ("package" )
194
193
name := r .URL .Query ().Get ("name" )
195
194
195
+ // If no parameters are provided, return the entire catalog (this is the same as /api/v1/all)
196
+ if schema == "" && pkg == "" && name == "" {
197
+ w .Header ().Add ("Content-Type" , "application/jsonl" )
198
+ http .ServeFile (w , r , filepath .Join (s .RootDir , fmt .Sprintf ("%s.jsonl" , catalog )))
199
+ return
200
+ }
201
+
196
202
catalogFilePath := filepath .Join (s .RootDir , fmt .Sprintf ("%s.jsonl" , catalog ))
197
203
catalogFileStat , err := os .Stat (catalogFilePath )
198
204
if err != nil {
0 commit comments