Skip to content

Commit 5958e20

Browse files
committed
Uploading no compact markers to the global marker index
1 parent 2177ec0 commit 5958e20

File tree

3 files changed

+139
-33
lines changed

3 files changed

+139
-33
lines changed

pkg/storage/tsdb/bucketindex/markers.go

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ func BlockDeletionMarkFilepath(blockID ulid.ULID) string {
2727
return fmt.Sprintf("%s/%s-%s", MarkersPathname, blockID.String(), metadata.DeletionMarkFilename)
2828
}
2929

30+
// NoCompactMarkFilenameMarkFilepath returns the path, relative to the tenant's bucket location,
31+
// of a block no compact mark in the bucket markers location.
32+
func NoCompactMarkFilenameMarkFilepath(blockID ulid.ULID) string {
33+
return fmt.Sprintf("%s/%s-%s", MarkersPathname, blockID.String(), metadata.NoCompactMarkFilename)
34+
}
35+
3036
// IsBlockDeletionMarkFilename returns whether the input filename matches the expected pattern
3137
// of block deletion markers stored in the markers location.
3238
func IsBlockDeletionMarkFilename(name string) (ulid.ULID, bool) {

pkg/storage/tsdb/bucketindex/markers_bucket_client.go

+25-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func BucketWithGlobalMarkers(b objstore.Bucket) objstore.Bucket {
2929

3030
// Upload implements objstore.Bucket.
3131
func (b *globalMarkersBucket) Upload(ctx context.Context, name string, r io.Reader) error {
32-
blockID, ok := b.isBlockDeletionMark(name)
32+
globalMarkPath, ok := b.isMark(name)
3333
if !ok {
3434
return b.parent.Upload(ctx, name, r)
3535
}
@@ -46,7 +46,6 @@ func (b *globalMarkersBucket) Upload(ctx context.Context, name string, r io.Read
4646
}
4747

4848
// Upload it to the global markers location too.
49-
globalMarkPath := path.Clean(path.Join(path.Dir(name), "../", BlockDeletionMarkFilepath(blockID)))
5049
return b.parent.Upload(ctx, globalMarkPath, bytes.NewBuffer(body))
5150
}
5251

@@ -58,8 +57,7 @@ func (b *globalMarkersBucket) Delete(ctx context.Context, name string) error {
5857
}
5958

6059
// Delete the marker in the global markers location too.
61-
if blockID, ok := b.isBlockDeletionMark(name); ok {
62-
globalMarkPath := path.Clean(path.Join(path.Dir(name), "../", BlockDeletionMarkFilepath(blockID)))
60+
if globalMarkPath, ok := b.isMark(name); ok {
6361
if err := b.parent.Delete(ctx, globalMarkPath); err != nil {
6462
if !b.parent.IsObjNotFoundErr(err) {
6563
return err
@@ -128,6 +126,29 @@ func (b *globalMarkersBucket) ReaderWithExpectedErrs(fn objstore.IsOpFailureExpe
128126
return b
129127
}
130128

129+
func (b *globalMarkersBucket) isMark(name string) (string, bool) {
130+
marks := map[string]func(ulid.ULID) string{
131+
metadata.DeletionMarkFilename: BlockDeletionMarkFilepath,
132+
metadata.NoCompactMarkFilename: NoCompactMarkFilenameMarkFilepath,
133+
}
134+
135+
for mark, f := range marks {
136+
if path.Base(name) == mark {
137+
// Parse the block ID in the path. If there's not block ID, then it's not the per-block
138+
// deletion mark.
139+
id, ok := block.IsBlockDir(path.Dir(name))
140+
141+
if ok {
142+
return path.Clean(path.Join(path.Dir(name), "../", f(id))), ok
143+
}
144+
145+
return "", ok
146+
}
147+
}
148+
149+
return "", false
150+
}
151+
131152
func (b *globalMarkersBucket) isBlockDeletionMark(name string) (ulid.ULID, bool) {
132153
if path.Base(name) != metadata.DeletionMarkFilename {
133154
return ulid.ULID{}, false

pkg/storage/tsdb/bucketindex/markers_bucket_client_test.go

+108-29
Original file line numberDiff line numberDiff line change
@@ -11,43 +11,114 @@ import (
1111
"github.com/prometheus/client_golang/prometheus/testutil"
1212
"github.com/stretchr/testify/assert"
1313
"github.com/stretchr/testify/require"
14+
"github.com/thanos-io/thanos/pkg/block/metadata"
1415
"github.com/thanos-io/thanos/pkg/objstore"
1516

1617
"github.com/cortexproject/cortex/pkg/storage/bucket"
1718
cortex_testutil "github.com/cortexproject/cortex/pkg/storage/tsdb/testutil"
1819
)
1920

20-
func TestGlobalMarkersBucket_Delete_ShouldSucceedIfDeletionMarkDoesNotExistInTheBlockButExistInTheGlobalLocation(t *testing.T) {
21-
bkt, _ := cortex_testutil.PrepareFilesystemBucket(t)
21+
func TestGlobalMarker_ShouldUploadGlobalLocation(t *testing.T) {
22+
block1 := ulid.MustNew(1, nil)
2223

23-
ctx := context.Background()
24-
bkt = BucketWithGlobalMarkers(bkt)
24+
tests := []struct {
25+
mark string
26+
globalpath string
27+
}{
28+
{
29+
mark: metadata.DeletionMarkFilename,
30+
globalpath: "markers/" + block1.String() + "-deletion-mark.json",
31+
},
32+
{
33+
mark: metadata.NoCompactMarkFilename,
34+
globalpath: "markers/" + block1.String() + "-no-compact-mark.json",
35+
},
36+
}
37+
38+
for _, tc := range tests {
39+
t.Run(tc.mark, func(t *testing.T) {
40+
originalPath := block1.String() + "/" + tc.mark
41+
bkt, _ := cortex_testutil.PrepareFilesystemBucket(t)
42+
43+
ctx := context.Background()
44+
bkt = BucketWithGlobalMarkers(bkt)
45+
46+
bkt.Upload(ctx, originalPath, strings.NewReader("{}"))
2547

26-
// Create a mocked block deletion mark in the global location.
27-
blockID := ulid.MustNew(1, nil)
28-
globalPath := BlockDeletionMarkFilepath(blockID)
29-
require.NoError(t, bkt.Upload(ctx, globalPath, strings.NewReader("{}")))
48+
// Ensure it exists on originalPath
49+
ok, err := bkt.Exists(ctx, originalPath)
50+
require.NoError(t, err)
51+
require.True(t, ok)
3052

31-
// Ensure it exists before deleting it.
32-
ok, err := bkt.Exists(ctx, globalPath)
33-
require.NoError(t, err)
34-
require.True(t, ok)
53+
// Ensure it exists on globalPath
54+
ok, err = bkt.Exists(ctx, tc.globalpath)
55+
require.NoError(t, err)
56+
require.True(t, ok)
3557

36-
require.NoError(t, bkt.Delete(ctx, globalPath))
58+
bkt.Delete(ctx, originalPath)
3759

38-
// Ensure has been actually deleted.
39-
ok, err = bkt.Exists(ctx, globalPath)
40-
require.NoError(t, err)
41-
require.False(t, ok)
60+
// Ensure it deleted on originalPath
61+
ok, err = bkt.Exists(ctx, originalPath)
62+
require.NoError(t, err)
63+
require.False(t, ok)
64+
65+
// Ensure it exists on globalPath
66+
ok, err = bkt.Exists(ctx, tc.globalpath)
67+
require.NoError(t, err)
68+
require.False(t, ok)
69+
})
70+
}
4271
}
4372

44-
func TestGlobalMarkersBucket_isBlockDeletionMark(t *testing.T) {
73+
func TestGlobalMarkersBucket_Delete_ShouldSucceedIfMarkDoesNotExistInTheBlockButExistInTheGlobalLocation(t *testing.T) {
74+
tests := []struct {
75+
name string
76+
pathF func(ulid.ULID) string
77+
}{
78+
{
79+
name: metadata.DeletionMarkFilename,
80+
pathF: BlockDeletionMarkFilepath,
81+
},
82+
{
83+
name: metadata.NoCompactMarkFilename,
84+
pathF: NoCompactMarkFilenameMarkFilepath,
85+
},
86+
}
87+
88+
for _, tc := range tests {
89+
t.Run(tc.name, func(t *testing.T) {
90+
bkt, _ := cortex_testutil.PrepareFilesystemBucket(t)
91+
92+
ctx := context.Background()
93+
bkt = BucketWithGlobalMarkers(bkt)
94+
95+
// Create a mocked block deletion mark in the global location.
96+
blockID := ulid.MustNew(1, nil)
97+
globalPath := tc.pathF(blockID)
98+
require.NoError(t, bkt.Upload(ctx, globalPath, strings.NewReader("{}")))
99+
100+
// Ensure it exists before deleting it.
101+
ok, err := bkt.Exists(ctx, globalPath)
102+
require.NoError(t, err)
103+
require.True(t, ok)
104+
105+
require.NoError(t, bkt.Delete(ctx, globalPath))
106+
107+
// Ensure has been actually deleted.
108+
ok, err = bkt.Exists(ctx, globalPath)
109+
require.NoError(t, err)
110+
require.False(t, ok)
111+
})
112+
}
113+
}
114+
115+
func TestGlobalMarkersBucket_isMark(t *testing.T) {
45116
block1 := ulid.MustNew(1, nil)
46117

47118
tests := []struct {
48-
name string
49-
expectedOk bool
50-
expectedID ulid.ULID
119+
name string
120+
expectedOk bool
121+
expectedGlobalPath string
51122
}{
52123
{
53124
name: "",
@@ -59,23 +130,31 @@ func TestGlobalMarkersBucket_isBlockDeletionMark(t *testing.T) {
59130
name: block1.String() + "/index",
60131
expectedOk: false,
61132
}, {
62-
name: block1.String() + "/deletion-mark.json",
63-
expectedOk: true,
64-
expectedID: block1,
133+
name: block1.String() + "/deletion-mark.json",
134+
expectedOk: true,
135+
expectedGlobalPath: "markers/" + block1.String() + "-deletion-mark.json",
136+
}, {
137+
name: "/path/to/" + block1.String() + "/deletion-mark.json",
138+
expectedOk: true,
139+
expectedGlobalPath: "/path/to/markers/" + block1.String() + "-deletion-mark.json",
140+
}, {
141+
name: block1.String() + "/no-compact-mark.json",
142+
expectedOk: true,
143+
expectedGlobalPath: "markers/" + block1.String() + "-no-compact-mark.json",
65144
}, {
66-
name: "/path/to/" + block1.String() + "/deletion-mark.json",
67-
expectedOk: true,
68-
expectedID: block1,
145+
name: "/path/to/" + block1.String() + "/no-compact-mark.json",
146+
expectedOk: true,
147+
expectedGlobalPath: "/path/to/markers/" + block1.String() + "-no-compact-mark.json",
69148
},
70149
}
71150

72151
b := BucketWithGlobalMarkers(nil).(*globalMarkersBucket)
73152

74153
for _, tc := range tests {
75154
t.Run(tc.name, func(t *testing.T) {
76-
actualID, actualOk := b.isBlockDeletionMark(tc.name)
155+
globalPath, actualOk := b.isMark(tc.name)
77156
assert.Equal(t, tc.expectedOk, actualOk)
78-
assert.Equal(t, tc.expectedID, actualID)
157+
assert.Equal(t, tc.expectedGlobalPath, globalPath)
79158
})
80159
}
81160
}

0 commit comments

Comments
 (0)