From c26e45efabdde4d6d274d260da75c56270330fc7 Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Wed, 9 Jun 2021 18:00:59 +0800 Subject: [PATCH] Fix the concurrent pushing the same image issue The transaction will be aborted when get errors during the execution which causes the following sqls report error. This commit moves the re-getting artifact logic out of the second transaction to avoid the concurrent pushing issue Signed-off-by: Wenkai Yin --- src/controller/artifact/controller.go | 20 ++++++++++---------- src/controller/repository/controller.go | 23 +++++++++++------------ 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/controller/artifact/controller.go b/src/controller/artifact/controller.go index 48c95e1ef..1b294c92d 100644 --- a/src/controller/artifact/controller.go +++ b/src/controller/artifact/controller.go @@ -199,21 +199,21 @@ func (c *controller) ensureArtifact(ctx context.Context, repository, digest stri if err = orm.WithTransaction(func(ctx context.Context) error { id, err := c.artMgr.Create(ctx, artifact) if err != nil { - // if got conflict error, try to get the artifact again - if errors.IsConflictErr(err) { - var e error - artifact, e = c.artMgr.GetByDigest(ctx, repository, digest) - if e != nil { - err = e - } - } return err } created = true artifact.ID = id return nil - })(ctx); err != nil && !errors.IsConflictErr(err) { - return false, nil, err + })(ctx); err != nil { + // got error that isn't conflict error, return directly + if !errors.IsConflictErr(err) { + return false, nil, err + } + // if got conflict error, try to get the artifact again + artifact, err = c.artMgr.GetByDigest(ctx, repository, digest) + if err != nil { + return false, nil, err + } } return created, artifact, nil diff --git a/src/controller/repository/controller.go b/src/controller/repository/controller.go index c54ac43c6..f68f27e18 100644 --- a/src/controller/repository/controller.go +++ b/src/controller/repository/controller.go @@ -104,22 +104,21 @@ func (c *controller) Ensure(ctx context.Context, name string) (bool, int64, erro Name: name, }) if err != nil { - // if got conflict error, try to get again - if errors.IsConflictErr(err) { - var e error - repository, e = c.repoMgr.GetByName(ctx, name) - if e != nil { - err = e - } else { - id = repository.RepositoryID - } - } return err } created = true return nil - })(ctx); err != nil && !errors.IsConflictErr(err) { - return false, 0, err + })(ctx); err != nil { + // isn't conflict error, return directly + if !errors.IsConflictErr(err) { + return false, 0, err + } + // if got conflict error, try to get again + repository, err = c.repoMgr.GetByName(ctx, name) + if err != nil { + return false, 0, err + } + id = repository.RepositoryID } return created, id, nil