Skip to content

Commit cd46813

Browse files
committed
merge in main
2 parents 6328899 + 04d202a commit cd46813

File tree

6 files changed

+54
-24
lines changed

6 files changed

+54
-24
lines changed

cli/server.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2360,10 +2360,12 @@ func ConnectToPostgres(ctx context.Context, logger slog.Logger, driver string, d
23602360
return nil, xerrors.Errorf("get postgres version: %w", err)
23612361
}
23622362
defer version.Close()
2363-
if version.Err() != nil {
2364-
return nil, xerrors.Errorf("version select: %w", version.Err())
2365-
}
23662363
if !version.Next() {
2364+
// it's critical we assign to the err variable, otherwise the defer statement
2365+
// that runs db.Close() will not execute it
2366+
if err = version.Err(); err != nil {
2367+
return nil, xerrors.Errorf("no rows returned for version select: %w", err)
2368+
}
23672369
return nil, xerrors.Errorf("no rows returned for version select")
23682370
}
23692371
var versionNum int

coderd/dynamicparameters/render.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,15 @@ func (r *Loader) dynamicRenderer(ctx context.Context, db database.Store, cache *
141141
return nil, xerrors.Errorf("acquire template file: %w", err)
142142
}
143143

144-
var moduleFilesFS fs.FS
144+
var terraformFS fs.FS = templateFS
145+
var moduleFilesFS *files.CloseFS
145146
if r.terraformValues.CachedModuleFiles.Valid {
146147
moduleFilesFS, err = cache.Acquire(fileCtx, r.terraformValues.CachedModuleFiles.UUID)
147148
if err != nil {
148-
cache.Release(r.job.FileID)
149+
templateFS.Close()
149150
return nil, xerrors.Errorf("acquire module files: %w", err)
150151
}
151-
templateFS = files.NewOverlayFS(templateFS, []files.Overlay{{Path: ".terraform/modules", FS: moduleFilesFS}})
152+
terraformFS = files.NewOverlayFS(templateFS, []files.Overlay{{Path: ".terraform/modules", FS: moduleFilesFS}})
152153
}
153154

