Skip to content

Commit 95db580

Browse files
Prevent race condition creating networks
1 parent 23891cd commit 95db580

1 file changed

Lines changed: 28 additions & 7 deletions

File tree

dgraphtest/local_cluster.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ type LocalCluster struct {
5656
customTokenizers string
5757

5858
// resources
59-
dcli *docker.Client
60-
net cnet
61-
zeros []*zero
62-
alphas []*alpha
59+
dcli *docker.Client
60+
net cnet
61+
netMutex sync.Mutex // protects network recreation
62+
zeros []*zero
63+
alphas []*alpha
6364
}
6465

6566
// UpgradeStrategy is an Enum that defines various upgrade strategies
@@ -188,6 +189,18 @@ func (c *LocalCluster) createNetwork() error {
188189

189190
networkResp, err := c.dcli.NetworkCreate(ctx, c.net.name, opts)
190191
if err != nil {
192+
// If network already exists (race condition), try to inspect and reuse it
193+
if strings.Contains(err.Error(), "already exists") {
194+
log.Printf("[INFO] network %s already exists (race condition), inspecting", c.net.name)
195+
existingNet, inspectErr := c.dcli.NetworkInspect(ctx, c.net.name, network.InspectOptions{})
196+
if inspectErr == nil {
197+
log.Printf("[INFO] reusing existing network %s (ID: %s)", c.net.name, existingNet.ID)
198+
c.net.id = existingNet.ID
199+
return nil
200+
}
201+
// If inspect also fails, return original create error
202+
log.Printf("[WARNING] failed to inspect network after creation conflict: %v", inspectErr)
203+
}
191204
return errors.Wrap(err, "error creating network")
192205
}
193206
c.net.id = networkResp.ID
@@ -274,10 +287,18 @@ func (c *LocalCluster) createContainer(dc dnode) (string, error) {
274287
if c.net.id != "" {
275288
_, err := c.dcli.NetworkInspect(ctx, c.net.id, network.InspectOptions{})
276289
if err != nil {
277-
log.Printf("[WARNING] network %s (ID: %s) not found, recreating", c.net.name, c.net.id)
278-
if err := c.createNetwork(); err != nil {
279-
return "", errors.Wrap(err, "error recreating network")
290+
// Use mutex to prevent multiple goroutines from recreating network simultaneously
291+
c.netMutex.Lock()
292+
// Double-check after acquiring lock - another goroutine may have recreated it
293+
_, recheckErr := c.dcli.NetworkInspect(ctx, c.net.id, network.InspectOptions{})
294+
if recheckErr != nil {
295+
log.Printf("[WARNING] network %s (ID: %s) not found, recreating", c.net.name, c.net.id)
296+
if err := c.createNetwork(); err != nil {
297+
c.netMutex.Unlock()
298+
return "", errors.Wrap(err, "error recreating network")
299+
}
280300
}
301+
c.netMutex.Unlock()
281302
}
282303
}
283304

0 commit comments

Comments
 (0)