MCPcopy Index your code
hub / github.com/coder/coder / Acquire

Method Acquire

coderd/files/cache.go:148–204  ·  view source on GitHub ↗

Acquire will load the fs.FS for the given file. It guarantees that parallel calls for the same fileID will only result in one fetch, and that parallel calls for distinct fileIDs will fetch in parallel. Safety: Every call to Acquire that does not return an error must call close on the returned value

(ctx context.Context, db database.Store, fileID uuid.UUID)

Source from the content-addressed store, hash-verified

146// Safety: Every call to Acquire that does not return an error must call close
147// on the returned value when it is done being used.
148func (c *Cache) Acquire(ctx context.Context, db database.Store, fileID uuid.UUID) (*CloseFS, error) {
149 // It's important that this `Load` call occurs outside `prepare`, after the
150 // mutex has been released, or we would continue to hold the lock until the
151 // entire file has been fetched, which may be slow, and would prevent other
152 // files from being fetched in parallel.
153 e := c.prepare(db, fileID)
154 ev, err := e.value.Load()
155 if err != nil {
156 c.lock.Lock()
157 defer c.lock.Unlock()
158 e.close()
159 e.purge()
160 return nil, err
161 }
162
163 cleanup := func() {
164 c.lock.Lock()
165 defer c.lock.Unlock()
166 e.close()
167 }
168
169 // We always run the fetch under a system context and actor, so we need to
170 // check the caller's context (including the actor) manually before returning.
171
172 // Check if the caller's context was canceled. Even though `Authorize` takes
173 // a context, we still check it manually first because none of our mock
174 // database implementations check for context cancellation.
175 if err := ctx.Err(); err != nil {
176 cleanup()
177 return nil, err
178 }
179
180 // Check that the caller is authorized to access the file
181 subject, ok := dbauthz.ActorFromContext(ctx)
182 if !ok {
183 cleanup()
184 return nil, dbauthz.ErrNoActor
185 }
186 if err := c.authz.Authorize(ctx, subject, policy.ActionRead, ev.Object); err != nil {
187 cleanup()
188 return nil, err
189 }
190
191 var closeOnce sync.Once
192 return &CloseFS{
193 FS: ev.FS,
194 close: func() {
195 // sync.Once makes the Close() idempotent, so we can call it
196 // multiple times without worrying about double-releasing.
197 closeOnce.Do(func() {
198 c.lock.Lock()
199 defer c.lock.Unlock()
200 e.close()
201 })
202 },
203 }, nil
204}
205

Callers

nothing calls this directly

Calls 11

prepareMethod · 0.95
ActorFromContextFunction · 0.92
cleanupFunction · 0.85
purgeMethod · 0.80
ErrMethod · 0.80
closeMethod · 0.65
AuthorizeMethod · 0.65
DoMethod · 0.65
LoadMethod · 0.45
LockMethod · 0.45
UnlockMethod · 0.45

Tested by

no test coverage detected