github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/storage/bootstrap/process_test.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package bootstrap 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/m3db/m3/src/cluster/shard" 28 "github.com/m3db/m3/src/dbnode/namespace" 29 "github.com/m3db/m3/src/dbnode/persist" 30 "github.com/m3db/m3/src/dbnode/persist/fs" 31 "github.com/m3db/m3/src/dbnode/retention" 32 "github.com/m3db/m3/src/dbnode/sharding" 33 "github.com/m3db/m3/src/dbnode/storage/bootstrap/result" 34 "github.com/m3db/m3/src/dbnode/topology" 35 xcontext "github.com/m3db/m3/src/x/context" 36 "github.com/m3db/m3/src/x/ident" 37 "github.com/m3db/m3/src/x/instrument" 38 xtime "github.com/m3db/m3/src/x/time" 39 40 "github.com/golang/mock/gomock" 41 "github.com/stretchr/testify/require" 42 ) 43 44 func TestBootstrapProcessRunActiveBlockAdvanced(t *testing.T) { 45 tests := []struct { 46 name string 47 shardsInitializing bool 48 expectErr error 49 }{ 50 { 51 name: "time shifted and shards initializing, should return error", 52 shardsInitializing: true, 53 expectErr: ErrFileSetSnapshotTypeRangeAdvanced, 54 }, 55 { 56 name: "time shifted and shards all available, should not return error", 57 shardsInitializing: false, 58 }, 59 } 60 61 for _, test := range tests { 62 t.Run(test.name, func(t *testing.T) { 63 ctrl := gomock.NewController(t) 64 defer ctrl.Finish() 65 66 var ( 67 ctx = xcontext.NewBackground() 68 blockSize = time.Hour 69 startTime = xtime.Now().Truncate(blockSize) 70 bufferPast = 30 * time.Minute 71 bufferFuture = 30 * time.Minute 72 // shift 'now' just enough so that after adding 'bufferFuture' it would reach the next block 73 now = startTime.Add(blockSize - bufferFuture) 74 shards = []uint32{0} 75 retentionOpts = retention.NewOptions(). 76 SetBlockSize(blockSize). 77 SetRetentionPeriod(12 * blockSize). 78 SetBufferPast(bufferPast). 79 SetBufferFuture(bufferFuture) 80 nsOptions = namespace.NewOptions().SetRetentionOptions(retentionOpts) 81 nsID = ident.StringID("ns") 82 ns, err = namespace.NewMetadata(nsID, nsOptions) 83 ) 84 require.NoError(t, err) 85 86 processNs := []ProcessNamespace{ 87 { 88 Metadata: ns, 89 Shards: shards, 90 DataAccumulator: NewMockNamespaceDataAccumulator(ctrl), 91 }, 92 } 93 94 bootstrapper := NewMockBootstrapper(ctrl) 95 bootstrapper.EXPECT().String().Return("mock_bootstrapper").AnyTimes() 96 bootstrapper.EXPECT(). 97 Bootstrap(gomock.Any(), gomock.Any(), gomock.Any()). 98 DoAndReturn(func(_, _, _ interface{}) (NamespaceResults, error) { 99 return NewNamespaceResults(NewNamespaces(processNs)), nil 100 }). 101 AnyTimes() 102 103 shardState := shard.Available 104 if test.shardsInitializing { 105 shardState = shard.Initializing 106 } 107 shardSet, err := sharding.NewShardSet(sharding.NewShards(shards, shardState), 108 sharding.DefaultHashFn(len(shards))) 109 require.NoError(t, err) 110 111 origin := topology.NewHost("self", "127.0.0.1:9000") 112 hostShardSet := topology.NewHostShardSet(origin, shardSet) 113 114 topoMapOpts := topology.NewStaticOptions(). 115 SetReplicas(1). 116 SetShardSet(shardSet). 117 SetHostShardSets([]topology.HostShardSet{hostShardSet}) 118 topoMap := topology.NewStaticMap(topoMapOpts) 119 topoState, err := newInitialTopologyState(origin, topoMap) 120 require.NoError(t, err) 121 122 processOpts := NewProcessOptions().SetOrigin(origin) 123 process := bootstrapProcess{ 124 processOpts: processOpts, 125 resultOpts: result.NewOptions(), 126 fsOpts: fs.NewOptions(), 127 nowFn: func() time.Time { return now.ToTime() }, 128 log: instrument.NewOptions().Logger(), 129 bootstrapper: bootstrapper, 130 initialTopologyState: topoState, 131 } 132 133 _, err = process.Run(ctx, startTime, processNs) 134 require.Equal(t, test.expectErr, err) 135 }) 136 } 137 } 138 139 func TestTargetRangesFileSetTypeForSnapshotDisabledNamespace(t *testing.T) { 140 sut := bootstrapProcess{processOpts: NewProcessOptions()} 141 nsOpts := namespace.NewOptions().SetSnapshotEnabled(false) 142 143 rangesForData := sut.targetRangesForData(xtime.Now(), nsOpts) 144 rangesForIndex := sut.targetRangesForIndex(xtime.Now(), nsOpts) 145 146 requireFilesetTypes(t, rangesForData, persist.FileSetFlushType) 147 requireFilesetTypes(t, rangesForIndex, persist.FileSetFlushType) 148 } 149 150 func TestTargetRangesFileSetTypeForSnapshotEnabledNamespace(t *testing.T) { 151 sut := bootstrapProcess{processOpts: NewProcessOptions()} 152 nsOpts := namespace.NewOptions().SetSnapshotEnabled(true) 153 154 rangesForData := sut.targetRangesForData(xtime.Now(), nsOpts) 155 rangesForIndex := sut.targetRangesForIndex(xtime.Now(), nsOpts) 156 157 requireFilesetTypes(t, rangesForData, persist.FileSetSnapshotType) 158 requireFilesetTypes(t, rangesForIndex, persist.FileSetSnapshotType) 159 } 160 161 func requireFilesetTypes(t *testing.T, ranges targetRangesResult, expectedSecond persist.FileSetType) { 162 persistConfigFirstRange := ranges.firstRangeWithPersistTrue.RunOptions.PersistConfig() 163 require.True(t, persistConfigFirstRange.Enabled) 164 require.Equal(t, persist.FileSetFlushType, persistConfigFirstRange.FileSetType) 165 166 persistConfigSecondRange := ranges.secondRange.RunOptions.PersistConfig() 167 require.True(t, persistConfigSecondRange.Enabled) 168 require.Equal(t, expectedSecond, persistConfigSecondRange.FileSetType) 169 }