From ad47d2f4447c1b734ea03243507921b7cf3e4901 Mon Sep 17 00:00:00 2001 From: Wang Yan Date: Mon, 24 Aug 2020 16:08:15 +0800 Subject: [PATCH] fix upgrade issue (#12857) fixes #12849 1, gives a default value to blob status in the migration script, and use none to replace the empty string as the StatusNone, that will more readable on debugging failure. 2, GC jobs marks all of blobs as StatusDelete in the mark phase, but if encounter any failure in the sweep phase, GC job will quite and all of blobs are in StatusDelete. If user wants to execute the GC again, it will fail as the StatusDelete cannot be marked as StatusDelete. So, add StatusDelete in the status map to make StatusDelete can be marked as StatusDelete. Signed-off-by: wang yan --- make/migrations/postgresql/0040_2.1.0_schema.up.sql | 2 +- src/pkg/blob/dao/dao.go | 2 ++ src/pkg/blob/dao/dao_test.go | 1 + src/pkg/blob/models/blob.go | 8 +++++--- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/make/migrations/postgresql/0040_2.1.0_schema.up.sql b/make/migrations/postgresql/0040_2.1.0_schema.up.sql index 029660c3c..5de5f6ade 100644 --- a/make/migrations/postgresql/0040_2.1.0_schema.up.sql +++ b/make/migrations/postgresql/0040_2.1.0_schema.up.sql @@ -35,7 +35,7 @@ CREATE TABLE IF NOT EXISTS task ( ); ALTER TABLE blob ADD COLUMN IF NOT EXISTS update_time timestamp default CURRENT_TIMESTAMP; -ALTER TABLE blob ADD COLUMN IF NOT EXISTS status varchar(255); +ALTER TABLE blob ADD COLUMN IF NOT EXISTS status varchar(255) default 'none'; ALTER TABLE blob ADD COLUMN IF NOT EXISTS version BIGINT default 0; CREATE INDEX IF NOT EXISTS idx_status ON blob (status); CREATE INDEX IF NOT EXISTS idx_version ON blob (version); diff --git a/src/pkg/blob/dao/dao.go b/src/pkg/blob/dao/dao.go index 0b3689959..8a4fabcab 100644 --- a/src/pkg/blob/dao/dao.go +++ b/src/pkg/blob/dao/dao.go @@ -155,6 +155,8 @@ func (d *dao) CreateBlob(ctx context.Context, blob *models.Blob) (int64, error) } blob.CreationTime = time.Now() + // the default status is none + blob.Status = models.StatusNone return o.InsertOrUpdate(blob, "digest") } diff --git a/src/pkg/blob/dao/dao_test.go b/src/pkg/blob/dao/dao_test.go index 25ca7afb9..779780435 100644 --- a/src/pkg/blob/dao/dao_test.go +++ b/src/pkg/blob/dao/dao_test.go @@ -121,6 +121,7 @@ func (suite *DaoTestSuite) TestGetBlobByDigest() { blob, err = suite.dao.GetBlobByDigest(ctx, digest) if suite.Nil(err) { suite.Equal(digest, blob.Digest) + suite.Equal(models.StatusNone, blob.Status) } } diff --git a/src/pkg/blob/models/blob.go b/src/pkg/blob/models/blob.go index f8212007c..e318ea840 100644 --- a/src/pkg/blob/models/blob.go +++ b/src/pkg/blob/models/blob.go @@ -46,20 +46,22 @@ StatusDelete -> StatusDeleting : Select the blob and call the API to delete asse StatusDeleting -> Trash : Delete success from the backend storage. StatusDelete -> StatusNone : Client asks the existence of blob, remove it from the candidate. StatusDelete -> StatusDeleteFailed : The storage driver returns fail when to delete the real data from the configurated file system. +StatusDelete -> StatusDelete : Encounter failure in the GC sweep phase. When to rerun the GC job, all of blob candidates are marked as StatusDelete again. StatusDeleteFailed -> StatusNone : The delete failed blobs can be pushed again, and back to normal. StatusDeleteFailed -> StatusDelete : The delete failed blobs should be in the candidate. */ const ( - StatusNone = "" + StatusNone = "none" StatusDelete = "delete" StatusDeleting = "deleting" StatusDeleteFailed = "deletefailed" ) -// StatusMap key is the target status, values are the accept source status. For example, only StatusNone and StatusDeleteFailed can be convert to StatusDelete. +// StatusMap key is the target status, values are the accepted source status. +// For example, only StatusDelete can be convert to StatusDeleting. var StatusMap = map[string][]string{ StatusNone: {StatusNone, StatusDelete, StatusDeleteFailed}, - StatusDelete: {StatusNone, StatusDeleteFailed}, + StatusDelete: {StatusNone, StatusDelete, StatusDeleteFailed}, StatusDeleting: {StatusDelete}, StatusDeleteFailed: {StatusDeleting}, }