Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4dfdd4f

Browse files
committed
Add closed state to DBCache for safe shutdown
Introduce `closed` state to the DBCache to ensure operations such as Verifying and Signing are safely terminated when the cache is closed. This update prevents resource access and ensures proper shutdown sequences, enhancing system reliability.
1 parent 430e1c2 commit 4dfdd4f

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

coderd/cryptokeys/dbkeycache.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type DBCache struct {
3131
timer *quartz.Timer
3232
// invalidateAt is the time at which the keys cache should be invalidated.
3333
invalidateAt time.Time
34+
closed bool
3435
}
3536

3637
type DBCacheOption func(*DBCache)
@@ -64,8 +65,13 @@ func NewDBCache(logger slog.Logger, db database.Store, feature database.CryptoKe
6465
// it is neither deleted nor has breached its deletion date. It should only be
6566
// used for verifying or decrypting payloads. To sign/encrypt call Signing.
6667
func (d *DBCache) Verifying(ctx context.Context, sequence int32) (codersdk.CryptoKey, error) {
67-
now := d.clock.Now()
6868
d.keysMu.RLock()
69+
if d.closed {
70+
d.keysMu.RUnlock()
71+
return codersdk.CryptoKey{}, ErrClosed
72+
}
73+
74+
now := d.clock.Now()
6975
key, ok := d.keys[sequence]
7076
d.keysMu.RUnlock()
7177
if ok {
@@ -97,6 +103,12 @@ func (d *DBCache) Verifying(ctx context.Context, sequence int32) (codersdk.Crypt
97103
// both past its start time and before its deletion time.
98104
func (d *DBCache) Signing(ctx context.Context) (codersdk.CryptoKey, error) {
99105
d.keysMu.RLock()
106+
107+
if d.closed {
108+
d.keysMu.RUnlock()
109+
return codersdk.CryptoKey{}, ErrClosed
110+
}
111+
100112
latest := d.latestKey
101113
d.keysMu.RUnlock()
102114

@@ -185,5 +197,11 @@ func (d *DBCache) newTimer() *quartz.Timer {
185197
func (d *DBCache) Close() {
186198
d.keysMu.Lock()
187199
defer d.keysMu.Unlock()
200+
201+
if d.closed {
202+
return
203+
}
204+
188205
d.timer.Stop()
206+
d.closed = true
189207
}

coderd/cryptokeys/dbkeycache_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,40 @@ func TestDBKeyCache(t *testing.T) {
104104
require.NoError(t, err)
105105
require.Equal(t, db2sdk.CryptoKey(expectedKey), got)
106106
})
107+
108+
t.Run("Closed", func(t *testing.T) {
109+
t.Parallel()
110+
111+
var (
112+
db, _ = dbtestutil.NewDB(t)
113+
clock = quartz.NewMock(t)
114+
ctx = testutil.Context(t, testutil.WaitShort)
115+
logger = slogtest.Make(t, nil)
116+
)
117+
118+
expectedKey := dbgen.CryptoKey(t, db, database.CryptoKey{
119+
Feature: database.CryptoKeyFeatureWorkspaceApps,
120+
Sequence: 10,
121+
StartsAt: clock.Now(),
122+
})
123+
124+
k := cryptokeys.NewDBCache(logger, db, database.CryptoKeyFeatureWorkspaceApps, cryptokeys.WithDBCacheClock(clock))
125+
defer k.Close()
126+
127+
got, err := k.Signing(ctx)
128+
require.NoError(t, err)
129+
require.Equal(t, db2sdk.CryptoKey(expectedKey), got)
130+
131+
got, err = k.Verifying(ctx, expectedKey.Sequence)
132+
require.NoError(t, err)
133+
require.Equal(t, db2sdk.CryptoKey(expectedKey), got)
134+
135+
k.Close()
136+
137+
_, err = k.Signing(ctx)
138+
require.ErrorIs(t, err, cryptokeys.ErrClosed)
139+
140+
_, err = k.Verifying(ctx, expectedKey.Sequence)
141+
require.ErrorIs(t, err, cryptokeys.ErrClosed)
142+
})
107143
}

coderd/cryptokeys/keycache.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import (
88
"github.com/coder/coder/v2/codersdk"
99
)
1010

11-
var ErrKeyNotFound = xerrors.New("key not found")
12-
13-
var ErrKeyInvalid = xerrors.New("key is invalid for use")
11+
var (
12+
ErrKeyNotFound = xerrors.New("key not found")
13+
ErrKeyInvalid = xerrors.New("key is invalid for use")
14+
ErrClosed = xerrors.New("closed")
15+
)
1416

1517
// Keycache provides an abstraction for fetching signing keys.
1618
type Keycache interface {

0 commit comments

Comments
 (0)