github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/integration/peers_bootstrap_partial_data_test.go (about) 1 //go:build integration 2 // +build integration 3 4 // Copyright (c) 2016 Uber Technologies, Inc. 5 // 6 // Permission is hereby granted, free of charge, to any person obtaining a copy 7 // of this software and associated documentation files (the "Software"), to deal 8 // in the Software without restriction, including without limitation the rights 9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 // copies of the Software, and to permit persons to whom the Software is 11 // furnished to do so, subject to the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be included in 14 // all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 // THE SOFTWARE. 23 24 package integration 25 26 import ( 27 "testing" 28 "time" 29 30 "github.com/m3db/m3/src/dbnode/integration/generate" 31 "github.com/m3db/m3/src/dbnode/namespace" 32 "github.com/m3db/m3/src/dbnode/retention" 33 xtest "github.com/m3db/m3/src/x/test" 34 xtime "github.com/m3db/m3/src/x/time" 35 36 "github.com/stretchr/testify/require" 37 ) 38 39 // This test simulates a case where node fails / reboots while fetching data from peers. 40 // When restarting / retrying bootstrap process, there already will be some data on disk, 41 // which can be fulfilled by filesystem bootstrapper. 42 func TestPeersBootstrapPartialData(t *testing.T) { 43 if testing.Short() { 44 t.SkipNow() 45 } 46 47 // Test setups 48 log := xtest.NewLogger(t) 49 blockSize := 2 * time.Hour 50 retentionOpts := retention.NewOptions(). 51 SetRetentionPeriod(5 * blockSize). 52 SetBlockSize(blockSize). 53 SetBufferPast(10 * time.Minute). 54 SetBufferFuture(2 * time.Minute) 55 idxOpts := namespace.NewIndexOptions(). 56 SetEnabled(true). 57 SetBlockSize(blockSize) 58 nsOpts := namespace.NewOptions().SetRetentionOptions(retentionOpts).SetIndexOptions(idxOpts) 59 namesp, err := namespace.NewMetadata(testNamespaces[0], nsOpts) 60 require.NoError(t, err) 61 opts := NewTestOptions(t). 62 SetNamespaces([]namespace.Metadata{namesp}). 63 // Use TChannel clients for writing / reading because we want to target individual nodes at a time 64 // and not write/read all nodes in the cluster. 65 SetUseTChannelClientForWriting(true). 66 SetUseTChannelClientForReading(true) 67 68 setupOpts := []BootstrappableTestSetupOptions{ 69 {DisablePeersBootstrapper: true}, 70 { 71 DisableCommitLogBootstrapper: true, 72 DisablePeersBootstrapper: false, 73 }, 74 } 75 setups, closeFn := NewDefaultBootstrappableTestSetups(t, opts, setupOpts) //nolint:govet 76 defer closeFn() 77 78 // Write test data to first node 79 now := setups[0].NowFn()() 80 inputData := []generate.BlockConfig{ 81 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-5 * blockSize)}, 82 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-4 * blockSize)}, 83 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-3 * blockSize)}, 84 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-2 * blockSize)}, 85 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-blockSize)}, 86 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now}, 87 } 88 seriesMaps := generate.BlocksByStart(inputData) 89 require.NoError(t, writeTestDataToDiskWithIndex(namesp, setups[0], seriesMaps)) 90 91 // Write a subset of blocks to second node, simulating an incomplete peer bootstrap. 92 partialBlockStarts := map[xtime.UnixNano]struct{}{ 93 inputData[0].Start: {}, 94 inputData[1].Start: {}, 95 inputData[2].Start: {}, 96 } 97 partialSeriesMaps := make(generate.SeriesBlocksByStart) 98 for blockStart, series := range seriesMaps { 99 if _, ok := partialBlockStarts[blockStart]; ok { 100 partialSeriesMaps[blockStart] = series 101 } 102 } 103 require.NoError(t, writeTestDataToDisk(namesp, setups[1], partialSeriesMaps, 0, 104 func(gOpts generate.Options) generate.Options { 105 return gOpts.SetWriteEmptyShards(false) 106 })) 107 108 // Start the first server with filesystem bootstrapper 109 require.NoError(t, setups[0].StartServer()) 110 111 // Start the last server with peers and filesystem bootstrappers 112 require.NoError(t, setups[1].StartServer()) 113 log.Debug("servers are now up") 114 115 // Stop the servers 116 defer func() { 117 setups.parallel(func(s TestSetup) { 118 require.NoError(t, s.StopServer()) 119 }) 120 log.Debug("servers are now down") 121 }() 122 123 // Verify in-memory data match what we expect 124 for _, setup := range setups { 125 verifySeriesMaps(t, setup, namesp.ID(), seriesMaps) 126 } 127 }