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  }