From 7a6308b4f90eaf08585cc7932cf1f9949e7f93e2 Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Fri, 17 Jun 2016 18:27:31 +0800 Subject: [PATCH] bug fix: fix confliction when more than one job are creating the same project --- job/replication/transfer.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/job/replication/transfer.go b/job/replication/transfer.go index 83113e8e4..574071589 100644 --- a/job/replication/transfer.go +++ b/job/replication/transfer.go @@ -18,6 +18,7 @@ package replication import ( "bytes" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -43,6 +44,10 @@ const ( StatePushManifest = "push_manifest" ) +var ( + ErrConflict = errors.New("conflict") +) + // BaseHandler holds informations shared by other state handlers type BaseHandler struct { project string // project_name @@ -136,15 +141,24 @@ type Checker struct { // Enter check existence of project, if it does not exist, create it, // if it exists, check whether the user has write privilege to it. func (c *Checker) Enter() (string, error) { +enter: exist, canWrite, err := c.projectExist() if err != nil { c.logger.Errorf("an error occurred while checking existence of project %s on %s with user %s : %v", c.project, c.dstURL, c.dstUsr, err) return "", err } if !exist { - if err := c.createProject(); err != nil { - c.logger.Errorf("an error occurred while creating project %s on %s with user %s : %v", c.project, c.dstURL, c.dstUsr, err) - return "", err + err := c.createProject() + if err != nil { + // other job may be also doing the same thing when the current job + // is creating project, so when the response code is 409, re-check + // the existence of project + if err == ErrConflict { + goto enter + } else { + c.logger.Errorf("an error occurred while creating project %s on %s with user %s : %v", c.project, c.dstURL, c.dstUsr, err) + return "", err + } } c.logger.Infof("project %s is created on %s with user %s", c.project, c.dstURL, c.dstUsr) return StatePullManifest, nil @@ -246,6 +260,10 @@ func (c *Checker) createProject() error { } if resp.StatusCode != http.StatusCreated { + if resp.StatusCode == http.StatusConflict { + return ErrConflict + } + defer resp.Body.Close() message, err := ioutil.ReadAll(resp.Body) if err != nil {