154155
plan := json.RawMessage("{}")
@@ -158,17 +159,17 @@ func (r *Loader) dynamicRenderer(ctx context.Context, db database.Store, cache *
158159

159160
return &dynamicRenderer{
160161
data: r,
161-
templateFS: templateFS,
162+
templateFS: terraformFS,
162163
db: db,
163164
plan: plan,
164165
ownerErrors: make(map[uuid.UUID]error),
165166
close: func() {
166167
// Up to 2 files are cached, and must be released when rendering is complete.
167168
// TODO: Might be smart to always call release when the context is
168169
// cancelled.
169-
cache.Release(r.job.FileID)
170+
templateFS.Close()
170171
if moduleFilesFS != nil {
171-
cache.Release(r.terraformValues.CachedModuleFiles.UUID)
172+
moduleFilesFS.Close()
172173
}
173174
},
174175
}, nil

coderd/files/cache.go

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,33 @@ type cacheEntry struct {
140140

141141
type fetcher func(context.Context, uuid.UUID) (CacheEntryValue, error)
142142

143+
var _ fs.FS = (*CloseFS)(nil)
144+
145+
// CloseFS is a wrapper around fs.FS that implements io.Closer. The Close()
146+
// method tells the cache to release the fileID. Once all open references are
147+
// closed, the file is removed from the cache.
148+
type CloseFS struct {
149+
fs.FS
150+
151+
close func()
152+
}
153+
154+
func (f *CloseFS) Close() { f.close() }
155+
143156
// Acquire will load the fs.FS for the given file. It guarantees that parallel
144157
// calls for the same fileID will only result in one fetch, and that parallel
145158
// calls for distinct fileIDs will fetch in parallel.
146159
//
147160
// Safety: Every call to Acquire that does not return an error must have a
148161
// matching call to Release.
149-
func (c *Cache) Acquire(ctx context.Context, fileID uuid.UUID) (fs.FS, error) {
150-
// It's important that this `Load` call occurs outside of `prepare`, after the
162+
func (c *Cache) Acquire(ctx context.Context, fileID uuid.UUID) (*CloseFS, error) {
163+
// It's important that this `Load` call occurs outside `prepare`, after the
151164
// mutex has been released, or we would continue to hold the lock until the
152165
// entire file has been fetched, which may be slow, and would prevent other
153166
// files from being fetched in parallel.
154167
it, err := c.prepare(ctx, fileID).Load()
155168
if err != nil {
156-
c.Release(fileID)
169+
c.release(fileID)
157170
return nil, err
158171
}
159172

@@ -163,11 +176,19 @@ func (c *Cache) Acquire(ctx context.Context, fileID uuid.UUID) (fs.FS, error) {
163176
}
164177
// Always check the caller can actually read the file.
165178
if err := c.authz.Authorize(ctx, subject, policy.ActionRead, it.Object); err != nil {
166-
c.Release(fileID)
179+
c.release(fileID)
167180
return nil, err
168181
}
169182

170-
return it.FS, err
183+
var once sync.Once
184+
return &CloseFS{
185+
FS: it.FS,
186+
close: func() {
187+
// sync.Once makes the Close() idempotent, so we can call it
188+
// multiple times without worrying about double-releasing.
189+
once.Do(func() { c.release(fileID) })
190+
},
191+
}, nil
171192
}
172193

173194
func (c *Cache) prepare(ctx context.Context, fileID uuid.UUID) *lazy.ValueWithError[CacheEntryValue] {
@@ -203,9 +224,12 @@ func (c *Cache) prepare(ctx context.Context, fileID uuid.UUID) *lazy.ValueWithEr
203224
return entry.value
204225
}
205226

206-
// Release decrements the reference count for the given fileID, and frees the
227+
// release decrements the reference count for the given fileID, and frees the
207228
// backing data if there are no further references being held.
208-
func (c *Cache) Release(fileID uuid.UUID) {
229+
//
230+
// release should only be called after a successful call to Acquire using the Release()
231+
// method on the returned *CloseFS.
232+
func (c *Cache) release(fileID uuid.UUID) {
209233
c.lock.Lock()
210234
defer c.lock.Unlock()
211235

coderd/files/cache_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestCacheRBAC(t *testing.T) {
7575
require.Equal(t, 0, cache.Count())
7676

7777
// Read the file with a file reader to put it into the cache.
78-
_, err := cache.Acquire(cacheReader, file.ID)
78+
a, err := cache.Acquire(cacheReader, file.ID)
7979
require.NoError(t, err)
8080
require.Equal(t, 1, cache.Count())
8181

@@ -86,12 +86,12 @@ func TestCacheRBAC(t *testing.T) {
8686
require.Equal(t, 1, cache.Count())
8787

8888
// UserReader can
89-
_, err = cache.Acquire(userReader, file.ID)
89+
b, err := cache.Acquire(userReader, file.ID)
9090
require.NoError(t, err)
9191
require.Equal(t, 1, cache.Count())
9292

93-
cache.Release(file.ID)
94-
cache.Release(file.ID)
93+
a.Close()
94+
b.Close()
9595
require.Equal(t, 0, cache.Count())
9696

9797
rec.AssertActorID(t, nobodyID.String(), rec.Pair(policy.ActionRead, file))
@@ -179,13 +179,15 @@ func TestRelease(t *testing.T) {
179179
ids = append(ids, uuid.New())
180180
}
181181

182+
releases := make(map[uuid.UUID][]func(), 0)
182183
// Acquire a bunch of references
183184
batchSize := 10
184185
for openedIdx, id := range ids {
185186
for batchIdx := range batchSize {
186187
it, err := c.Acquire(ctx, id)
187188
require.NoError(t, err)
188-
require.Equal(t, emptyFS, it)
189+
require.Equal(t, emptyFS, it.FS)
190+
releases[id] = append(releases[id], it.Close)
189191

190192
// Each time a new file is opened, the metrics should be updated as so:
191193
opened := openedIdx + 1
@@ -206,7 +208,8 @@ func TestRelease(t *testing.T) {
206208
for closedIdx, id := range ids {
207209
stillOpen := len(ids) - closedIdx
208210
for closingIdx := range batchSize {
209-
c.Release(id)
211+
releases[id][0]()
212+
releases[id] = releases[id][1:]
210213

211214
// Each time a file is released, the metrics should decrement the file refs
212215
require.Equal(t, (stillOpen*batchSize)-(closingIdx+1), promhelp.GaugeValue(t, reg, cachePromMetricName("open_file_refs_current"), nil))

site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ export const CreateWorkspacePageViewExperimental: FC<
393393
</TooltipProvider>
394394
</span>
395395
<FeatureStageBadge
396-
contentType={"early_access"}
396+
contentType={"beta"}
397397
size="sm"
398398
labelText="Dynamic parameters"
399399
/>

site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ const WorkspaceParametersPageExperimental: FC = () => {
237237
</span>
238238
</span>
239239
<FeatureStageBadge
240-
contentType={"early_access"}
240+
contentType={"beta"}
241241
size="sm"
242242
labelText="Dynamic parameters"
243243
/>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy