github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/service/service_recovery_test.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package service 16 17 import ( 18 "context" 19 "testing" 20 21 "github.com/matrixorigin/matrixone/pkg/logservice" 22 "github.com/matrixorigin/matrixone/pkg/pb/txn" 23 "github.com/matrixorigin/matrixone/pkg/txn/storage/mem" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestRecoveryFromCommittedWithData(t *testing.T) { 28 mlog := mem.NewMemLog() 29 wTxn := NewTestTxn(1, 1, 1) 30 wTxn.Status = txn.TxnStatus_Committed 31 wTxn.CommitTS = NewTestTimestamp(2) 32 addLog(t, mlog, wTxn, 1, 2) 33 34 sender := NewTestSender() 35 defer func() { 36 assert.NoError(t, sender.Close()) 37 }() 38 39 s := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog).(*service) 40 assert.NoError(t, s.Start()) 41 defer func() { 42 assert.NoError(t, s.Close(false)) 43 }() 44 45 checkData(t, wTxn, s, 2, 1, true) 46 checkData(t, wTxn, s, 2, 2, true) 47 } 48 49 func TestRecoveryFromMultiCommittedWithData(t *testing.T) { 50 mlog := mem.NewMemLog() 51 wTxn := NewTestTxn(1, 1, 1) 52 wTxn.Status = txn.TxnStatus_Committed 53 wTxn.CommitTS = NewTestTimestamp(2) 54 addLog(t, mlog, wTxn, 1, 2) 55 addLog(t, mlog, wTxn, 1, 2) 56 addLog(t, mlog, wTxn, 1, 2) 57 58 sender := NewTestSender() 59 defer func() { 60 assert.NoError(t, sender.Close()) 61 }() 62 63 s := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog).(*service) 64 assert.NoError(t, s.Start()) 65 defer func() { 66 assert.NoError(t, s.Close(false)) 67 }() 68 69 checkData(t, wTxn, s, 2, 1, true) 70 checkData(t, wTxn, s, 2, 2, true) 71 } 72 73 func TestRecoveryFromCommittedAfterPrepared(t *testing.T) { 74 mlog := mem.NewMemLog() 75 wTxn := NewTestTxn(1, 1, 1) 76 wTxn.Status = txn.TxnStatus_Prepared 77 wTxn.PreparedTS = NewTestTimestamp(2) 78 addLog(t, mlog, wTxn, 1, 2) 79 80 wTxn.Status = txn.TxnStatus_Committed 81 wTxn.CommitTS = NewTestTimestamp(3) 82 addLog(t, mlog, wTxn) 83 84 sender := NewTestSender() 85 defer func() { 86 assert.NoError(t, sender.Close()) 87 }() 88 89 s := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog).(*service) 90 assert.NoError(t, s.Start()) 91 defer func() { 92 assert.NoError(t, s.Close(false)) 93 }() 94 95 checkData(t, wTxn, s, 3, 1, true) 96 checkData(t, wTxn, s, 3, 2, true) 97 } 98 99 func TestRecoveryFromMultiCommittedAfterPrepared(t *testing.T) { 100 mlog := mem.NewMemLog() 101 wTxn := NewTestTxn(1, 1, 1) 102 wTxn.Status = txn.TxnStatus_Prepared 103 wTxn.PreparedTS = NewTestTimestamp(2) 104 addLog(t, mlog, wTxn, 1, 2) 105 addLog(t, mlog, wTxn, 1, 2) 106 addLog(t, mlog, wTxn, 1, 2) 107 108 wTxn.Status = txn.TxnStatus_Committed 109 wTxn.CommitTS = NewTestTimestamp(3) 110 addLog(t, mlog, wTxn) 111 addLog(t, mlog, wTxn) 112 addLog(t, mlog, wTxn) 113 114 sender := NewTestSender() 115 defer func() { 116 assert.NoError(t, sender.Close()) 117 }() 118 119 s := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog).(*service) 120 assert.NoError(t, s.Start()) 121 defer func() { 122 assert.NoError(t, s.Close(false)) 123 }() 124 125 checkData(t, wTxn, s, 3, 1, true) 126 checkData(t, wTxn, s, 3, 2, true) 127 } 128 129 func TestRecoveryFromMultiTNShardWithAllPrepared(t *testing.T) { 130 mlog1 := mem.NewMemLog() 131 mlog2 := mem.NewMemLog() 132 133 wTxn := NewTestTxn(1, 1, 1, 2) 134 wTxn.Status = txn.TxnStatus_Prepared 135 wTxn.PreparedTS = NewTestTimestamp(2) 136 137 addLog(t, mlog1, wTxn, 1) 138 addLog(t, mlog2, wTxn, 2) 139 140 sender := NewTestSender() 141 defer func() { 142 assert.NoError(t, sender.Close()) 143 }() 144 145 s1 := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog1).(*service) 146 s2 := NewTestTxnServiceWithLog(t, 2, sender, NewTestClock(0), mlog2).(*service) 147 sender.AddTxnService(s1) 148 sender.AddTxnService(s2) 149 150 assert.NoError(t, s1.Start()) 151 defer func() { 152 assert.NoError(t, s1.Close(false)) 153 }() 154 155 assert.NoError(t, s2.Start()) 156 defer func() { 157 assert.NoError(t, s2.Close(false)) 158 }() 159 160 for e := range s1.storage.(*mem.KVTxnStorage).GetEventC() { 161 if e.Type == mem.CommitType { 162 break 163 } 164 } 165 166 for e := range s2.storage.(*mem.KVTxnStorage).GetEventC() { 167 if e.Type == mem.CommitType { 168 break 169 } 170 } 171 172 checkData(t, wTxn, s1, 2, 1, true) 173 checkData(t, wTxn, s2, 2, 2, true) 174 } 175 176 func TestRecoveryFromMultiTNShardWithAnyNotPrepared(t *testing.T) { 177 mlog1 := mem.NewMemLog() 178 mlog2 := mem.NewMemLog() 179 180 wTxn := NewTestTxn(1, 1, 1, 2) 181 wTxn.Status = txn.TxnStatus_Prepared 182 wTxn.PreparedTS = NewTestTimestamp(2) 183 184 addLog(t, mlog1, wTxn, 1) 185 186 sender := NewTestSender() 187 defer func() { 188 assert.NoError(t, sender.Close()) 189 }() 190 191 s1 := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog1).(*service) 192 s2 := NewTestTxnServiceWithLog(t, 2, sender, NewTestClock(0), mlog2).(*service) 193 sender.AddTxnService(s1) 194 sender.AddTxnService(s2) 195 196 assert.NoError(t, s1.Start()) 197 defer func() { 198 assert.NoError(t, s1.Close(false)) 199 }() 200 201 assert.NoError(t, s2.Start()) 202 defer func() { 203 assert.NoError(t, s2.Close(false)) 204 }() 205 206 for e := range s1.storage.(*mem.KVTxnStorage).GetEventC() { 207 if e.Type == mem.RollbackType { 208 break 209 } 210 } 211 212 checkData(t, wTxn, s1, 0, 1, false) 213 checkData(t, wTxn, s2, 0, 2, false) 214 } 215 216 func TestRecoveryFromMultiTNShardWithCommitting(t *testing.T) { 217 mlog1 := mem.NewMemLog() 218 mlog2 := mem.NewMemLog() 219 220 wTxn := NewTestTxn(1, 1, 1, 2) 221 wTxn.Status = txn.TxnStatus_Prepared 222 wTxn.PreparedTS = NewTestTimestamp(2) 223 224 addLog(t, mlog1, wTxn, 1) 225 addLog(t, mlog2, wTxn, 2) 226 227 wTxn.CommitTS = NewTestTimestamp(2) 228 wTxn.Status = txn.TxnStatus_Committing 229 addLog(t, mlog1, wTxn, 1) 230 231 sender := NewTestSender() 232 defer func() { 233 assert.NoError(t, sender.Close()) 234 }() 235 236 s1 := NewTestTxnServiceWithLog(t, 1, sender, NewTestClock(0), mlog1).(*service) 237 s2 := NewTestTxnServiceWithLog(t, 2, sender, NewTestClock(0), mlog2).(*service) 238 sender.AddTxnService(s1) 239 sender.AddTxnService(s2) 240 241 assert.NoError(t, s1.Start()) 242 defer func() { 243 assert.NoError(t, s1.Close(false)) 244 }() 245 246 assert.NoError(t, s2.Start()) 247 defer func() { 248 assert.NoError(t, s2.Close(false)) 249 }() 250 251 for e := range s1.storage.(*mem.KVTxnStorage).GetEventC() { 252 if e.Type == mem.CommitType { 253 break 254 } 255 } 256 257 for e := range s2.storage.(*mem.KVTxnStorage).GetEventC() { 258 if e.Type == mem.CommitType { 259 break 260 } 261 } 262 263 checkData(t, wTxn, s1, 2, 1, true) 264 checkData(t, wTxn, s2, 2, 2, true) 265 } 266 267 func addLog(t *testing.T, l logservice.Client, wTxn txn.TxnMeta, keys ...byte) { 268 klog := mem.KVLog{ 269 Txn: wTxn, 270 } 271 for _, k := range keys { 272 klog.Keys = append(klog.Keys, GetTestKey(k)) 273 klog.Values = append(klog.Values, GetTestValue(k, wTxn)) 274 } 275 276 _, err := l.Append(context.Background(), logservice.LogRecord{ 277 Data: klog.MustMarshal(), 278 }) 279 assert.NoError(t, err) 280 }