Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update refresh health query #1027

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 10 additions & 36 deletions stores/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -1991,42 +1991,16 @@ LIMIT ?
rowsAffected = res.RowsAffected

// Update the health of objects with outdated health.
var err error
if isSQLite(tx) {
err = tx.Exec(`
UPDATE objects
SET health = (
SELECT MIN(slabs.health)
FROM slabs
INNER JOIN slices ON slices.db_slab_id = slabs.id
INNER JOIN objects ON slices.db_object_id = objects.id
)
WHERE EXISTS (
SELECT 1 FROM slabs
INNER JOIN slices ON slices.db_slab_id = slabs.id
INNER JOIN objects ON slices.db_object_id = objects.id
WHERE slabs.health < objects.health
)
`).Error
} else {
err = tx.Exec(`
UPDATE objects
JOIN (
SELECT slices.db_object_id, MIN(slabs.health) AS min_health
FROM slabs
INNER JOIN slices ON slices.db_slab_id = slabs.id
GROUP BY slices.db_object_id
) AS min_healths ON objects.id = min_healths.db_object_id
SET objects.health = min_healths.min_health
WHERE objects.health > (
SELECT MIN(slabs.health)
FROM slabs
INNER JOIN slices ON slices.db_slab_id = slabs.id
WHERE slices.db_object_id = objects.id
);
`).Error
}
return err
return tx.Exec(`
UPDATE objects SET health = (
SELECT MIN(slabs.health)
FROM slabs
INNER JOIN slices ON slices.db_slab_id = slabs.id AND slices.db_object_id = objects.id
) WHERE health != (
SELECT MIN(slabs.health)
FROM slabs
INNER JOIN slices ON slices.db_slab_id = slabs.id AND slices.db_object_id = objects.id
)`).Error
})
if err != nil {
return err
Expand Down
113 changes: 113 additions & 0 deletions stores/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3879,6 +3879,119 @@ func TestSlabHealthInvalidation(t *testing.T) {
}
}

func TestRefreshHealth(t *testing.T) {
ss := newTestSQLStore(t, defaultTestSQLStoreConfig)
defer ss.Close()

// define a helper function to return an object's health
health := func(name string) float64 {
t.Helper()
o, err := ss.Object(context.Background(), api.DefaultBucketName, name)
if err != nil {
t.Fatal(err)
}
return o.Health
}

// add test hosts
hks, err := ss.addTestHosts(2)
if err != nil {
t.Fatal(err)
}

// add test contract & set it as contract set
fcids, _, err := ss.addTestContracts(hks)
if err != nil {
t.Fatal(err)
}
err = ss.SetContractSet(context.Background(), testContractSet, fcids)
if err != nil {
t.Fatal(err)
}

// add two test objects
o1 := t.Name() + "1"
if added, err := ss.addTestObject(o1, object.Object{
Key: object.GenerateEncryptionKey(),
Slabs: []object.SlabSlice{{Slab: object.Slab{
Key: object.GenerateEncryptionKey(),
Shards: []object.Sector{
newTestShard(hks[0], fcids[0], types.Hash256{0}),
newTestShard(hks[1], fcids[1], types.Hash256{1}),
},
}}},
}); err != nil {
t.Fatal(err)
} else if added.Health != 1 {
t.Fatal("expected health to be 1, got", added.Health)
}

o2 := t.Name() + "2"
if added, err := ss.addTestObject(o2, object.Object{
Key: object.GenerateEncryptionKey(),
Slabs: []object.SlabSlice{{Slab: object.Slab{
Key: object.GenerateEncryptionKey(),
Shards: []object.Sector{
newTestShard(hks[0], fcids[0], types.Hash256{2}),
newTestShard(hks[1], fcids[1], types.Hash256{3}),
},
}}},
}); err != nil {
t.Fatal(err)
} else if added.Health != 1 {
t.Fatal("expected health to be 1, got", added.Health)
}

// update contract set and refresh health, assert health is .5
err = ss.SetContractSet(context.Background(), testContractSet, fcids[:1])
if err != nil {
t.Fatal(err)
}
err = ss.RefreshHealth(context.Background())
if err != nil {
t.Fatal(err)
}
if health(o1) != .5 {
t.Fatal("expected health to be .5, got", health(o1))
} else if health(o2) != .5 {
t.Fatal("expected health to be .5, got", health(o2))
}

// set the health of s1 to be lower than .5
err = ss.overrideSlabHealth(o1, 0.4)
if err != nil {
t.Fatal(err)
}

// refresh health and assert only object 1's health got updated
err = ss.RefreshHealth(context.Background())
if err != nil {
t.Fatal(err)
}
if health(o1) != .4 {
t.Fatal("expected health to be .4, got", health(o1))
} else if health(o2) != .5 {
t.Fatal("expected health to be .5, got", health(o2))
}

// set the health of s2 to be higher than .5
err = ss.overrideSlabHealth(o2, 0.6)
if err != nil {
t.Fatal(err)
}

// refresh health and assert only object 2's health got updated
err = ss.RefreshHealth(context.Background())
if err != nil {
t.Fatal(err)
}
if health(o1) != .4 {
t.Fatal("expected health to be .4, got", health(o1))
} else if health(o2) != .6 {
t.Fatal("expected health to be .6, got", health(o2))
}
}

func TestSlabCleanupTrigger(t *testing.T) {
ss := newTestSQLStore(t, defaultTestSQLStoreConfig)
defer ss.Close()
Expand Down
Loading