@@ -17,6 +17,7 @@ import (
1717 "testing"
1818 "time"
1919
20+ "github.com/oklog/ulid"
2021 "github.com/pkg/errors"
2122 "github.com/prometheus/client_golang/prometheus"
2223 "github.com/prometheus/client_golang/prometheus/testutil"
@@ -27,6 +28,7 @@ import (
2728 "github.com/stretchr/testify/assert"
2829 "github.com/stretchr/testify/mock"
2930 "github.com/stretchr/testify/require"
31+ "github.com/thanos-io/thanos/pkg/shipper"
3032 "github.com/weaveworks/common/httpgrpc"
3133 "github.com/weaveworks/common/middleware"
3234 "github.com/weaveworks/common/user"
@@ -2213,3 +2215,87 @@ func TestIngester_CloseTSDBsOnShutdown(t *testing.T) {
22132215 db = i .getTSDB (userID )
22142216 require .Nil (t , db )
22152217}
2218+
2219+ func TestIngesterNotDeleteUnshippedBlocks (t * testing.T ) {
2220+ chunkRange := 2 * time .Hour
2221+ chunkRangeMilliSec := chunkRange .Milliseconds ()
2222+ cfg := defaultIngesterTestConfig ()
2223+ cfg .BlocksStorageConfig .TSDB .BlockRanges = []time.Duration {chunkRange }
2224+ cfg .BlocksStorageConfig .TSDB .Retention = time .Millisecond // Which means delete all but first block.
2225+ cfg .LifecyclerConfig .JoinAfter = 0
2226+
2227+ // Create ingester
2228+ i , cleanup , err := newIngesterMockWithTSDBStorage (cfg , nil )
2229+ require .NoError (t , err )
2230+ t .Cleanup (cleanup )
2231+
2232+ require .NoError (t , services .StartAndAwaitRunning (context .Background (), i ))
2233+ t .Cleanup (func () {
2234+ _ = services .StopAndAwaitTerminated (context .Background (), i )
2235+ })
2236+
2237+ // Wait until it's ACTIVE
2238+ test .Poll (t , 10 * time .Millisecond , ring .ACTIVE , func () interface {} {
2239+ return i .lifecycler .GetState ()
2240+ })
2241+
2242+ // Push some data to create 3 blocks.
2243+ ctx := user .InjectOrgID (context .Background (), userID )
2244+ for j := int64 (0 ); j < 5 ; j ++ {
2245+ req , _ , _ := mockWriteRequest (labels.Labels {{Name : labels .MetricName , Value : "test" }}, 0 , j * chunkRangeMilliSec )
2246+ _ , err := i .v2Push (ctx , req )
2247+ require .NoError (t , err )
2248+ }
2249+
2250+ db := i .getTSDB (userID )
2251+ require .NotNil (t , db )
2252+ require .Nil (t , db .Compact ())
2253+
2254+ oldBlocks := db .Blocks ()
2255+ require .Equal (t , 3 , len (oldBlocks ))
2256+
2257+ // Saying that we have shipped the second block, so only that should get deleted.
2258+ require .Nil (t , shipper .WriteMetaFile (nil , db .Dir (), & shipper.Meta {
2259+ Version : shipper .MetaVersion1 ,
2260+ Uploaded : []ulid.ULID {oldBlocks [1 ].Meta ().ULID },
2261+ }))
2262+
2263+ // Add more samples that could trigger another compaction and hence reload of blocks.
2264+ for j := int64 (5 ); j < 6 ; j ++ {
2265+ req , _ , _ := mockWriteRequest (labels.Labels {{Name : labels .MetricName , Value : "test" }}, 0 , j * chunkRangeMilliSec )
2266+ _ , err := i .v2Push (ctx , req )
2267+ require .NoError (t , err )
2268+ }
2269+ require .Nil (t , db .Compact ())
2270+
2271+ // Only the second block should be gone along with a new block.
2272+ newBlocks := db .Blocks ()
2273+ require .Equal (t , 3 , len (newBlocks ))
2274+ require .Equal (t , oldBlocks [0 ].Meta ().ULID , newBlocks [0 ].Meta ().ULID ) // First block remains same.
2275+ require .Equal (t , oldBlocks [2 ].Meta ().ULID , newBlocks [1 ].Meta ().ULID ) // 3rd block becomes 2nd now.
2276+ require .NotEqual (t , oldBlocks [1 ].Meta ().ULID , newBlocks [2 ].Meta ().ULID ) // The new block won't match previous 2nd block.
2277+
2278+ // Shipping 2 more blocks, hence all the blocks from first round.
2279+ require .Nil (t , shipper .WriteMetaFile (nil , db .Dir (), & shipper.Meta {
2280+ Version : shipper .MetaVersion1 ,
2281+ Uploaded : []ulid.ULID {oldBlocks [1 ].Meta ().ULID , newBlocks [0 ].Meta ().ULID , newBlocks [1 ].Meta ().ULID },
2282+ }))
2283+
2284+ // Add more samples that could trigger another compaction and hence reload of blocks.
2285+ for j := int64 (6 ); j < 7 ; j ++ {
2286+ req , _ , _ := mockWriteRequest (labels.Labels {{Name : labels .MetricName , Value : "test" }}, 0 , j * chunkRangeMilliSec )
2287+ _ , err := i .v2Push (ctx , req )
2288+ require .NoError (t , err )
2289+ }
2290+ require .Nil (t , db .Compact ())
2291+
2292+ // All blocks from the old blocks should be gone now.
2293+ newBlocks2 := db .Blocks ()
2294+ require .Equal (t , 2 , len (newBlocks2 ))
2295+
2296+ require .Equal (t , newBlocks [2 ].Meta ().ULID , newBlocks2 [0 ].Meta ().ULID ) // Block created in last round.
2297+ for _ , b := range oldBlocks {
2298+ // Second block is not one among old blocks.
2299+ require .NotEqual (t , b .Meta ().ULID , newBlocks2 [1 ].Meta ().ULID )
2300+ }
2301+ }
0 commit comments