github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/logtail/service/service_test.go (about)

     1  // Copyright 2021 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  	"math"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/stretchr/testify/require"
    24  
    25  	"github.com/matrixorigin/matrixone/pkg/common/morpc"
    26  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    27  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    28  	"github.com/matrixorigin/matrixone/pkg/logutil"
    29  	"github.com/matrixorigin/matrixone/pkg/pb/api"
    30  	"github.com/matrixorigin/matrixone/pkg/pb/logtail"
    31  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    32  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    33  	"github.com/matrixorigin/matrixone/pkg/tests"
    34  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    35  	taelogtail "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logtail"
    36  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/options"
    37  )
    38  
    39  func TestService(t *testing.T) {
    40  	tableA := mockTable(1, 1, 1)
    41  	tableB := mockTable(2, 2, 2)
    42  	tableC := mockTable(3, 3, 3)
    43  
    44  	addrs, err := tests.GetAddressBatch("127.0.0.1", 1)
    45  	require.NoError(t, err)
    46  
    47  	address := addrs[0]
    48  	logtailer := mockLocktailer(tableA, tableB, tableC)
    49  	rt := mockRuntime()
    50  
    51  	/* ---- construct logtail server ---- */
    52  	logtailServer, err := NewLogtailServer(
    53  		address, options.NewDefaultLogtailServerCfg(), logtailer, rt,
    54  		WithServerCollectInterval(500*time.Millisecond),
    55  		WithServerSendTimeout(5*time.Second),
    56  		WithServerEnableChecksum(true),
    57  		WithServerMaxMessageSize(32+7),
    58  		WithServerPayloadCopyBufferSize(16*mpool.KB),
    59  		WithServerMaxLogtailFetchFailure(5),
    60  	)
    61  	require.NoError(t, err)
    62  
    63  	/* ---- start logtail server ---- */
    64  	err = logtailServer.Start()
    65  	require.NoError(t, err)
    66  	defer func() {
    67  		err := logtailServer.Close()
    68  		require.NoError(t, err)
    69  	}()
    70  
    71  	/* ---- construct logtail client ---- */
    72  	codec := morpc.NewMessageCodec(func() morpc.Message { return &LogtailResponseSegment{} },
    73  		morpc.WithCodecPayloadCopyBufferSize(16*mpool.KB),
    74  		morpc.WithCodecEnableChecksum(),
    75  		morpc.WithCodecMaxBodySize(16*mpool.KB),
    76  	)
    77  	bf := morpc.NewGoettyBasedBackendFactory(codec)
    78  	rpcClient, err := morpc.NewClient(bf, morpc.WithClientMaxBackendPerHost(1))
    79  	require.NoError(t, err)
    80  
    81  	rpcStream, err := rpcClient.NewStream(address, false)
    82  	require.NoError(t, err)
    83  
    84  	logtailClient, err := NewLogtailClient(rpcStream, WithClientRequestPerSecond(100))
    85  	require.NoError(t, err)
    86  	defer func() {
    87  		err := logtailClient.Close()
    88  		require.NoError(t, err)
    89  	}()
    90  
    91  	/* ---- send subscription request via logtail client ---- */
    92  	{
    93  		t.Log("send subscription request via logtail client")
    94  		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    95  		defer cancel()
    96  		err := logtailClient.Subscribe(ctx, tableA)
    97  		require.NoError(t, err)
    98  	}
    99  
   100  	/* ---- wait subscription response via logtail client ---- */
   101  	{
   102  		t.Log("wait subscription response via logtail client")
   103  		resp, err := logtailClient.Receive()
   104  		require.NoError(t, err)
   105  		require.NotNil(t, resp.GetSubscribeResponse())
   106  		require.Equal(t, tableA.String(), resp.GetSubscribeResponse().Logtail.Table.String())
   107  	}
   108  
   109  	/* ---- wait update response via logtail client ---- */
   110  	{
   111  		t.Log("wait update response via logtail client")
   112  		resp, err := logtailClient.Receive()
   113  		require.NoError(t, err)
   114  		require.NotNil(t, resp.GetUpdateResponse())
   115  		require.Equal(t, 1, len(resp.GetUpdateResponse().LogtailList))
   116  		require.Equal(t, tableA.String(), resp.GetUpdateResponse().LogtailList[0].Table.String())
   117  	}
   118  
   119  	/* ---- send unsubscription request via logtail client ---- */
   120  	{
   121  		t.Log("send unsubscription request via logtail client")
   122  		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   123  		defer cancel()
   124  		err := logtailClient.Unsubscribe(ctx, tableA)
   125  		require.NoError(t, err)
   126  	}
   127  
   128  	/* ---- wait subscription response via logtail client ---- */
   129  	{
   130  		t.Log("wait unsubscription response via logtail client")
   131  		for {
   132  			resp, err := logtailClient.Receive()
   133  			require.NoError(t, err)
   134  			if resp.GetUnsubscribeResponse() != nil {
   135  				require.Equal(t, tableA.String(), resp.GetUnsubscribeResponse().Table.String())
   136  				break
   137  			}
   138  		}
   139  	}
   140  
   141  	/* ---- wait update response via logtail client ---- */
   142  	{
   143  		t.Log("wait update response via logtail client")
   144  		resp, err := logtailClient.Receive()
   145  		require.NoError(t, err)
   146  		require.NotNil(t, resp.GetUpdateResponse())
   147  		require.Equal(t, 0, len(resp.GetUpdateResponse().LogtailList))
   148  	}
   149  }
   150  
   151  type logtailer struct {
   152  	tables []api.TableID
   153  }
   154  
   155  func mockLocktailer(tables ...api.TableID) taelogtail.Logtailer {
   156  	return &logtailer{
   157  		tables: tables,
   158  	}
   159  }
   160  
   161  func (m *logtailer) RangeLogtail(
   162  	ctx context.Context, from, to timestamp.Timestamp,
   163  ) ([]logtail.TableLogtail, error) {
   164  	tails := make([]logtail.TableLogtail, 0, len(m.tables))
   165  	for _, table := range m.tables {
   166  		tails = append(tails, mockLogtail(table))
   167  	}
   168  	return tails, nil
   169  }
   170  
   171  func (m *logtailer) TableLogtail(
   172  	ctx context.Context, table api.TableID, from, to timestamp.Timestamp,
   173  ) (logtail.TableLogtail, error) {
   174  	for _, t := range m.tables {
   175  		if t.String() == table.String() {
   176  			return mockLogtail(table), nil
   177  		}
   178  	}
   179  	return logtail.TableLogtail{CkpLocation: "checkpoint", Table: &table, Ts: &to}, nil
   180  }
   181  
   182  func mockRuntime() runtime.Runtime {
   183  	return runtime.NewRuntime(
   184  		metadata.ServiceType_DN,
   185  		"uuid",
   186  		logutil.GetLogger(),
   187  		runtime.WithClock(
   188  			clock.NewHLCClock(
   189  				func() int64 { return time.Now().UTC().UnixNano() },
   190  				time.Duration(math.MaxInt64),
   191  			),
   192  		),
   193  	)
   194  }