Skip to content

Commit 449858c

Browse files
committed
Merge branch '68-empty-sessions' into 'master'
# Description Fix panic on idle clone checking (#68) See merge request postgres-ai/database-lab!65
2 parents af66da0 + 44de988 commit 449858c

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LDFLAGS = -ldflags "-s -w \
2121

2222
# Go tooling command aliases
2323
GOBUILD = GO111MODULE=on GOARCH=${GOARCH} go build ${LDFLAGS}
24-
GOTEST = GO111MODULE=on go test
24+
GOTEST = GO111MODULE=on go test -race
2525
GORUN = GO111MODULE=on go run ${LDFLAGS}
2626

2727
PLATFORMS=darwin linux

pkg/services/cloning/mode_base.go

+36-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"fmt"
1010
"strconv"
1111
"strings"
12+
"sync"
1213
"time"
1314

1415
"gitlab.com/postgres-ai/database-lab/pkg/log"
@@ -27,6 +28,7 @@ type baseCloning struct {
2728
cloning
2829

2930
// TODO(akartasov): Fix data race.
31+
cloneMutex sync.RWMutex
3032
clones map[string]*CloneWrapper
3133
instanceStatus *models.InstanceStatus
3234
snapshots []*models.Snapshot
@@ -67,7 +69,7 @@ func (c *baseCloning) CreateClone(clone *models.Clone) error {
6769
// TODO(akartasov): Separate validation rules.
6870
clone.ID = strings.TrimSpace(clone.ID)
6971

70-
if _, ok := c.clones[clone.ID]; ok {
72+
if _, ok := c.findWrapper(clone.ID); ok {
7173
return errors.New("clone with such ID already exists")
7274
}
7375

@@ -88,7 +90,6 @@ func (c *baseCloning) CreateClone(clone *models.Clone) error {
8890
}
8991

9092
w := NewCloneWrapper(clone)
91-
c.clones[clone.ID] = w
9293

9394
clone.Status = &models.Status{
9495
Code: models.StatusCreating,
@@ -153,11 +154,13 @@ func (c *baseCloning) CreateClone(clone *models.Clone) error {
153154
}
154155
}()
155156

157+
c.setWrapper(clone.ID, w)
158+
156159
return nil
157160
}
158161

159162
func (c *baseCloning) DestroyClone(id string) error {
160-
w, ok := c.clones[id]
163+
w, ok := c.findWrapper(id)
161164
if !ok {
162165
return errors.New("clone not found")
163166
}
@@ -187,14 +190,16 @@ func (c *baseCloning) DestroyClone(id string) error {
187190
return
188191
}
189192

193+
c.cloneMutex.Lock()
190194
delete(c.clones, w.clone.ID)
195+
c.cloneMutex.Unlock()
191196
}()
192197

193198
return nil
194199
}
195200

196201
func (c *baseCloning) GetClone(id string) (*models.Clone, error) {
197-
w, ok := c.clones[id]
202+
w, ok := c.findWrapper(id)
198203
if !ok {
199204
return nil, errors.New("clone not found")
200205
}
@@ -249,20 +254,22 @@ func (c *baseCloning) UpdateClone(id string, patch *models.Clone) error {
249254
return errors.New("CreatedAt cannot be changed")
250255
}
251256

252-
w, ok := c.clones[id]
257+
w, ok := c.findWrapper(id)
253258
if !ok {
254259
return errors.New("clone not found")
255260
}
256261

257262
// Set fields.
258263

264+
c.cloneMutex.Lock()
259265
w.clone.Protected = patch.Protected
266+
c.cloneMutex.Unlock()
260267

261268
return nil
262269
}
263270

264271
func (c *baseCloning) ResetClone(id string) error {
265-
w, ok := c.clones[id]
272+
w, ok := c.findWrapper(id)
266273
if !ok {
267274
return errors.New("clone not found")
268275
}
@@ -328,15 +335,32 @@ func (c *baseCloning) GetSnapshots() ([]*models.Snapshot, error) {
328335
return c.snapshots, nil
329336
}
330337

338+
// GetClones returns all clones.
331339
func (c *baseCloning) GetClones() []*models.Clone {
332-
clones := make([]*models.Clone, 0)
340+
clones := make([]*models.Clone, 0, len(c.clones))
333341
for _, clone := range c.clones {
334342
clones = append(clones, clone.clone)
335343
}
336344

337345
return clones
338346
}
339347

348+
// findWrapper retrieves a clone findWrapper by id.
349+
func (c *baseCloning) findWrapper(id string) (*CloneWrapper, bool) {
350+
c.cloneMutex.RLock()
351+
w, ok := c.clones[id]
352+
c.cloneMutex.RUnlock()
353+
354+
return w, ok
355+
}
356+
357+
// setWrapper adds a clone wrapper to the map of clones.
358+
func (c *baseCloning) setWrapper(id string, wrapper *CloneWrapper) {
359+
c.cloneMutex.Lock()
360+
c.clones[id] = wrapper
361+
c.cloneMutex.Unlock()
362+
}
363+
340364
func (c *baseCloning) getExpectedCloningTime() float64 {
341365
if len(c.clones) == 0 {
342366
return 0
@@ -432,6 +456,11 @@ func (c *baseCloning) isIdleClone(wrapper *CloneWrapper) (bool, error) {
432456

433457
session := wrapper.session
434458

459+
// TODO(akartasov): Remove wrappers without session.
460+
if session == nil {
461+
return false, errors.New("failed to get clone session")
462+
}
463+
435464
lastSessionActivity, err := c.provision.LastSessionActivity(session, idleDuration)
436465
if err != nil {
437466
if err == pglog.ErrNotFound {

0 commit comments

Comments
 (0)