From dcacdaa36f89272c791bef065a04262af9f5bf19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Tue, 16 Jun 2026 09:29:20 +0200 Subject: [PATCH 1/2] Modernize pkg --- pkg/api/internal/rest/request.go | 9 +- pkg/api/internal/rest/request_test.go | 3 +- pkg/applier/redo_test.go | 9 +- pkg/causality/conflict_detector.go | 6 +- pkg/causality/internal/slots.go | 2 +- pkg/causality/internal/slots_test.go | 18 +- pkg/causality/tests/driver.go | 2 +- pkg/causality/tests/worker.go | 6 +- pkg/causality/txn_cache_test.go | 4 +- pkg/chann/chann_test.go | 78 ++++---- pkg/chann/drainable_chann_test.go | 2 +- pkg/chdelay/channel_delayer_test.go | 14 +- pkg/cmd/factory/factory_impl_test.go | 4 +- pkg/cmd/server/server.go | 2 +- pkg/cmd/util/helper.go | 12 +- pkg/cmd/util/helper_test.go | 2 +- pkg/column-mapping/column.go | 10 +- pkg/column-mapping/column_test.go | 26 +-- pkg/compression/compress.go | 4 +- pkg/config/replica_config.go | 2 +- pkg/config/server_config.go | 8 +- pkg/container/queue/chunkqueue.go | 22 +-- pkg/container/queue/chunkqueue_test.go | 30 +-- pkg/container/queue/iterator_test.go | 22 +-- pkg/container/sortmap/sort.go | 7 +- pkg/diff/checkpoint.go | 4 +- pkg/diff/diff.go | 4 +- pkg/diff/merge.go | 4 +- pkg/diff/merge_test.go | 2 +- pkg/diff/spliter_test.go | 32 +-- pkg/diff/util.go | 8 +- pkg/election/elector_test.go | 32 ++- pkg/election/storage_orm.go | 2 +- pkg/election/storage_sql_test.go | 3 +- pkg/errors/helper.go | 4 +- pkg/errors/helper_test.go | 4 +- pkg/etcd/client.go | 10 +- pkg/etcd/client_test.go | 3 +- pkg/etcd/etcd.go | 2 +- pkg/etcd/etcd_test.go | 5 +- pkg/etcd/util_test.go | 2 +- pkg/filter/expr_filter_bench_test.go | 14 +- pkg/filter/expr_filter_test.go | 120 ++++++------ pkg/filter/filter.go | 9 +- pkg/filter/sql_event_filter_test.go | 1 - pkg/filter/utils.go | 8 +- pkg/fsutil/file_allocator.go | 6 +- pkg/fsutil/file_allocator_test.go | 2 +- pkg/importer/db.go | 4 +- pkg/importer/job.go | 6 +- pkg/importer/parser.go | 33 ++-- pkg/label/label_test.go | 2 - pkg/label/selector_test.go | 10 +- pkg/leakutil/leak_helper_test.go | 2 +- pkg/logutil/log.go | 7 +- pkg/logutil/log_test.go | 6 +- pkg/migrate/migrate_test.go | 50 ++--- pkg/notify/notify_test.go | 22 +-- pkg/orchestrator/batch.go | 6 +- pkg/orchestrator/batch_test.go | 8 +- pkg/orchestrator/etcd_worker_bank_test.go | 12 +- pkg/orchestrator/etcd_worker_test.go | 12 +- pkg/orchestrator/reactor_state.go | 17 +- pkg/p2p/client.go | 8 +- pkg/p2p/client_batch_sender.go | 5 +- pkg/p2p/client_batch_sender_test.go | 16 +- pkg/p2p/client_connector_test.go | 6 +- pkg/p2p/grpc_client.go | 11 +- pkg/p2p/grpc_client_test.go | 18 +- pkg/p2p/internal/send_chan_test.go | 58 ++---- pkg/p2p/message_router.go | 6 +- pkg/p2p/message_router_test.go | 40 ++-- pkg/p2p/mock_cluster.go | 20 +- pkg/p2p/model.go | 2 +- pkg/p2p/serializer.go | 4 +- pkg/p2p/server.go | 16 +- pkg/p2p/server_ack_manager.go | 2 +- pkg/p2p/server_client_integration_test.go | 98 ++++------ pkg/p2p/server_stream_handle_test.go | 12 +- pkg/p2p/server_test.go | 172 ++++++---------- pkg/p2p/server_wrapper_test.go | 6 +- pkg/pdutil/api_client_test.go | 13 +- pkg/pdutil/clock_test.go | 3 +- pkg/retry/retry_test.go | 2 +- pkg/security/credential.go | 2 +- pkg/security/sasl_test.go | 2 - pkg/sink/cloudstorage/path_test.go | 15 +- pkg/sink/cloudstorage/table_definition.go | 16 +- .../cloudstorage/table_definition_test.go | 2 +- pkg/sink/codec/avro/avro.go | 50 ++--- pkg/sink/codec/avro/avro_test.go | 29 ++- .../avro/confluent_schema_registry_test.go | 14 +- pkg/sink/codec/avro/decoder.go | 46 ++--- pkg/sink/codec/bootstraper.go | 4 +- pkg/sink/codec/bootstraper_test.go | 3 +- pkg/sink/codec/canal/canal_entry.go | 4 +- pkg/sink/codec/canal/canal_json_decoder.go | 20 +- pkg/sink/codec/canal/canal_json_message.go | 16 +- pkg/sink/codec/common/helper.go | 16 +- pkg/sink/codec/common/verify_checksum.go | 6 +- pkg/sink/codec/craft/craft_encoder_test.go | 4 +- pkg/sink/codec/craft/message_decoder.go | 18 +- pkg/sink/codec/craft/message_encoder.go | 2 +- pkg/sink/codec/csv/csv_decoder_test.go | 2 +- pkg/sink/codec/csv/csv_message_test.go | 2 +- pkg/sink/codec/debezium/codec.go | 2 +- pkg/sink/codec/debezium/debezium_test.go | 2 +- pkg/sink/codec/debezium/decoder.go | 38 ++-- pkg/sink/codec/encoder.go | 2 +- pkg/sink/codec/maxwell/maxwell_message.go | 28 +-- .../codec/maxwell/maxwell_message_test.go | 2 +- pkg/sink/codec/open/open_protocol_decoder.go | 14 +- .../codec/open/open_protocol_encoder_test.go | 4 +- pkg/sink/codec/simple/avro.go | 184 +++++++++--------- pkg/sink/codec/simple/decoder.go | 6 +- pkg/sink/codec/simple/encoder_test.go | 13 +- pkg/sink/codec/simple/marshaller.go | 2 +- pkg/sink/codec/simple/message.go | 36 ++-- pkg/sink/codec/utils/test_utils.go | 2 +- pkg/sink/kafka/options_test.go | 38 ++-- pkg/sink/kafka/sarama_test.go | 2 - pkg/sink/observer/observer_test.go | 8 +- pkg/sink/observer/tidb.go | 18 +- pkg/sink/pulsar/logger.go | 18 +- pkg/spanz/btree_map_test.go | 2 +- pkg/spanz/convert.go | 7 +- pkg/spanz/convert_test.go | 2 +- pkg/spanz/hash_map_test.go | 2 +- pkg/spanz/map_bench_test.go | 2 +- pkg/sqlmodel/causality.go | 16 +- pkg/sqlmodel/causality_fk_test.go | 4 +- pkg/sqlmodel/causality_test.go | 60 +++--- pkg/sqlmodel/multirow.go | 10 +- pkg/sqlmodel/multirow_bench_test.go | 12 +- pkg/sqlmodel/multirow_test.go | 54 ++--- pkg/sqlmodel/reduce.go | 16 +- pkg/sqlmodel/reduce_test.go | 76 ++++---- pkg/sqlmodel/row_change.go | 28 +-- pkg/sqlmodel/row_change_test.go | 112 +++++------ pkg/sqlmodel/utils.go | 10 +- pkg/sqlmodel/where_handle.go | 2 +- pkg/sqlmodel/where_handle_test.go | 6 +- pkg/tcpserver/tcp_server_test.go | 84 +++----- pkg/upstream/manager.go | 6 +- pkg/upstream/upstream.go | 6 +- pkg/upstream/upstream_test.go | 7 +- pkg/util/atomic_test.go | 6 +- pkg/util/json_writer.go | 2 +- pkg/util/seahash/seahash_test.go | 2 +- pkg/util/test_helper_test.go | 2 +- pkg/uuid/uuid_test.go | 2 +- pkg/version/check_test.go | 4 +- pkg/workerpool/async_pool_test.go | 4 +- pkg/workerpool/pool.go | 6 +- pkg/workerpool/pool_impl.go | 10 +- pkg/workerpool/pool_test.go | 66 +++---- 156 files changed, 1159 insertions(+), 1461 deletions(-) diff --git a/pkg/api/internal/rest/request.go b/pkg/api/internal/rest/request.go index 4fa31e0856..cbbec9ba6b 100644 --- a/pkg/api/internal/rest/request.go +++ b/pkg/api/internal/rest/request.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "io" + "maps" "net/http" "net/url" "path" @@ -129,9 +130,7 @@ func (r *Request) WithURI(uri string) *Request { if r.params == nil { r.params = make(url.Values) } - for k, v := range vals { - r.params[k] = v - } + maps.Copy(r.params, vals) } return r } @@ -210,7 +209,7 @@ func (r *Request) WithMaxRetries(maxRetries uint64) *Request { // only supports two types now: // 1. io.Reader // 2. type which can be json marshalled -func (r *Request) WithBody(obj interface{}) *Request { +func (r *Request) WithBody(obj any) *Request { if r.err != nil { return r } @@ -406,7 +405,7 @@ func (r Result) Error() error { } // Into stores the http response body into obj. -func (r Result) Into(obj interface{}) error { +func (r Result) Into(obj any) error { if r.err != nil { return r.err } diff --git a/pkg/api/internal/rest/request_test.go b/pkg/api/internal/rest/request_test.go index be0f4d19a7..5684cbd224 100644 --- a/pkg/api/internal/rest/request_test.go +++ b/pkg/api/internal/rest/request_test.go @@ -128,8 +128,7 @@ func TestRequestDoContextTimeout(t *testing.T) { })) defer testServer.Close() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() c, err := CDCRESTClientFromConfig(&Config{ Host: testServer.URL, diff --git a/pkg/applier/redo_test.go b/pkg/applier/redo_test.go index 6b67e57e65..fcde318266 100644 --- a/pkg/applier/redo_test.go +++ b/pkg/applier/redo_test.go @@ -89,8 +89,7 @@ func (br *MockReader) ReadMeta(ctx context.Context) (checkpointTs, resolvedTs ui } func TestApply(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() checkpointTs := uint64(1000) resolvedTs := uint64(2000) @@ -303,8 +302,7 @@ func TestApply(t *testing.T) { } func TestApplyBigTxn(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() checkpointTs := uint64(1000) resolvedTs := uint64(2000) @@ -479,8 +477,7 @@ func TestApplyBigTxn(t *testing.T) { } func TestApplyMeetSinkError(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() port, err := freeport.GetFreePort() require.Nil(t, err) diff --git a/pkg/causality/conflict_detector.go b/pkg/causality/conflict_detector.go index 417fda4f21..5dc269354e 100644 --- a/pkg/causality/conflict_detector.go +++ b/pkg/causality/conflict_detector.go @@ -61,11 +61,9 @@ func NewConflictDetector[Txn txnEvent]( ret.resolvedTxnCaches[i] = newTxnCache[Txn](opt) } - ret.wg.Add(1) - go func() { - defer ret.wg.Done() + ret.wg.Go(func() { ret.runBackgroundTasks() - }() + }) return ret } diff --git a/pkg/causality/internal/slots.go b/pkg/causality/internal/slots.go index 99e32ca429..15c2dabb2b 100644 --- a/pkg/causality/internal/slots.go +++ b/pkg/causality/internal/slots.go @@ -35,7 +35,7 @@ type Slots struct { // NewSlots creates a new Slots. func NewSlots(numSlots uint64) *Slots { slots := make([]slot, numSlots) - for i := uint64(0); i < numSlots; i++ { + for i := range numSlots { slots[i].nodes = make(map[uint64]*Node, 8) } return &Slots{ diff --git a/pkg/causality/internal/slots_test.go b/pkg/causality/internal/slots_test.go index 312523355a..e508b06d7b 100644 --- a/pkg/causality/internal/slots_test.go +++ b/pkg/causality/internal/slots_test.go @@ -29,13 +29,13 @@ func TestSlotsTrivial(t *testing.T) { slots := NewSlots(8) nodes := make([]*Node, 0, 1000) - for i := 0; i < count; i++ { + for range count { node := newNodeForTest(1, 2, 3, 4, 5) slots.Add(node) nodes = append(nodes, node) } - for i := 0; i < count; i++ { + for i := range count { slots.Remove(nodes[i]) } @@ -53,7 +53,7 @@ func TestSlotsConcurrentOps(t *testing.T) { slots := NewSlots(8) freeNodeChan := make(chan *Node, N) inuseNodeChan := make(chan *Node, N) - for i := 0; i < N; i++ { + for range N { freeNodeChan <- newNodeForTest(1, 9, 17, 25, 33) } @@ -62,9 +62,7 @@ func TestSlotsConcurrentOps(t *testing.T) { // test concurrent add and remove won't panic var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { select { case <-ctx.Done(): @@ -75,11 +73,9 @@ func TestSlotsConcurrentOps(t *testing.T) { inuseNodeChan <- node } } - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { select { case <-ctx.Done(): @@ -90,7 +86,7 @@ func TestSlotsConcurrentOps(t *testing.T) { freeNodeChan <- newNodeForTest(1, 9, 17, 25, 33) } } - }() + }) wg.Wait() } diff --git a/pkg/causality/tests/driver.go b/pkg/causality/tests/driver.go index bac3aa50c4..c06d02397e 100644 --- a/pkg/causality/tests/driver.go +++ b/pkg/causality/tests/driver.go @@ -43,7 +43,7 @@ func newConflictTestDriver( }) workers := make([]*workerForTest, 0, numWorkers) - for i := 0; i < numWorkers; i++ { + for i := range numWorkers { id := int64(i) workers = append(workers, newWorkerForTest(detector.GetOutChByCacheID(id))) } diff --git a/pkg/causality/tests/worker.go b/pkg/causality/tests/worker.go index 363fce7526..ba4aa84740 100644 --- a/pkg/causality/tests/worker.go +++ b/pkg/causality/tests/worker.go @@ -55,11 +55,9 @@ func newWorkerForTest(txnCh <-chan causality.TxnWithNotifier[*txnForTest]) *work closeCh: make(chan struct{}), } - ret.wg.Add(1) - go func() { - defer ret.wg.Done() + ret.wg.Go(func() { ret.run(txnCh) - }() + }) return ret } diff --git a/pkg/causality/txn_cache_test.go b/pkg/causality/txn_cache_test.go index d83a937c5c..b3bdff1801 100644 --- a/pkg/causality/txn_cache_test.go +++ b/pkg/causality/txn_cache_test.go @@ -38,7 +38,7 @@ func TestBoundedWorker(t *testing.T) { Size: size, BlockStrategy: BlockStrategyWaitAvailable, }) - for i := 0; i < size; i++ { + for range size { // Add 10 events to the worker. ok := worker.add(TxnWithNotifier[txnEvent]{ TxnEvent: mockTxnEvent{}, @@ -66,7 +66,7 @@ func TestBoundedWorkerWithBlock(t *testing.T) { Size: size, BlockStrategy: BlockStrategyWaitEmpty, }) - for i := 0; i < size; i++ { + for range size { // Add 10 events to the worker. ok := worker.add(TxnWithNotifier[txnEvent]{ TxnEvent: mockTxnEvent{}, diff --git a/pkg/chann/chann_test.go b/pkg/chann/chann_test.go index 7b56f7e869..c7151ce9df 100644 --- a/pkg/chann/chann_test.go +++ b/pkg/chann/chann_test.go @@ -131,22 +131,22 @@ func TestChan(t *testing.T) { // ensure that we receive them non-corrupted in FIFO order. c := New[int](Cap(chanCap)) go func() { - for i := 0; i < 100; i++ { + for i := range 100 { c.In() <- i } }() - for i := 0; i < 100; i++ { + for i := range 100 { v := <-c.Out() require.Equalf(t, i, v, "chan[%d]", chanCap) } // Same, but using recv2. go func() { - for i := 0; i < 100; i++ { + for i := range 100 { c.In() <- i } }() - for i := 0; i < 100; i++ { + for i := range 100 { v, ok := <-c.Out() require.Truef(t, ok, "chan[%d]: receive failed, expected %v", chanCap, i) require.Equalf(t, i, v, "chan[%d]", chanCap) @@ -156,18 +156,18 @@ func TestChan(t *testing.T) { // ensure that we receive what we send. const P = 4 const L = 1000 - for p := 0; p < P; p++ { + for range P { go func() { - for i := 0; i < L; i++ { + for i := range L { c.In() <- i } }() } done := New[map[int]int](Cap(0)) - for p := 0; p < P; p++ { + for range P { go func() { recv := make(map[int]int) - for i := 0; i < L; i++ { + for range L { v := <-c.Out() recv[v] = recv[v] + 1 } @@ -175,7 +175,7 @@ func TestChan(t *testing.T) { }() } recv := make(map[int]int) - for p := 0; p < P; p++ { + for range P { for k, v := range <-done.Out() { recv[k] = recv[k] + v } @@ -242,7 +242,7 @@ const internalCacheSize = 16 + 1<<10 func TestNonblockSelectRace(t *testing.T) { n := 1000 done := New[bool](Cap(1)) - for i := 0; i < n; i++ { + for range n { c1 := New[int]() c2 := New[int]() // The input channel of an unbounded buffer have an internal @@ -250,7 +250,7 @@ func TestNonblockSelectRace(t *testing.T) { // queue both gets full, we are certain that once the next send // is complete, the out will be available for sure hence the // waiting time of a receive is bounded. - for i := 0; i < internalCacheSize; i++ { + for range internalCacheSize { c1.In() <- 1 } c1.In() <- 1 @@ -266,7 +266,7 @@ func TestNonblockSelectRace(t *testing.T) { done.In() <- true }() // Same for c2 - for i := 0; i < internalCacheSize; i++ { + for range internalCacheSize { c2.In() <- 1 } c2.In() <- 1 @@ -289,11 +289,11 @@ func TestNonblockSelectRace(t *testing.T) { func TestNonblockSelectRace2(t *testing.T) { n := 1000 done := make(chan bool, 1) - for i := 0; i < n; i++ { + for range n { c1 := New[int]() c2 := New[int]() // See TestNonblockSelectRace. - for i := 0; i < internalCacheSize; i++ { + for range internalCacheSize { c1.In() <- 1 } c1.In() <- 1 @@ -331,17 +331,15 @@ func TestUnboundedChann(t *testing.T) { t.Run("interface{}", func(t *testing.T) { t.Run("send", func(t *testing.T) { // Ensure send to an unbounded channel does not block. - c := New[interface{}]() + c := New[any]() blocked := false - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case c.In() <- true: default: blocked = true } - }() + }) wg.Wait() require.Falsef(t, blocked, "send op to an unbounded channel blocked") c.Close() @@ -350,23 +348,21 @@ func TestUnboundedChann(t *testing.T) { t.Run("recv", func(t *testing.T) { // Ensure that receive op from unbounded chan can happen on // the same goroutine of send op. - c := New[interface{}]() - wg.Add(1) - go func() { - defer wg.Done() + c := New[any]() + wg.Go(func() { c.In() <- true <-c.Out() - }() + }) wg.Wait() c.Close() }) t.Run("order", func(t *testing.T) { // Ensure that the unbounded channel processes everything FIFO. - c := New[interface{}]() - for i := 0; i < 1<<11; i++ { + c := New[any]() + for i := range 1 << 11 { c.In() <- i } - for i := 0; i < 1<<11; i++ { + for i := range 1 << 11 { val := <-c.Out() require.Equalf( t, @@ -383,15 +379,13 @@ func TestUnboundedChann(t *testing.T) { // Ensure send to an unbounded channel does not block. c := New[struct{}]() blocked := false - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case c.In() <- struct{}{}: default: blocked = true } - }() + }) <-c.Out() wg.Wait() require.Falsef(t, blocked, "send op to an unbounded channel blocked") @@ -402,23 +396,21 @@ func TestUnboundedChann(t *testing.T) { // Ensure that receive op from unbounded chan can happen on // the same goroutine of send op. c := New[struct{}]() - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { c.In() <- struct{}{} <-c.Out() - }() + }) wg.Wait() c.Close() }) t.Run("order", func(t *testing.T) { // Ensure that the unbounded channel processes everything FIFO. c := New[struct{}]() - for i := 0; i < 1<<11; i++ { + for range 1 << 11 { c.In() <- struct{}{} } n := 0 - for i := 0; i < 1<<11; i++ { + for range 1 << 11 { if _, ok := <-c.Out(); ok { n++ } @@ -433,7 +425,7 @@ func TestUnboundedChann(t *testing.T) { func TestUnboundedChannClose(t *testing.T) { t.Run("close-status", func(t *testing.T) { ch := New[any]() - for i := 0; i < 100; i++ { + for range 100 { ch.In() <- 0 } ch.Close() @@ -455,7 +447,7 @@ func TestUnboundedChannClose(t *testing.T) { n := 0 done := make(chan struct{}) ch := New[struct{}]() - for i := 0; i < N; i++ { + for range N { ch.In() <- struct{}{} } go func() { @@ -476,8 +468,8 @@ func TestUnboundedChannClose(t *testing.T) { N := 10 n := 0 done := make(chan struct{}) - ch := New[interface{}]() - for i := 0; i < N; i++ { + ch := New[any]() + for range N { ch.In() <- true } go func() { @@ -497,7 +489,7 @@ func TestUnboundedChannClose(t *testing.T) { func BenchmarkUnboundedChann(b *testing.B) { b.Run("interface{}", func(b *testing.B) { b.Run("sync", func(b *testing.B) { - c := New[interface{}]() + c := New[any]() defer c.Close() b.ResetTimer() b.ReportAllocs() @@ -507,7 +499,7 @@ func BenchmarkUnboundedChann(b *testing.B) { } }) b.Run("chann", func(b *testing.B) { - c := New[interface{}]() + c := New[any]() defer c.Close() b.ResetTimer() b.ReportAllocs() diff --git a/pkg/chann/drainable_chann_test.go b/pkg/chann/drainable_chann_test.go index e4dcd4b7e9..49490bece8 100644 --- a/pkg/chann/drainable_chann_test.go +++ b/pkg/chann/drainable_chann_test.go @@ -17,7 +17,7 @@ import "testing" func TestCloseAndDrain(t *testing.T) { ch := NewAutoDrainChann[int]() - for i := 0; i < 100; i++ { + for i := range 100 { ch.In() <- i } diff --git a/pkg/chdelay/channel_delayer_test.go b/pkg/chdelay/channel_delayer_test.go index 8433abbdf8..9d657d5ba8 100644 --- a/pkg/chdelay/channel_delayer_test.go +++ b/pkg/chdelay/channel_delayer_test.go @@ -38,19 +38,15 @@ func testChannelDelayer(t *testing.T, delayBy time.Duration, count int) { delayer := NewChannelDelayer(delayBy, inCh, 1024, 16) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer close(inCh) - for i := 0; i < count; i++ { + for range count { inCh <- time.Now() } - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { counter := 0 for ts := range delayer.Out() { @@ -59,7 +55,7 @@ func testChannelDelayer(t *testing.T, delayBy time.Duration, count int) { } require.Equal(t, count, counter) - }() + }) wg.Wait() delayer.Close() diff --git a/pkg/cmd/factory/factory_impl_test.go b/pkg/cmd/factory/factory_impl_test.go index 4f33e673c1..e2275ae695 100644 --- a/pkg/cmd/factory/factory_impl_test.go +++ b/pkg/cmd/factory/factory_impl_test.go @@ -14,7 +14,6 @@ package factory import ( - "context" "testing" "github.com/golang/mock/gomock" @@ -33,8 +32,7 @@ func TestFactoryImplPdClient(t *testing.T) { t.Parallel() c := mock_factory.NewMockClientGetter(gomock.NewController(t)) f := factoryImpl{ClientGetter: c} - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() cmdcontext.SetDefaultContext(ctx) var certAllowedCN []string diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index b5799afecb..0285e80a0c 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -232,7 +232,7 @@ func (o *Options) validate() error { if len(o.ServerPdAddr) == 0 { return cerror.ErrInvalidServerOption.GenWithStack("empty PD address") } - for _, ep := range strings.Split(o.ServerPdAddr, ",") { + for ep := range strings.SplitSeq(o.ServerPdAddr, ",") { // NOTICE: The configuration used here is the one that has been completed, // as it may be configured by the configuration file. if err := util.VerifyPdEndpoint(ep, o.ServerConfig.Security.IsTLSEnabled()); err != nil { diff --git a/pkg/cmd/util/helper.go b/pkg/cmd/util/helper.go index d0256d1b58..736a5d34dd 100644 --- a/pkg/cmd/util/helper.go +++ b/pkg/cmd/util/helper.go @@ -19,6 +19,7 @@ import ( "net/url" "os" "os/signal" + "slices" "strings" "syscall" @@ -117,7 +118,7 @@ func findProxyFields() []zap.Field { // StrictDecodeFile decodes the toml file strictly. If any item in confFile file is not mapped // into the Config struct, issue an error and stop the server from starting. -func StrictDecodeFile(path, component string, cfg interface{}, ignoreCheckItems ...string) error { +func StrictDecodeFile(path, component string, cfg any, ignoreCheckItems ...string) error { metaData, err := toml.DecodeFile(path, cfg) if err != nil { return errors.Trace(err) @@ -125,12 +126,7 @@ func StrictDecodeFile(path, component string, cfg interface{}, ignoreCheckItems // check if item is a ignoreCheckItem hasIgnoreItem := func(item []string) bool { - for _, ignoreCheckItem := range ignoreCheckItems { - if item[0] == ignoreCheckItem { - return true - } - } - return false + return slices.Contains(ignoreCheckItems, item[0]) } if undecoded := metaData.Undecoded(); len(undecoded) > 0 { @@ -179,7 +175,7 @@ func VerifyPdEndpoint(pdEndpoint string, useTLS bool) error { } // JSONPrint will output the data in JSON format. -func JSONPrint(cmd *cobra.Command, v interface{}) error { +func JSONPrint(cmd *cobra.Command, v any) error { data, err := json.MarshalIndent(v, "", " ") if err != nil { return err diff --git a/pkg/cmd/util/helper_test.go b/pkg/cmd/util/helper_test.go index b436a0551e..b245ee1467 100644 --- a/pkg/cmd/util/helper_test.go +++ b/pkg/cmd/util/helper_test.go @@ -45,7 +45,7 @@ func TestProxyFields(t *testing.T) { require.Nil(t, os.Unsetenv(env)) } - for i := 0; i < 3; i++ { + for i := range 3 { if (1< 0 { - addLen = q.chunkLength - c.r - if addLen > n { - addLen = n - } + addLen = min(q.chunkLength-c.r, n) copy(c.data[c.r:c.r+addLen], vals[cnt:cnt+addLen]) c.r += addLen q.size += addLen @@ -308,10 +299,7 @@ func (q *ChunkQueue[T]) PopMany(n int) ([]T, bool) { cnt := 0 for i := q.head; i < q.tail && cnt < n; i++ { c := q.chunks[i] - popLen := c.len() - if n-cnt < popLen { - popLen = n - cnt - } + popLen := min(n-cnt, c.len()) for j := 0; j < popLen; j++ { res[cnt+j] = c.data[c.l+j] c.data[c.l+j] = q.defaultValue diff --git a/pkg/container/queue/chunkqueue_test.go b/pkg/container/queue/chunkqueue_test.go index 7138d46ee8..e161763cbb 100644 --- a/pkg/container/queue/chunkqueue_test.go +++ b/pkg/container/queue/chunkqueue_test.go @@ -47,7 +47,7 @@ func TestChunkQueueCommon(t *testing.T) { // PushMany & PopMany elements := make([]int, 0, testCaseSize) require.True(t, q.Empty()) - for i := 0; i < testCaseSize; i++ { + for i := range testCaseSize { elements = append(elements, i) } q.PushMany(elements...) @@ -66,7 +66,7 @@ func TestChunkQueueCommon(t *testing.T) { q.PushMany(elements...) require.Equal(t, testCaseSize, q.Len()) require.False(t, q.Empty()) - for j := 0; j < testCaseSize; j++ { + for range testCaseSize { i := rand.Intn(testCaseSize) v := q.Peek(i) it := q.GetIterator(i) @@ -89,7 +89,7 @@ func TestChunkQueueCommon(t *testing.T) { require.True(t, ok) // Pop one by one - for i := 0; i < testCaseSize; i++ { + for i := range testCaseSize { h, ok := q.Head() require.Equal(t, i, h) require.True(t, ok) @@ -161,7 +161,7 @@ func doRandomTest[T comparable](t *testing.T, getVal func() T) { q := NewChunkQueue[T]() slice := make([]T, 0, 100) var val T - for i := 0; i < 100; i++ { + for i := range 100 { op := rand.Intn(4) if i == 99 { op = opPopAll @@ -174,7 +174,7 @@ func doRandomTest[T comparable](t *testing.T, getVal func() T) { case opPushMany: n := rand.Intn(1024) + 1 vals := make([]T, n) - for j := 0; j < n; j++ { + for range n { vals = append(vals, getVal()) } q.PushMany(vals...) @@ -201,14 +201,14 @@ func doRandomTest[T comparable](t *testing.T, getVal func() T) { popSlice := slice[0:n] slice = append(make([]T, 0, len(slice[n:])), slice[n:]...) - for i := 0; i < len(pops); i++ { + for i := range pops { require.Equal(t, popSlice[i], pops[i]) } } case opPopAll: pops := q.PopAll() require.Equal(t, len(pops), len(slice)) - for i := 0; i < len(pops); i++ { + for i := range pops { require.Equal(t, slice[i], pops[i]) } slice = slice[:0] @@ -231,7 +231,7 @@ func TestExpand(t *testing.T) { t.Parallel() q := NewChunkQueue[int]() - for i := 0; i < testCaseSize; i++ { + for range testCaseSize { q.Push(1) require.Equal(t, 1, q.Len()) freeSpace := q.Cap() - q.Len() @@ -248,7 +248,7 @@ func TestDequeueMany(t *testing.T) { q := NewChunkQueue[int]() x := testCaseSize - for v := 0; v < x; v++ { + for v := range x { q.Push(v) } f := 0 @@ -280,7 +280,7 @@ func TestRange(t *testing.T) { t.Parallel() q := NewChunkQueue[int]() - for i := 0; i < testCaseSize; i++ { + for i := range testCaseSize { q.Push(i) } @@ -329,7 +329,7 @@ func TestRangeAndPop(t *testing.T) { t.Parallel() q := NewChunkQueue[int]() - for i := 0; i < testCaseSize; i++ { + for i := range testCaseSize { q.Push(i) } @@ -393,7 +393,7 @@ func TestChunkQueuePushMany(t *testing.T) { func prepareSlice(n int) []int { data := make([]int, 0, n) - for i := 0; i < n; i++ { + for i := range n { data = append(data, i) } return data @@ -401,7 +401,7 @@ func prepareSlice(n int) []int { func prepareChunkQueue(n int) *ChunkQueue[int] { q := NewChunkQueue[int]() - for i := 0; i < n; i++ { + for i := range n { q.Push(i) } return q @@ -488,7 +488,7 @@ func BenchmarkPopMany(b *testing.B) { b.Run("PopMany-3rdPartyDeque", func(b *testing.B) { x := b.N q := deque.NewDeque() - for i := 0; i < x; i++ { + for i := range x { q.Enqueue(i) } ls := []int{x / 5, x / 5, x / 5, x / 5, x - x/5*4} @@ -542,7 +542,7 @@ func BenchmarkChunkQueueLoopPop(b *testing.B) { q.RangeAndPop(func(val int) bool { return val < 0 }) - for i := 0; i < x; i++ { + for range x { v, _ := q.Head() if v < 0 { break diff --git a/pkg/container/queue/iterator_test.go b/pkg/container/queue/iterator_test.go index 64e2ef6462..eef071ed53 100644 --- a/pkg/container/queue/iterator_test.go +++ b/pkg/container/queue/iterator_test.go @@ -28,7 +28,7 @@ const ( func TestChunkQueueIteratorPrevNext(t *testing.T) { t.Parallel() q := NewChunkQueue[int]() - for i := 0; i < iterTestSize; i++ { + for i := range iterTestSize { q.Push(i) } @@ -57,7 +57,7 @@ func BenchmarkIterate(b *testing.B) { b.Run("Iterate-ChunkQueue-by-iterator", func(b *testing.B) { q := NewChunkQueue[int]() n := b.N - for i := 0; i < n; i++ { + for i := range n { q.Push(i) } b.ResetTimer() @@ -75,7 +75,7 @@ func BenchmarkIterate(b *testing.B) { b.Run("Iterate-ChunkQueue-by-Peek", func(b *testing.B) { q := NewChunkQueue[int]() n := b.N - for i := 0; i < n; i++ { + for i := range n { q.Push(i) } b.ResetTimer() @@ -91,7 +91,7 @@ func BenchmarkIterate(b *testing.B) { b.Run("Iterate-ChunkQueue-by-Range", func(b *testing.B) { q := NewChunkQueue[int]() n := b.N - for i := 0; i < n; i++ { + for i := range n { q.Push(i) } b.ResetTimer() @@ -107,12 +107,12 @@ func BenchmarkIterate(b *testing.B) { b.Run("Iterate-Slice-byLoop", func(b *testing.B) { n := b.N q := make([]int, n) - for i := 0; i < n; i++ { + for i := range n { q[i] = i } b.ResetTimer() - for i := 0; i < len(q); i++ { + for i := range q { if q[i] != i { panic("error") } @@ -123,7 +123,7 @@ func BenchmarkIterate(b *testing.B) { q := deque.NewDeque() n := b.N - for i := 0; i < n; i++ { + for i := range n { q.Enqueue(i) } b.ResetTimer() @@ -140,12 +140,12 @@ func BenchmarkIterate(b *testing.B) { q := deque.NewDeque() n := b.N - for i := 0; i < n; i++ { + for i := range n { q.Enqueue(i) } b.ResetTimer() - for i := 0; i < n; i++ { + for i := range n { val := q.Peek(i) if val != i { panic("not equal") @@ -169,7 +169,7 @@ func TestChunkQueueGetIterator(t *testing.T) { require.False(t, oldIt.Valid(), oldIt.Prev()) require.True(t, q.Empty()) - for i := 0; i < iterTestSize; i++ { + for i := range iterTestSize { q.Push(i) } require.True(t, q.End().Index() < 0) @@ -179,7 +179,7 @@ func TestChunkQueueGetIterator(t *testing.T) { }) require.NotPanics(t, func() { - for i := 0; i < iterTestSize; i++ { + for i := range iterTestSize { it = q.GetIterator(i) require.Equal(t, i, it.Index(), it.Value(), q.Peek(i)) } diff --git a/pkg/container/sortmap/sort.go b/pkg/container/sortmap/sort.go index 1cb04e6db5..d577a3cf16 100644 --- a/pkg/container/sortmap/sort.go +++ b/pkg/container/sortmap/sort.go @@ -14,19 +14,18 @@ package sortmap import ( + "cmp" "sort" - - "golang.org/x/exp/constraints" ) // Pair represents the KV pairs in the input map of Sort. -type Pair[K constraints.Ordered, V any] struct { +type Pair[K cmp.Ordered, V any] struct { Key K Value V } // Sort converts an unordered golang map to a slice sorted by map key. -func Sort[K constraints.Ordered, V any](m map[K]V) []Pair[K, V] { +func Sort[K cmp.Ordered, V any](m map[K]V) []Pair[K, V] { s := make([]Pair[K, V], 0, len(m)) for k, v := range m { s = append(s, Pair[K, V]{k, v}) diff --git a/pkg/diff/checkpoint.go b/pkg/diff/checkpoint.go index c71d8574ae..7f21bd0ac7 100644 --- a/pkg/diff/checkpoint.go +++ b/pkg/diff/checkpoint.go @@ -126,7 +126,7 @@ func initChunks(ctx context.Context, db *sql.DB, instanceID, schema, table strin valuesPlaceholders := "(?, ?, ?, ?, ?, ?, ?, ?, ?)" valuesPlaceholdersArray := make([]string, 0, batch) - values := make([]interface{}, 0, 9*batch) + values := make([]any, 0, 9*batch) for i, chunk := range chunks { num++ @@ -303,7 +303,7 @@ func createCheckpointTable(ctx context.Context, db *sql.DB) error { // cleanCheckpoint deletes the table's checkpoint info in table `summary` and `chunk` func cleanCheckpoint(ctx context.Context, db *sql.DB, schema, table string) error { where := "`schema` = ? AND `table` = ?" - args := []interface{}{schema, table} + args := []any{schema, table} err := dbutil.DeleteRows(ctx, db, checkpointSchemaName, summaryTableName, where, args) if err != nil { diff --git a/pkg/diff/diff.go b/pkg/diff/diff.go index 6d6ebdc0cb..1f088dc340 100644 --- a/pkg/diff/diff.go +++ b/pkg/diff/diff.go @@ -498,7 +498,7 @@ func (t *TableDiff) compareChecksum(ctx context.Context, chunk *ChunkRange) (boo ) defer close(checksumInfoCh) - getChecksum := func(db *sql.DB, schema, table, limitRange string, tbInfo *model.TableInfo, args []interface{}, tp string) { + getChecksum := func(db *sql.DB, schema, table, limitRange string, tbInfo *model.TableInfo, args []any, tp string) { beginTime := time.Now() checksum, err := dbutil.GetCRC32Checksum(ctx1, db, schema, table, tbInfo, limitRange, args) cost := time.Since(beginTime) @@ -1017,7 +1017,7 @@ func compareData(map1, map2 map[string]*dbutil.ColumnData, orderKeyCols []*model } func getChunkRows(ctx context.Context, db *sql.DB, schema, table string, tableInfo *model.TableInfo, where string, - args []interface{}, collation string, + args []any, collation string, ) (*sql.Rows, []*model.ColumnInfo, error) { _, orderKeyCols := dbutil.SelectUniqueOrderKey(tableInfo) diff --git a/pkg/diff/merge.go b/pkg/diff/merge.go index a36f176e93..d9da7d652a 100644 --- a/pkg/diff/merge.go +++ b/pkg/diff/merge.go @@ -94,12 +94,12 @@ func (r RowDatas) Less(i, j int) bool { func (r RowDatas) Swap(i, j int) { r.Rows[i], r.Rows[j] = r.Rows[j], r.Rows[i] } // Push implements heap.Interface's Push function -func (r *RowDatas) Push(x interface{}) { +func (r *RowDatas) Push(x any) { r.Rows = append(r.Rows, x.(RowData)) } // Pop implements heap.Interface's Pop function -func (r *RowDatas) Pop() interface{} { +func (r *RowDatas) Pop() any { if len(r.Rows) == 0 { return nil } diff --git a/pkg/diff/merge_test.go b/pkg/diff/merge_test.go index ca08055c53..fe7d180430 100644 --- a/pkg/diff/merge_test.go +++ b/pkg/diff/merge_test.go @@ -56,7 +56,7 @@ func (s *testMergerSuite) TestMerge(c *check.C) { }) } - for i := 0; i < len(ids); i++ { + for i := range ids { rowData := heap.Pop(rowDatas).(RowData) id := string(rowData.Data["id"].Data) name := string(rowData.Data["name"].Data) diff --git a/pkg/diff/spliter_test.go b/pkg/diff/spliter_test.go index 77026ace56..40a526c583 100644 --- a/pkg/diff/spliter_test.go +++ b/pkg/diff/spliter_test.go @@ -42,14 +42,14 @@ func (s *testSpliterSuite) TestSplitRangeByRandom(c *check.C) { createTableSQL string splitCount int originChunk *ChunkRange - randomValues [][]interface{} + randomValues [][]any expectResult []chunkResult }{ { "create table `test`.`test`(`a` int, `b` varchar(10), `c` float, `d` datetime, primary key(`a`, `b`))", 3, NewChunkRange().copyAndUpdate("a", "0", "10").copyAndUpdate("b", "a", "z"), - [][]interface{}{ + [][]any{ {5, 7}, {"g", "n"}, }, @@ -69,7 +69,7 @@ func (s *testSpliterSuite) TestSplitRangeByRandom(c *check.C) { "create table `test`.`test`(`a` int, `b` varchar(10), `c` float, `d` datetime, primary key(`b`))", 3, NewChunkRange().copyAndUpdate("b", "a", "z"), - [][]interface{}{ + [][]any{ {"g", "n"}, }, []chunkResult{ @@ -88,7 +88,7 @@ func (s *testSpliterSuite) TestSplitRangeByRandom(c *check.C) { "create table `test`.`test`(`a` int, `b` varchar(10), `c` float, `d` datetime, primary key(`b`))", 2, NewChunkRange().copyAndUpdate("b", "a", "z"), - [][]interface{}{ + [][]any{ {"g"}, }, []chunkResult{ @@ -104,7 +104,7 @@ func (s *testSpliterSuite) TestSplitRangeByRandom(c *check.C) { "create table `test`.`test`(`a` int, `b` varchar(10), `c` float, `d` datetime, primary key(`b`))", 3, NewChunkRange().copyAndUpdate("b", "a", "z"), - [][]interface{}{ + [][]any{ {}, }, []chunkResult{ @@ -142,13 +142,13 @@ func (s *testSpliterSuite) TestRandomSpliter(c *check.C) { testCases := []struct { createTableSQL string count int - randomValues [][]interface{} + randomValues [][]any expectResult []chunkResult }{ { "create table `test`.`test`(`a` int, `b` varchar(10), `c` float, `d` datetime, primary key(`a`, `b`))", 10, - [][]interface{}{ + [][]any{ {1, 2, 3, 4, 5}, {"a", "b", "c", "d", "e"}, }, @@ -176,7 +176,7 @@ func (s *testSpliterSuite) TestRandomSpliter(c *check.C) { }, { "create table `test`.`test`(`a` int, `b` varchar(10), `c` float, `d` datetime, primary key(`b`))", 10, - [][]interface{}{ + [][]any{ {"a", "b", "c", "d", "e"}, }, []chunkResult{ @@ -232,7 +232,7 @@ func (s *testSpliterSuite) TestRandomSpliter(c *check.C) { } } -func createFakeResultForRandomSplit(mock sqlmock.Sqlmock, count int, randomValues [][]interface{}) { +func createFakeResultForRandomSplit(mock sqlmock.Sqlmock, count int, randomValues [][]any) { if count > 0 { // generate fake result for get the row count of this table countRows := sqlmock.NewRows([]string{"cnt"}).AddRow(count) @@ -259,15 +259,15 @@ func (s *testSpliterSuite) TestBucketSpliter(c *check.C) { testCases := []struct { chunkSize int - aRandomValues []interface{} - bRandomValues []interface{} + aRandomValues []any + bRandomValues []any expectResult []chunkResult }{ { // chunk size less than the count of bucket 64, and the bucket's count 64 >= 32, so will split by random in every bucket 32, - []interface{}{32, 32 * 3, 32 * 5, 32 * 7, 32 * 9}, - []interface{}{6, 6 * 3, 6 * 5, 6 * 7, 6 * 9}, + []any{32, 32 * 3, 32 * 5, 32 * 7, 32 * 9}, + []any{6, 6 * 3, 6 * 5, 6 * 7, 6 * 9}, []chunkResult{ { "(`a` < ?) OR (`a` = ? AND `b` <= ?)", @@ -439,7 +439,7 @@ func (s *testSpliterSuite) TestBucketSpliter(c *check.C) { } } -func createFakeResultForBucketSplit(mock sqlmock.Sqlmock, aRandomValues, bRandomValues []interface{}) { +func createFakeResultForBucketSplit(mock sqlmock.Sqlmock, aRandomValues, bRandomValues []any) { /* +---------+------------+-------------+----------+-----------+-------+---------+-------------+-------------+ | Db_name | Table_name | Column_name | Is_index | Bucket_id | Count | Repeats | Lower_Bound | Upper_Bound | @@ -454,7 +454,7 @@ func createFakeResultForBucketSplit(mock sqlmock.Sqlmock, aRandomValues, bRandom // Mock query with subquery to get all table_ids (main table + partitions) at once statsRows := sqlmock.NewRows([]string{"is_index", "hist_id", "bucket_id", "count", "lower_bound", "upper_bound"}) - for i := 0; i < 5; i++ { + for i := range 5 { // Encode index bounds as real encoded keys: PRIMARY(a, b) where both a and b are integers. lowerA, lowerB := i*64, i*12 upperA, upperB := (i+1)*64-1, (i+1)*12-1 @@ -471,7 +471,7 @@ func createFakeResultForBucketSplit(mock sqlmock.Sqlmock, aRandomValues, bRandom WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnRows(statsRows) - for i := 0; i < len(aRandomValues); i++ { + for i := range aRandomValues { aRandomRows := sqlmock.NewRows([]string{"a"}) aRandomRows.AddRow(aRandomValues[i]) mock.ExpectQuery("ORDER BY rand_value").WillReturnRows(aRandomRows) diff --git a/pkg/diff/util.go b/pkg/diff/util.go index 3d8355eb54..6c8bb40afc 100644 --- a/pkg/diff/util.go +++ b/pkg/diff/util.go @@ -24,8 +24,8 @@ import ( "go.uber.org/zap" ) -func sliceToMap(slice []string) map[string]interface{} { - sMap := make(map[string]interface{}) +func sliceToMap(slice []string) map[string]any { + sMap := make(map[string]any) for _, str := range slice { sMap[str] = struct{}{} } @@ -121,8 +121,8 @@ func rowToString(row map[string]*dbutil.ColumnData) string { return s.String() } -func stringsToInterfaces(strs []string) []interface{} { - is := make([]interface{}, 0, len(strs)) +func stringsToInterfaces(strs []string) []any { + is := make([]any, 0, len(strs)) for _, str := range strs { is = append(is, str) } diff --git a/pkg/election/elector_test.go b/pkg/election/elector_test.go index ddca2a0556..b97d2286e7 100644 --- a/pkg/election/elector_test.go +++ b/pkg/election/elector_test.go @@ -68,7 +68,7 @@ func TestElectorBasic(t *testing.T) { ) firstLeaderID := make(chan string, 1) const electorCount = 5 - for i := 0; i < electorCount; i++ { + for i := range electorCount { id := fmt.Sprintf("elector-%d", i) config := election.Config{ ID: id, @@ -91,13 +91,11 @@ func TestElectorBasic(t *testing.T) { require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := elector.RunElection(ctx) require.Error(t, err) require.Equal(t, context.Canceled, errors.Cause(err)) - }() + }) electors = append(electors, elector) configs = append(configs, config) @@ -247,14 +245,12 @@ func TestElectorRenewFailure(t *testing.T) { require.NoError(t, err) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := e1.RunElection(ctx) require.Error(t, err) require.Equal(t, context.Canceled, errors.Cause(err)) - }() + }) // Wait for leader to be elected. require.Eventually(t, func() bool { @@ -277,13 +273,11 @@ func TestElectorRenewFailure(t *testing.T) { }) require.NoError(t, err) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := e2.RunElection(ctx) require.Error(t, err) require.Equal(t, context.Canceled, errors.Cause(err)) - }() + }) // Make s1 fail and wait for s2 to be elected. s1Err.Store(errors.New("connection error")) @@ -369,13 +363,11 @@ func TestLeaderCallbackUnexpectedExit(t *testing.T) { require.NoError(t, err) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := e1.RunElection(ctx) require.Error(t, err) require.Equal(t, context.Canceled, errors.Cause(err)) - }() + }) // Wait for leader to be elected. require.Eventually(t, func() bool { @@ -397,13 +389,11 @@ func TestLeaderCallbackUnexpectedExit(t *testing.T) { RenewDeadline: renewDeadline, }) require.NoError(t, err) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := e2.RunElection(ctx) require.Error(t, err) require.Equal(t, context.Canceled, errors.Cause(err)) - }() + }) // Make elector 1 leader callback return error. e1CallbackErr.Store(errors.New("callback error")) diff --git a/pkg/election/storage_orm.go b/pkg/election/storage_orm.go index 52533ccf1d..81ca9a0963 100644 --- a/pkg/election/storage_orm.go +++ b/pkg/election/storage_orm.go @@ -38,7 +38,7 @@ func (r Record) Value() (driver.Value, error) { } // Scan implements the sql.Scanner interface -func (r *Record) Scan(value interface{}) error { +func (r *Record) Scan(value any) error { b, ok := value.([]byte) if !ok { return errors.New("type assertion to []byte failed") diff --git a/pkg/election/storage_sql_test.go b/pkg/election/storage_sql_test.go index 6b4ee9d8cd..8ae061979b 100644 --- a/pkg/election/storage_sql_test.go +++ b/pkg/election/storage_sql_test.go @@ -140,8 +140,7 @@ func TestInMemorySQLStorage(t *testing.T) { s, err := NewInMemorySQLStorage(dbName, "leader_election") require.NoError(t, err) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() record := &Record{ LeaderID: "id1", diff --git a/pkg/errors/helper.go b/pkg/errors/helper.go index 0bbd574fa5..ee184b4c84 100644 --- a/pkg/errors/helper.go +++ b/pkg/errors/helper.go @@ -27,7 +27,7 @@ import ( // as cause error. // If given `err` is nil, returns a nil error, which a the different behavior // against `Wrap` function in pingcap/errors. -func WrapError(rfcError *errors.Error, err error, args ...interface{}) error { +func WrapError(rfcError *errors.Error, err error, args ...any) error { if err == nil { return nil } @@ -170,7 +170,7 @@ func IsCliUnprintableError(err error) bool { } // WrapChangefeedUnretryableErr wraps an error into ErrChangefeedUnRetryable. -func WrapChangefeedUnretryableErr(err error, args ...interface{}) error { +func WrapChangefeedUnretryableErr(err error, args ...any) error { return WrapError(ErrChangefeedUnretryable, err, args...) } diff --git a/pkg/errors/helper_test.go b/pkg/errors/helper_test.go index 6c705f8325..8fc417eee4 100644 --- a/pkg/errors/helper_test.go +++ b/pkg/errors/helper_test.go @@ -33,13 +33,13 @@ func TestWrapError(t *testing.T) { err error isNil bool expected string - args []interface{} + args []any }{ {ErrDecodeFailed, nil, true, "", nil}, { ErrDecodeFailed, err, false, "[CDC:ErrDecodeFailed]decode failed: args data: cause error", - []interface{}{"args data"}, + []any{"args data"}, }, } ) diff --git a/pkg/etcd/client.go b/pkg/etcd/client.go index 77e5beafb4..01b3c22d5d 100644 --- a/pkg/etcd/client.go +++ b/pkg/etcd/client.go @@ -418,7 +418,7 @@ func CreateRawEtcdClient(securityConf *security.Credential, grpcDialOption grpc. select { case <-client.Ctx().Done(): log.Info("etcd client is closed, exit health check goroutine") - checker.Range(func(key, value interface{}) bool { + checker.Range(func(key, value any) bool { client := value.(*healthyClient) client.Close() return true @@ -486,15 +486,15 @@ func (checker *healthyChecker) patrol(ctx context.Context) []string { // See https://github.com/etcd-io/etcd/blob/85b640cee793e25f3837c47200089d14a8392dc7/etcdctl/ctlv3/command/ep_command.go#L105-L145 var wg sync.WaitGroup count := 0 - checker.Range(func(key, value interface{}) bool { + checker.Range(func(key, value any) bool { count++ return true }) hch := make(chan string, count) healthyList := make([]string, 0, count) - checker.Range(func(key, value interface{}) bool { + checker.Range(func(key, value any) bool { wg.Add(1) - go func(key, value interface{}) { + go func(key, value any) { defer wg.Done() ep := key.(string) client := value.(*healthyClient) @@ -539,7 +539,7 @@ func (checker *healthyChecker) update(eps []string) { } checker.addClient(ep, time.Now()) } - checker.Range(func(key, value interface{}) bool { + checker.Range(func(key, value any) bool { ep := key.(string) if _, exist := updateEps[ep]; !exist { if client, ok := value.(*healthyClient); ok { diff --git a/pkg/etcd/client_test.go b/pkg/etcd/client_test.go index 199897c559..6226739707 100644 --- a/pkg/etcd/client_test.go +++ b/pkg/etcd/client_test.go @@ -90,8 +90,7 @@ func TestRetry(t *testing.T) { require.NotNil(t, err) require.Containsf(t, errors.Cause(err).Error(), "mock error", "err:%v", err.Error()) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() // Test Txn case // case 0: normal diff --git a/pkg/etcd/etcd.go b/pkg/etcd/etcd.go index c88053ff19..64ecce9314 100644 --- a/pkg/etcd/etcd.go +++ b/pkg/etcd/etcd.go @@ -653,7 +653,7 @@ func GcServiceIDForTest() string { // getFreeListenURLs get free ports and localhost as url. func getFreeListenURLs(n int) (urls []*url.URL, retErr error) { - for i := 0; i < n; i++ { + for range n { u, err := url.Parse(tempurl.Alloc()) if err != nil { retErr = errors.Trace(err) diff --git a/pkg/etcd/etcd_test.go b/pkg/etcd/etcd_test.go index daa83ecd0e..c425ee943c 100644 --- a/pkg/etcd/etcd_test.go +++ b/pkg/etcd/etcd_test.go @@ -283,8 +283,7 @@ func TestGetAllCaptureLeases(t *testing.T) { s.SetUpTest(t) defer s.TearDownTest(t) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() testCases := []*model.CaptureInfo{ { ID: "a3f41a6a-3c31-44f4-aa27-344c1b8cd658", @@ -359,7 +358,7 @@ func TestGetOwnerRevision(t *testing.T) { // checks that the global monotonicity is guaranteed. wg.Add(3) - for i := 0; i < 3; i++ { + for i := range 3 { i := i go func() { defer wg.Done() diff --git a/pkg/etcd/util_test.go b/pkg/etcd/util_test.go index 248078ec19..6ddadf6d05 100644 --- a/pkg/etcd/util_test.go +++ b/pkg/etcd/util_test.go @@ -24,7 +24,7 @@ import ( func TestGetRevisionFromWatchOpts(t *testing.T) { t.Parallel() - for i := 0; i < 100; i++ { + for range 100 { rev := rand.Int63n(math.MaxInt64) opt := clientv3.WithRev(rev) require.Equal(t, getRevisionFromWatchOpts(opt), rev) diff --git a/pkg/filter/expr_filter_bench_test.go b/pkg/filter/expr_filter_bench_test.go index 8048be6e59..a2c1415b13 100644 --- a/pkg/filter/expr_filter_bench_test.go +++ b/pkg/filter/expr_filter_bench_test.go @@ -70,8 +70,8 @@ func BenchmarkSkipDML(b *testing.B) { // set columns to non nil to indicate this case is for insert // set columns to nil to indicate this case is for delete columns []*model.Column - preRow []interface{} - row []interface{} + preRow []any + row []any ignore bool } @@ -83,7 +83,7 @@ func BenchmarkSkipDML(b *testing.B) { columns: []*model.Column{ {Name: "none"}, }, - row: []interface{}{999, "Will", 39, "male"}, + row: []any{999, "Will", 39, "male"}, ignore: true, }, { // insert @@ -95,7 +95,7 @@ func BenchmarkSkipDML(b *testing.B) { columns: []*model.Column{ {Name: "none"}, }, - row: []interface{}{999, "Will", 39, "male"}, + row: []any{999, "Will", 39, "male"}, ignore: true, }, { // update @@ -105,11 +105,11 @@ func BenchmarkSkipDML(b *testing.B) { preColumns: []*model.Column{ {Name: "none"}, }, - preRow: []interface{}{876, "Li", 45, "female"}, + preRow: []any{876, "Li", 45, "female"}, columns: []*model.Column{ {Name: "none"}, }, - row: []interface{}{1, "Dongmen", 20, "male"}, + row: []any{1, "Dongmen", 20, "male"}, ignore: true, }, { // delete @@ -119,7 +119,7 @@ func BenchmarkSkipDML(b *testing.B) { preColumns: []*model.Column{ {Name: "none"}, }, - preRow: []interface{}{876, "Li", 45, "female"}, + preRow: []any{876, "Li", 45, "female"}, ignore: true, }, } diff --git a/pkg/filter/expr_filter_test.go b/pkg/filter/expr_filter_test.go index 843a1f9287..0eb5e1a752 100644 --- a/pkg/filter/expr_filter_test.go +++ b/pkg/filter/expr_filter_test.go @@ -31,7 +31,7 @@ import ( ) // adjustBinaryProtocolForDatumWithoutVirtualCol converts the data in binlog to TiDB datum. -func adjustBinaryProtocolForDatumWithoutVirtualCol(ctx sessionctx.Context, data []interface{}, cols []*timodel.ColumnInfo) ([]types.Datum, error) { +func adjustBinaryProtocolForDatumWithoutVirtualCol(ctx sessionctx.Context, data []any, cols []*timodel.ColumnInfo) ([]types.Datum, error) { ret := make([]types.Datum, 0, len(data)) colIndex := 0 for _, d := range data { @@ -66,8 +66,8 @@ func TestShouldSkipDMLBasic(t *testing.T) { // set columns to non nil to indicate this case is for insert // set columns to nil to indicate this case is for delete columns []*model.ColumnData - preRow []interface{} - row []interface{} + preRow []any + row []any ignore bool } @@ -98,7 +98,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{999, "Will", 39, "male"}, + row: []any{999, "Will", 39, "male"}, ignore: false, }, { // schema name does not configure in matcher, no rule to filter it @@ -107,7 +107,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{888, "Li", 45, "male"}, + row: []any{888, "Li", 45, "male"}, ignore: false, }, { // insert @@ -116,7 +116,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "Dongmen", 20, "male"}, + row: []any{1, "Dongmen", 20, "male"}, ignore: true, }, { // insert @@ -125,7 +125,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{2, "Rustin", 18, "male"}, + row: []any{2, "Rustin", 18, "male"}, ignore: false, }, { // insert @@ -134,7 +134,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{3, "Susan", 3, "female"}, + row: []any{3, "Susan", 3, "female"}, ignore: true, }, { // delete @@ -143,7 +143,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{4, "Helen", 18, "female"}, + preRow: []any{4, "Helen", 18, "female"}, ignore: false, }, { // delete @@ -152,7 +152,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{5, "Madonna", 32, "female"}, + preRow: []any{5, "Madonna", 32, "female"}, ignore: true, }, { // delete @@ -161,7 +161,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{6, "Madison", 48, "male"}, + preRow: []any{6, "Madison", 48, "male"}, ignore: false, }, { // update, filler by new value @@ -170,11 +170,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{7, "Marry", 28, "female"}, + preRow: []any{7, "Marry", 28, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{7, "Marry", 32, "female"}, + row: []any{7, "Marry", 32, "female"}, ignore: true, }, { // update @@ -183,11 +183,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{8, "Marilyn", 18, "female"}, + preRow: []any{8, "Marilyn", 18, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{8, "Monroe", 22, "female"}, + row: []any{8, "Monroe", 22, "female"}, ignore: false, }, { // update, filter by old value @@ -196,11 +196,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{9, "Andreja", 25, "male"}, + preRow: []any{9, "Andreja", 25, "male"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{9, "Andreja", 25, "female"}, + row: []any{9, "Andreja", 25, "female"}, ignore: true, }, }, @@ -226,7 +226,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "Dongmen", 20, "male"}, + row: []any{1, "Dongmen", 20, "male"}, ignore: true, }, { // insert @@ -235,7 +235,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{2, "Rustin", 18, "male"}, + row: []any{2, "Rustin", 18, "male"}, ignore: false, }, { // insert @@ -244,7 +244,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{3, "Susan", 3, "female"}, + row: []any{3, "Susan", 3, "female"}, ignore: true, }, { // delete @@ -253,7 +253,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{4, "Helen", 18, "female"}, + preRow: []any{4, "Helen", 18, "female"}, ignore: false, }, { // delete @@ -262,7 +262,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{5, "Madonna", 32, "female"}, + preRow: []any{5, "Madonna", 32, "female"}, ignore: true, }, { // delete @@ -271,7 +271,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{6, "Madison", 48, "male"}, + preRow: []any{6, "Madison", 48, "male"}, ignore: false, }, { // update, filler by new value @@ -280,11 +280,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{7, "Marry", 28, "female"}, + preRow: []any{7, "Marry", 28, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{7, "Marry", 32, "female"}, + row: []any{7, "Marry", 32, "female"}, ignore: true, }, { // update @@ -293,11 +293,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{8, "Marilyn", 18, "female"}, + preRow: []any{8, "Marilyn", 18, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{8, "Monroe", 22, "female"}, + row: []any{8, "Monroe", 22, "female"}, ignore: false, }, { // update, filter by old value @@ -306,11 +306,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{9, "Andreja", 25, "male"}, + preRow: []any{9, "Andreja", 25, "male"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{9, "Andreja", 25, "female"}, + row: []any{9, "Andreja", 25, "female"}, ignore: true, }, }, @@ -332,7 +332,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "apple", 12888}, + row: []any{1, "apple", 12888}, ignore: true, }, { // insert @@ -341,7 +341,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{2, "microsoft", 5888}, + row: []any{2, "microsoft", 5888}, ignore: false, }, }, @@ -363,7 +363,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "李白", "静夜思"}, + row: []any{1, "李白", "静夜思"}, ignore: true, }, { // insert @@ -372,7 +372,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{2, "杜甫", "石壕吏"}, + row: []any{2, "杜甫", "石壕吏"}, ignore: false, }, { // insert @@ -381,7 +381,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{4, "屈原", "离骚"}, + row: []any{4, "屈原", "离骚"}, ignore: true, }, { // insert @@ -390,7 +390,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{3, "辛弃疾", "众里寻他千百度"}, + row: []any{3, "辛弃疾", "众里寻他千百度"}, ignore: true, }, }, @@ -414,7 +414,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "Spring", "January", "March"}, + row: []any{1, "Spring", "January", "March"}, ignore: false, }, { // do not ignore any event of test.season table @@ -423,11 +423,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{2, "Summer", "April", "June"}, + preRow: []any{2, "Summer", "April", "June"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{2, "Summer", "April", "July"}, + row: []any{2, "Summer", "April", "July"}, ignore: false, }, { // ignore insert event of test.autumn table @@ -436,7 +436,7 @@ func TestShouldSkipDMLBasic(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{3, "Autumn", "July", "September"}, + row: []any{3, "Autumn", "July", "September"}, ignore: true, }, { // ignore update event of test.winter table @@ -445,11 +445,11 @@ func TestShouldSkipDMLBasic(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{4, "Winter", "October", "January"}, + preRow: []any{4, "Winter", "October", "January"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{4, "Winter", "October", "December"}, + row: []any{4, "Winter", "October", "December"}, ignore: true, }, }, @@ -504,8 +504,8 @@ func TestShouldSkipDMLError(t *testing.T) { // set columns to non nil to indicate this case is for insert // set columns to nil to indicate this case is for delete columns []*model.ColumnData - preRow []interface{} - row []interface{} + preRow []any + row []any ignore bool err error errMsg string @@ -538,7 +538,7 @@ func TestShouldSkipDMLError(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{999, "Will", 39, "male"}, + row: []any{999, "Will", 39, "male"}, ignore: false, err: cerror.ErrExpressionColumnNotFound, errMsg: "Cannot find column 'mather' from table 'test.student' in", @@ -549,11 +549,11 @@ func TestShouldSkipDMLError(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{876, "Li", 45, "female"}, + preRow: []any{876, "Li", 45, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "Dongmen", 20, "male"}, + row: []any{1, "Dongmen", 20, "male"}, ignore: false, err: cerror.ErrExpressionParseFailed, errMsg: "There is a syntax error in", @@ -564,7 +564,7 @@ func TestShouldSkipDMLError(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{876, "Li", 45, "female"}, + preRow: []any{876, "Li", 45, "female"}, ignore: false, err: cerror.ErrExpressionParseFailed, errMsg: "There is a syntax error in", @@ -624,8 +624,8 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { // set columns to non nil to indicate this case is for insert // set columns to nil to indicate this case is for delete columns []*model.ColumnData - preRow []interface{} - row []interface{} + preRow []any + row []any ignore bool err error errMsg string @@ -658,7 +658,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{999, "Will", 39, "male"}, + row: []any{999, "Will", 39, "male"}, ignore: false, err: cerror.ErrExpressionColumnNotFound, errMsg: "Cannot find column 'mather' from table 'test.student' in", @@ -671,7 +671,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{999, "Will", 39, "male", "Marry"}, + row: []any{999, "Will", 39, "male", "Marry"}, ignore: false, }, { // update @@ -680,11 +680,11 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{876, "Li", 45, "female"}, + preRow: []any{876, "Li", 45, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "Dongmen", 20, "male"}, + row: []any{1, "Dongmen", 20, "male"}, ignore: true, }, { // delete @@ -693,7 +693,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{876, "Li", 45, "female", "Maria"}, + preRow: []any{876, "Li", 45, "female", "Maria"}, ignore: true, }, }, @@ -718,7 +718,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{999, "Will", 39, "male", "Apple"}, + row: []any{999, "Will", 39, "male", "Apple"}, ignore: true, }, { // insert @@ -727,7 +727,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{11, "Tom", 21, "male", "FaceBook"}, + row: []any{11, "Tom", 21, "male", "FaceBook"}, ignore: false, }, { // update @@ -736,11 +736,11 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{876, "Li", 45, "female"}, + preRow: []any{876, "Li", 45, "female"}, columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{1, "Dongmen", 20, "male"}, + row: []any{1, "Dongmen", 20, "male"}, ignore: true, }, { // delete @@ -749,7 +749,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { preColumns: []*model.ColumnData{ {ColumnID: 0}, }, - preRow: []interface{}{876, "Li", 45, "female", "Google"}, + preRow: []any{876, "Li", 45, "female", "Google"}, ignore: true, }, { // insert @@ -759,7 +759,7 @@ func TestShouldSkipDMLTableUpdated(t *testing.T) { columns: []*model.ColumnData{ {ColumnID: 0}, }, - row: []interface{}{999, "Will", 39, "male"}, + row: []any{999, "Will", 39, "male"}, ignore: false, err: cerror.ErrExpressionColumnNotFound, errMsg: "Cannot find column 'company' from table 'test.worker' in", diff --git a/pkg/filter/filter.go b/pkg/filter/filter.go index 6b343daf23..912558bbfa 100644 --- a/pkg/filter/filter.go +++ b/pkg/filter/filter.go @@ -14,6 +14,8 @@ package filter import ( + "slices" + timodel "github.com/pingcap/tidb/pkg/meta/model" tfilter "github.com/pingcap/tidb/pkg/util/table-filter" "github.com/pingcap/tiflow/cdc/model" @@ -244,12 +246,7 @@ func (f *filter) Verify(tableInfos []*model.TableInfo) error { } func (f *filter) shouldIgnoreStartTs(ts uint64) bool { - for _, ignoreTs := range f.ignoreTxnStartTs { - if ignoreTs == ts { - return true - } - } - return false + return slices.Contains(f.ignoreTxnStartTs, ts) } func isAllowedDDL(actionType timodel.ActionType) bool { diff --git a/pkg/filter/sql_event_filter_test.go b/pkg/filter/sql_event_filter_test.go index d7b17ce882..7aef3a36a2 100644 --- a/pkg/filter/sql_event_filter_test.go +++ b/pkg/filter/sql_event_filter_test.go @@ -465,7 +465,6 @@ func TestShouldSkipDML(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() f, err := newSQLEventFilter(tc.cfg) diff --git a/pkg/filter/utils.go b/pkg/filter/utils.go index aa7fb4b1fa..96b501e9fc 100644 --- a/pkg/filter/utils.go +++ b/pkg/filter/utils.go @@ -15,6 +15,7 @@ package filter import ( "fmt" + "slices" "strings" timodel "github.com/pingcap/tidb/pkg/meta/model" @@ -119,12 +120,7 @@ var alterTableSubType = []timodel.ActionType{ // isAlterTable returns true if the given job type is alter table's subtype. func isAlterTable(jobType timodel.ActionType) bool { - for _, t := range alterTableSubType { - if t == jobType { - return true - } - } - return false + return slices.Contains(alterTableSubType, jobType) } // SupportedEventTypes returns the supported event types. diff --git a/pkg/fsutil/file_allocator.go b/pkg/fsutil/file_allocator.go index acf4f203d9..c25a47afc5 100644 --- a/pkg/fsutil/file_allocator.go +++ b/pkg/fsutil/file_allocator.go @@ -52,11 +52,9 @@ func NewFileAllocator(dir string, prefix string, size int64) *FileAllocator { doneCh: make(chan struct{}), } - allocator.wg.Add(1) - go func() { - defer allocator.wg.Done() + allocator.wg.Go(func() { allocator.run() - }() + }) return allocator } diff --git a/pkg/fsutil/file_allocator_test.go b/pkg/fsutil/file_allocator_test.go index 44c6bb91f5..5137ac3623 100644 --- a/pkg/fsutil/file_allocator_test.go +++ b/pkg/fsutil/file_allocator_test.go @@ -66,7 +66,7 @@ func benchmarkWriteData(b *testing.B, size int, useFileAlloctor bool) { } data := make([]byte, size) - for i := 0; i < size; i++ { + for i := range size { data[i] = byte(i) } diff --git a/pkg/importer/db.go b/pkg/importer/db.go index 3242cd0539..8f6037a3f0 100644 --- a/pkg/importer/db.go +++ b/pkg/importer/db.go @@ -65,7 +65,7 @@ func uniqInt64Value(column *column, max int64) int64 { func genRowDatas(table *table, count int) ([]string, error) { datas := make([]string, 0, count) - for i := 0; i < count; i++ { + for range count { data, err := genRowData(table) if err != nil { return nil, errors.Trace(err) @@ -242,7 +242,7 @@ func closeDB(db *sql.DB) error { func createDBs(cfg dbutil.DBConfig, count int) ([]*sql.DB, error) { dbs := make([]*sql.DB, 0, count) - for i := 0; i < count; i++ { + for range count { db, err := createDB(cfg) if err != nil { return nil, errors.Trace(err) diff --git a/pkg/importer/job.go b/pkg/importer/job.go index 9ed994618b..6af8035190 100644 --- a/pkg/importer/job.go +++ b/pkg/importer/job.go @@ -23,7 +23,7 @@ import ( ) func addJobs(jobCount int, jobChan chan struct{}) { - for i := 0; i < jobCount; i++ { + for range jobCount { jobChan <- struct{}{} } @@ -72,7 +72,7 @@ func doJob(table *table, db *sql.DB, batch int, jobChan chan struct{}, doneChan } func doWait(doneChan chan struct{}, start time.Time, jobCount int, workerCount int) { - for i := 0; i < workerCount; i++ { + for range workerCount { <-doneChan } @@ -96,7 +96,7 @@ func doProcess(table *table, dbs []*sql.DB, jobCount int, workerCount int, batch start := time.Now() go addJobs(jobCount, jobChan) - for i := 0; i < workerCount; i++ { + for i := range workerCount { go doJob(table, dbs[i], batch, jobChan, doneChan) } diff --git a/pkg/importer/parser.go b/pkg/importer/parser.go index b13d3fb92b..9a702c2653 100644 --- a/pkg/importer/parser.go +++ b/pkg/importer/parser.go @@ -73,8 +73,8 @@ func (col *column) parseRule(kvs []string) { log.Fatal("parseRule", zap.Error(err)) } } else if key == "set" { - fields := strings.Split(value, ",") - for _, field := range fields { + fields := strings.SplitSeq(value, ",") + for field := range fields { col.set = append(col.set, strings.TrimSpace(field)) } } @@ -92,8 +92,8 @@ func (col *column) parseColumnComment() { content = comment[start+2 : end] } - fields := strings.Split(content, ";") - for _, field := range fields { + fields := strings.SplitSeq(content, ";") + for field := range fields { field = strings.TrimSpace(field) kvs := strings.Split(field, "=") col.parseRule(kvs) @@ -129,12 +129,12 @@ type table struct { } func (t *table) printColumns() string { - ret := "" + var ret strings.Builder for _, col := range t.columns { - ret += fmt.Sprintf("%v", col) + ret.WriteString(fmt.Sprintf("%v", col)) } - return ret + return ret.String() } func (t *table) String() string { @@ -142,23 +142,24 @@ func (t *table) String() string { return "" } - ret := fmt.Sprintf("[table]name: %s\n", t.name) - ret += "[table]columns:\n" - ret += t.printColumns() + var ret strings.Builder + ret.WriteString(fmt.Sprintf("[table]name: %s\n", t.name)) + ret.WriteString("[table]columns:\n") + ret.WriteString(t.printColumns()) - ret += fmt.Sprintf("[table]column list: %s\n", t.columnList) + ret.WriteString(fmt.Sprintf("[table]column list: %s\n", t.columnList)) - ret += "[table]indices:\n" + ret.WriteString("[table]indices:\n") for k, v := range t.indices { - ret += fmt.Sprintf("key->%s, value->%v", k, v) + ret.WriteString(fmt.Sprintf("key->%s, value->%v", k, v)) } - ret += "[table]unique indices:\n" + ret.WriteString("[table]unique indices:\n") for k, v := range t.uniqIndices { - ret += fmt.Sprintf("key->%s, value->%v", k, v) + ret.WriteString(fmt.Sprintf("key->%s, value->%v", k, v)) } - return ret + return ret.String() } func newTable() *table { diff --git a/pkg/label/label_test.go b/pkg/label/label_test.go index fb6799cd6a..55b1c23201 100644 --- a/pkg/label/label_test.go +++ b/pkg/label/label_test.go @@ -51,7 +51,6 @@ func TestNewKey(t *testing.T) { t.Parallel() for _, tc := range cases { - tc := tc t.Run(tc.str, func(t *testing.T) { t.Parallel() res, err := NewKey(tc.str) @@ -69,7 +68,6 @@ func TestNewValue(t *testing.T) { t.Parallel() for _, tc := range cases { - tc := tc t.Run(tc.str, func(t *testing.T) { t.Parallel() res, err := NewValue(tc.str) diff --git a/pkg/label/selector_test.go b/pkg/label/selector_test.go index f764498bec..d80934a7f0 100644 --- a/pkg/label/selector_test.go +++ b/pkg/label/selector_test.go @@ -140,7 +140,6 @@ func TestSelectorMatches(t *testing.T) { } for idx, tc := range cases { - tc := tc t.Run(strconv.Itoa(idx), func(t *testing.T) { t.Parallel() require.Equal(t, tc.shouldMatch, tc.selector.Matches(tc.labels)) @@ -161,13 +160,11 @@ func TestSelectorRegexLazyCompile(t *testing.T) { labelSetNotMatch := map[Key]Value{"tenant": "abcdef", "node_type": "2"} var wg sync.WaitGroup - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 10 { + wg.Go(func() { require.True(t, selector.Matches(labelSetMatch)) require.False(t, selector.Matches(labelSetNotMatch)) - }() + }) } wg.Wait() @@ -235,7 +232,6 @@ func TestSelectorValidate(t *testing.T) { } for idx, tc := range cases { - tc := tc t.Run(strconv.Itoa(idx), func(t *testing.T) { t.Parallel() tc.checkErr(tc.selector.Validate()) diff --git a/pkg/leakutil/leak_helper_test.go b/pkg/leakutil/leak_helper_test.go index 940cc065cb..622f49a7b3 100644 --- a/pkg/leakutil/leak_helper_test.go +++ b/pkg/leakutil/leak_helper_test.go @@ -20,7 +20,7 @@ import ( ) func TestSetUpLeakTest(t *testing.T) { - leakChan := make(chan interface{}) + leakChan := make(chan any) go func() { <-leakChan diff --git a/pkg/logutil/log.go b/pkg/logutil/log.go index 5ac1c6bf55..3539cde8f4 100644 --- a/pkg/logutil/log.go +++ b/pkg/logutil/log.go @@ -18,6 +18,7 @@ import ( "context" "io" "os" + "slices" "strconv" "strings" @@ -202,10 +203,8 @@ func initOptionalComponent(op *loggerOp, cfg *Config) error { // ZapErrorFilter wraps zap.Error, if err is in given filterErrors, it will be set to nil func ZapErrorFilter(err error, filterErrors ...error) zap.Field { cause := errors.Cause(err) - for _, ferr := range filterErrors { - if cause == ferr { - return zap.Error(nil) - } + if slices.Contains(filterErrors, cause) { + return zap.Error(nil) } return zap.Error(err) } diff --git a/pkg/logutil/log_test.go b/pkg/logutil/log_test.go index 479c8240fd..f4ec4cf4b7 100644 --- a/pkg/logutil/log_test.go +++ b/pkg/logutil/log_test.go @@ -220,14 +220,12 @@ func TestMySQLLogger(t *testing.T) { ms, err := net.Listen("tcp4", "127.0.0.1:0") require.NoError(t, err) wg := sync.WaitGroup{} - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { conn, err := ms.Accept() require.NoError(t, err) err = conn.Close() require.NoError(t, err) - }() + }) dsnStr := fmt.Sprintf("root:@tcp(%s)/", ms.Addr().String()) db, err := sql.Open("mysql", dsnStr) diff --git a/pkg/migrate/migrate_test.go b/pkg/migrate/migrate_test.go index 2c7ade910c..c559aede60 100644 --- a/pkg/migrate/migrate_test.go +++ b/pkg/migrate/migrate_test.go @@ -191,23 +191,17 @@ func TestMigration(t *testing.T) { // 3. tow non-owner node wait for meta migrating done wg := new(sync.WaitGroup) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := migrator.WaitMetaVersionMatched(ctx) require.NoError(t, err) - }() - wg.Add(1) - go func() { - defer wg.Done() + }) + wg.Go(func() { err := migrator.WaitMetaVersionMatched(ctx) require.NoError(t, err) - }() + }) - wg.Add(1) // 4.owner note migrates meta data - go func() { - defer wg.Done() + wg.Go(func() { // 5. test ShouldMigrate works as expected should, err := migrator.ShouldMigrate(ctx) require.NoError(t, err) @@ -216,7 +210,7 @@ func TestMigration(t *testing.T) { err = migrator.Migrate(ctx) require.NoError(t, err) } - }() + }) // 6. wait for migration done wg.Wait() @@ -291,7 +285,7 @@ func TestMigration(t *testing.T) { require.Equal(t, int64(1), v) // migrate again - for i := 0; i < 10; i++ { + for range 10 { err = m.Migrate(ctx) require.Nil(t, err) } @@ -410,23 +404,17 @@ func TestMigrationNonDefaultCluster(t *testing.T) { } // 3. tow non-owner node wait for meta migrating done wg := new(sync.WaitGroup) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := migrator.WaitMetaVersionMatched(ctx) require.NoError(t, err) - }() - wg.Add(1) - go func() { - defer wg.Done() + }) + wg.Go(func() { err := migrator.WaitMetaVersionMatched(ctx) require.NoError(t, err) - }() + }) - wg.Add(1) // 4.owner note migrates meta data - go func() { - defer wg.Done() + wg.Go(func() { // 5. test ShouldMigrate works as expected should, err := migrator.ShouldMigrate(ctx) require.NoError(t, err) @@ -435,7 +423,7 @@ func TestMigrationNonDefaultCluster(t *testing.T) { err = migrator.Migrate(ctx) require.NoError(t, err) } - }() + }) // 6. wait for migration done wg.Wait() @@ -498,8 +486,7 @@ func newMockPDClient(normal bool) *mockPDClient { } func TestMigrateGcServiceSafePoint(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() m := &migrator{} mockClient := newMockPDClient(true) @@ -549,8 +536,7 @@ func TestMigrateGcServiceSafePoint(t *testing.T) { } func TestRemoveOldGcServiceSafePointFailed(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() mockClient := newMockPDClient(true) m := &migrator{} @@ -589,8 +575,7 @@ func TestRemoveOldGcServiceSafePointFailed(t *testing.T) { } func TestListServiceSafePointFailed(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() mockClient := newMockPDClient(true) m := &migrator{} @@ -600,8 +585,7 @@ func TestListServiceSafePointFailed(t *testing.T) { } func TestNoServiceSafePoint(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() mockClient := newMockPDClient(true) m := &migrator{} diff --git a/pkg/notify/notify_test.go b/pkg/notify/notify_test.go index f64f2a232f..2704c6991b 100644 --- a/pkg/notify/notify_test.go +++ b/pkg/notify/notify_test.go @@ -36,7 +36,7 @@ func TestNotifyHub(t *testing.T) { require.Nil(t, err) finishedCh := make(chan struct{}) go func() { - for i := 0; i < 5; i++ { + for range 5 { time.Sleep(time.Second) notifier.Notify() } @@ -82,11 +82,11 @@ func TestContinusStop(t *testing.T) { n := 50 receivers := make([]*Receiver, n) var err error - for i := 0; i < n; i++ { + for i := range n { receivers[i], err = notifier.NewReceiver(10 * time.Millisecond) require.Nil(t, err) } - for i := 0; i < n; i++ { + for i := range n { i := i go func() { for { @@ -98,7 +98,7 @@ func TestContinusStop(t *testing.T) { } }() } - for i := 0; i < n; i++ { + for i := range n { receivers[i].Stop() } <-ctx.Done() @@ -122,9 +122,7 @@ func TestNotifierMultiple(t *testing.T) { counter := atomic.NewInt32(0) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { _, ok := <-receiver.C if !ok { @@ -132,15 +130,13 @@ func TestNotifierMultiple(t *testing.T) { } counter.Add(1) } - }() + }) receiver1, err := notifier.NewReceiver(time.Minute) require.NoError(t, err) counter1 := atomic.NewInt32(0) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { _, ok := <-receiver1.C if !ok { @@ -148,10 +144,10 @@ func TestNotifierMultiple(t *testing.T) { } counter1.Add(1) } - }() + }) N := 5 - for i := 0; i < N; i++ { + for range N { notifier.Notify() time.Sleep(time.Millisecond * 100) } diff --git a/pkg/orchestrator/batch.go b/pkg/orchestrator/batch.go index 3bc9870616..71cd611e57 100644 --- a/pkg/orchestrator/batch.go +++ b/pkg/orchestrator/batch.go @@ -14,6 +14,8 @@ package orchestrator import ( + "maps" + "github.com/pingcap/errors" cerrors "github.com/pingcap/tiflow/pkg/errors" "github.com/pingcap/tiflow/pkg/orchestrator/util" @@ -60,9 +62,7 @@ func getBatchChangedState(state map[util.EtcdKey][]byte, patchGroups [][]DataPat len(batchChangedState)+len(changedState) >= etcdTxnMaxOps { break } - for k, v := range changedState { - batchChangedState[k] = v - } + maps.Copy(batchChangedState, changedState) num++ totalSize += changedSize } diff --git a/pkg/orchestrator/batch_test.go b/pkg/orchestrator/batch_test.go index 95a7721872..d1833bdde8 100644 --- a/pkg/orchestrator/batch_test.go +++ b/pkg/orchestrator/batch_test.go @@ -25,12 +25,12 @@ func TestGetBatchChangeState(t *testing.T) { t.Parallel() patchGroupSize := 1000 patchGroup := make([][]DataPatch, patchGroupSize) - for i := 0; i < patchGroupSize; i++ { + for i := range patchGroupSize { i := i patches := []DataPatch{&SingleDataPatch{ Key: util.NewEtcdKey(fmt.Sprintf("/key%d", i)), Func: func(old []byte) (newValue []byte, changed bool, err error) { - newValue = []byte(fmt.Sprintf("abc%d", i)) + newValue = fmt.Appendf(nil, "abc%d", i) return newValue, true, nil }, }} @@ -42,7 +42,7 @@ func TestGetBatchChangeState(t *testing.T) { require.LessOrEqual(t, n, len(patchGroup)) require.LessOrEqual(t, size, etcdTxnMaxSize) require.LessOrEqual(t, len(changedState), etcdTxnMaxOps) - require.Equal(t, []byte(fmt.Sprintf("abc%d", 0)), changedState[util.NewEtcdKey("/key0")]) + require.Equal(t, fmt.Appendf(nil, "abc%d", 0), changedState[util.NewEtcdKey("/key0")]) // test single patch exceed txn max size largeSizePatches := []DataPatch{&SingleDataPatch{ @@ -63,7 +63,7 @@ func TestGetBatchChangeState(t *testing.T) { manyOpsPatches = append(manyOpsPatches, &SingleDataPatch{ Key: util.NewEtcdKey(fmt.Sprintf("/key%d", i)), Func: func(old []byte) (newValue []byte, changed bool, err error) { - newValue = []byte(fmt.Sprintf("abc%d", i)) + newValue = fmt.Appendf(nil, "abc%d", i) return newValue, true, nil }, }) diff --git a/pkg/orchestrator/etcd_worker_bank_test.go b/pkg/orchestrator/etcd_worker_bank_test.go index 81438e7f02..e6d03ec569 100644 --- a/pkg/orchestrator/etcd_worker_bank_test.go +++ b/pkg/orchestrator/etcd_worker_bank_test.go @@ -92,7 +92,7 @@ func (b *bankReactorState) patchAccount(index int, fn func(int) int) DataPatch { } func (b *bankReactorState) TransferRandomly(transferNumber int) { - for i := 0; i < transferNumber; i++ { + for range transferNumber { accountA := rand.Intn(len(b.account)) accountB := rand.Intn(len(b.account)) transferMoney := rand.Intn(100) @@ -148,16 +148,14 @@ func TestEtcdBank(t *testing.T) { }() defer cancel() - for i := 0; i < totalAccountNumber; i++ { + for i := range totalAccountNumber { _, err := cli.Put(ctx, fmt.Sprintf("%s%d", bankTestPrefix, i), "0") require.Nil(t, err) } - for i := 0; i < workerNumber; i++ { + for i := range workerNumber { i := i - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { worker, err := NewEtcdWorker(cdcCli, bankTestPrefix, &bankReactor{ accountNumber: totalAccountNumber, @@ -171,7 +169,7 @@ func TestEtcdBank(t *testing.T) { require.Contains(t, err.Error(), "context deadline exceeded") return } - }() + }) } wg.Wait() } diff --git a/pkg/orchestrator/etcd_worker_test.go b/pkg/orchestrator/etcd_worker_test.go index 95c49907b0..8623f667e0 100644 --- a/pkg/orchestrator/etcd_worker_test.go +++ b/pkg/orchestrator/etcd_worker_test.go @@ -228,13 +228,13 @@ func TestEtcdSum(t *testing.T) { jsonStr, err := json.Marshal(initArray) require.Nil(t, err) - for i := 0; i < numGroups; i++ { + for i := range numGroups { _, err := cli.Put(ctx, testEtcdKeyPrefix+"/"+strconv.Itoa(i), string(jsonStr)) require.Nil(t, err) } errg, ctx := errgroup.WithContext(ctx) - for i := 0; i < numValuesPerGroup+1; i++ { + for i := range numValuesPerGroup + 1 { finalI := i errg.Go(func() error { values := make([][]int, numGroups) @@ -340,7 +340,7 @@ func TestLinearizability(t *testing.T) { cdcCli, err := etcd.NewCDCEtcdClient(ctx, cli0.Unwrap(), "default") require.Nil(t, err) cli := newClient() - for i := 0; i < 1000; i++ { + for i := range 1000 { _, err := cli.Put(ctx, testEtcdKeyPrefix+"/lin", strconv.Itoa(i)) require.Nil(t, err) } @@ -743,12 +743,10 @@ func TestModifyAfterDelete(t *testing.T) { require.Nil(t, err) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := worker1.Run(ctx, nil, time.Millisecond*100, "owner") require.Nil(t, err) - }() + }) modifyReactor.waitOnCh <- struct{}{} diff --git a/pkg/orchestrator/reactor_state.go b/pkg/orchestrator/reactor_state.go index ccbde53e1c..6571288cb3 100644 --- a/pkg/orchestrator/reactor_state.go +++ b/pkg/orchestrator/reactor_state.go @@ -50,10 +50,7 @@ type GlobalReactorState struct { // NewGlobalState creates a new global state. func NewGlobalState(clusterID string, captureSessionTTL int) *GlobalReactorState { - captureRemoveTTL := captureSessionTTL / 2 - if captureRemoveTTL < defaultCaptureRemoveTTL { - captureRemoveTTL = defaultCaptureRemoveTTL - } + captureRemoveTTL := max(captureSessionTTL/2, defaultCaptureRemoveTTL) return &GlobalReactorState{ ClusterID: clusterID, Owner: map[string]struct{}{}, @@ -436,7 +433,7 @@ func (s *ChangefeedReactorState) Update(key util.EtcdKey, value []byte, _ bool) // UpdateCDCKey updates the state by a parsed etcd key func (s *ChangefeedReactorState) UpdateCDCKey(key *etcd.CDCKey, value []byte) error { - var e interface{} + var e any switch key.Tp { case etcd.CDCKeyTypeChangefeedInfo: if key.ChangefeedID != s.ID { @@ -557,7 +554,7 @@ func (s *ChangefeedReactorState) PatchInfo(fn func(*model.ChangeFeedInfo) (*mode Tp: etcd.CDCKeyTypeChangefeedInfo, ChangefeedID: s.ID, } - s.patchAny(key.String(), changefeedInfoTPI, func(e interface{}) (interface{}, bool, error) { + s.patchAny(key.String(), changefeedInfoTPI, func(e any) (any, bool, error) { // e == nil means that the key is not exist before this patch if e == nil { return fn(nil) @@ -573,7 +570,7 @@ func (s *ChangefeedReactorState) PatchStatus(fn func(*model.ChangeFeedStatus) (* Tp: etcd.CDCKeyTypeChangeFeedStatus, ChangefeedID: s.ID, } - s.patchAny(key.String(), changefeedStatusTPI, func(e interface{}) (interface{}, bool, error) { + s.patchAny(key.String(), changefeedStatusTPI, func(e any) (any, bool, error) { // e == nil means that the key is not exist before this patch if e == nil { return fn(nil) @@ -590,7 +587,7 @@ func (s *ChangefeedReactorState) PatchTaskPosition(captureID model.CaptureID, fn CaptureID: captureID, ChangefeedID: s.ID, } - s.patchAny(key.String(), taskPositionTPI, func(e interface{}) (interface{}, bool, error) { + s.patchAny(key.String(), taskPositionTPI, func(e any) (any, bool, error) { // e == nil means that the key is not exist before this patch if e == nil { return fn(nil) @@ -605,14 +602,14 @@ var ( changefeedInfoTPI *model.ChangeFeedInfo ) -func (s *ChangefeedReactorState) patchAny(key string, tpi interface{}, fn func(interface{}) (interface{}, bool, error)) { +func (s *ChangefeedReactorState) patchAny(key string, tpi any, fn func(any) (any, bool, error)) { patch := &SingleDataPatch{ Key: util.NewEtcdKey(key), Func: func(v []byte) ([]byte, bool, error) { if s.skipPatchesInThisTick { return v, false, cerrors.ErrEtcdIgnore.GenWithStackByArgs() } - var e interface{} + var e any if v != nil { tp := reflect.TypeOf(tpi) e = reflect.New(tp.Elem()).Interface() diff --git a/pkg/p2p/client.go b/pkg/p2p/client.go index 9b67424d66..1cbad9cd3a 100644 --- a/pkg/p2p/client.go +++ b/pkg/p2p/client.go @@ -30,10 +30,10 @@ type MessageClient interface { Run(ctx context.Context, network string, addr string, receiverID NodeID, credential *security.Credential) (ret error) // SendMessage sends a message of a given topic. It would block if the inner channel is congested. - SendMessage(ctx context.Context, topic Topic, value interface{}) (seq Seq, ret error) + SendMessage(ctx context.Context, topic Topic, value any) (seq Seq, ret error) // TrySendMessage tries to send a message of a given topic. It will return an error if the inner channel is congested. - TrySendMessage(ctx context.Context, topic Topic, value interface{}) (seq Seq, ret error) + TrySendMessage(ctx context.Context, topic Topic, value any) (seq Seq, ret error) // CurrentAck is used to query the latest sequence number for a topic that is acknowledged by the server. // Note: currently only used for test. @@ -87,7 +87,7 @@ func (c *localMessageClient) Run( return nil } -func (c *localMessageClient) SendMessage(ctx context.Context, topic Topic, value interface{}) (Seq, error) { +func (c *localMessageClient) SendMessage(ctx context.Context, topic Topic, value any) (Seq, error) { select { case <-ctx.Done(): return 0, ctx.Err() @@ -98,7 +98,7 @@ func (c *localMessageClient) SendMessage(ctx context.Context, topic Topic, value } } -func (c *localMessageClient) TrySendMessage(ctx context.Context, topic Topic, value interface{}) (Seq, error) { +func (c *localMessageClient) TrySendMessage(ctx context.Context, topic Topic, value any) (Seq, error) { select { case <-ctx.Done(): return 0, ctx.Err() diff --git a/pkg/p2p/client_batch_sender.go b/pkg/p2p/client_batch_sender.go index 3527a77fe6..8070cc0353 100644 --- a/pkg/p2p/client_batch_sender.go +++ b/pkg/p2p/client_batch_sender.go @@ -46,10 +46,7 @@ type grpcClientBatchSender struct { } func newClientBatchSender(stream MessageClientStream, maxEntryCount, maxSizeBytes int) clientBatchSender[MessageEntry] { - sliceCap := maxEntryCount - if sliceCap > maxPreallocBatchSize { - sliceCap = maxPreallocBatchSize - } + sliceCap := min(maxEntryCount, maxPreallocBatchSize) return &grpcClientBatchSender{ stream: stream, buffer: make([]MessageEntry, 0, sliceCap), diff --git a/pkg/p2p/client_batch_sender_test.go b/pkg/p2p/client_batch_sender_test.go index aa035a36b1..89d864c854 100644 --- a/pkg/p2p/client_batch_sender_test.go +++ b/pkg/p2p/client_batch_sender_test.go @@ -14,7 +14,6 @@ package p2p import ( - "context" "fmt" "math" "testing" @@ -25,8 +24,7 @@ import ( ) func TestClientBatchSenderMaxCount(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() grpcStream := newMockSendMessageClient(ctx) sender := newClientBatchSender(grpcStream, 100, math.MaxInt64) @@ -36,7 +34,7 @@ func TestClientBatchSenderMaxCount(t *testing.T) { for i := 1; i < 100; i++ { err := sender.Append(&proto.MessageEntry{ Topic: "test-topic", - Content: []byte(fmt.Sprintf("test-%d", i)), + Content: fmt.Appendf(nil, "test-%d", i), Sequence: int64(i), }) require.NoError(t, err) @@ -61,8 +59,7 @@ func TestClientBatchSenderMaxCount(t *testing.T) { } func TestClientBatchSenderMaxSize(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() grpcStream := newMockSendMessageClient(ctx) sender := newClientBatchSender(grpcStream, math.MaxInt64, 1000) @@ -72,7 +69,7 @@ func TestClientBatchSenderMaxSize(t *testing.T) { for size := 0; size < 220; { msg := &proto.MessageEntry{ Topic: "test-topic", - Content: []byte(fmt.Sprintf("test-%d", i)), + Content: fmt.Appendf(nil, "test-%d", i), Sequence: int64(i), } i++ @@ -93,15 +90,14 @@ func TestClientBatchSenderMaxSize(t *testing.T) { // one more message err := sender.Append(&proto.MessageEntry{ Topic: "test-topic", - Content: []byte(fmt.Sprintf("test-%d", i)), + Content: fmt.Appendf(nil, "test-%d", i), Sequence: int64(i), }) require.NoError(t, err) } func TestClientBatchSenderFlush(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() grpcStream := newMockSendMessageClient(ctx) sender := newClientBatchSender(grpcStream, math.MaxInt64, 1000) diff --git a/pkg/p2p/client_connector_test.go b/pkg/p2p/client_connector_test.go index 1777f707cf..1260f1dcbe 100644 --- a/pkg/p2p/client_connector_test.go +++ b/pkg/p2p/client_connector_test.go @@ -52,11 +52,9 @@ func TestClientConnector(t *testing.T) { p2p.RegisterCDCPeerToPeerServer(grpcServer, mockService) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { _ = grpcServer.Serve(lis) - }() + }) cc := newClientConnector() diff --git a/pkg/p2p/grpc_client.go b/pkg/p2p/grpc_client.go index a926d11b18..d8d46cd5b7 100644 --- a/pkg/p2p/grpc_client.go +++ b/pkg/p2p/grpc_client.go @@ -15,6 +15,7 @@ package p2p import ( "context" + "maps" "sync" "time" @@ -251,9 +252,7 @@ func (c *grpcMessageClient) runTx(ctx context.Context, stream MessageClientStrea func (c *grpcMessageClient) retrySending(ctx context.Context, stream MessageClientStream) error { topicsCloned := make(map[string]*topicEntry) c.topicMu.RLock() - for k, v := range c.topics { - topicsCloned[k] = v - } + maps.Copy(topicsCloned, c.topics) c.topicMu.RUnlock() batcher := c.newSenderFn(stream) @@ -355,13 +354,13 @@ func (c *grpcMessageClient) runRx(ctx context.Context, stream MessageClientStrea // SendMessage sends a message. It will block if the client is not ready to // accept the message for now. Once the function returns without an error, // the client will try its best to send the message, until `Run` is canceled. -func (c *grpcMessageClient) SendMessage(ctx context.Context, topic Topic, value interface{}) (seq Seq, ret error) { +func (c *grpcMessageClient) SendMessage(ctx context.Context, topic Topic, value any) (seq Seq, ret error) { return c.sendMessage(ctx, topic, value, false) } // TrySendMessage tries to send a message. It will return ErrPeerMessageSendTryAgain // if the client is not ready to accept the message. -func (c *grpcMessageClient) TrySendMessage(ctx context.Context, topic Topic, value interface{}) (seq Seq, ret error) { +func (c *grpcMessageClient) TrySendMessage(ctx context.Context, topic Topic, value any) (seq Seq, ret error) { // FIXME (zixiong): This is a temporary way for testing client congestion. // This failpoint will be removed once we abstract the MessageClient as an interface. failpoint.Inject("ClientInjectSendMessageTryAgain", func() { @@ -376,7 +375,7 @@ func (c *grpcMessageClient) TrySendMessage(ctx context.Context, topic Topic, val return c.sendMessage(ctx, topic, value, true) } -func (c *grpcMessageClient) sendMessage(ctx context.Context, topic Topic, value interface{}, nonblocking bool) (seq Seq, ret error) { +func (c *grpcMessageClient) sendMessage(ctx context.Context, topic Topic, value any, nonblocking bool) (seq Seq, ret error) { if c.isClosed.Load() { return 0, cerrors.ErrPeerMessageClientClosed.GenWithStackByArgs() } diff --git a/pkg/p2p/grpc_client_test.go b/pkg/p2p/grpc_client_test.go index 378b82a1a9..4cc8e66f4a 100644 --- a/pkg/p2p/grpc_client_test.go +++ b/pkg/p2p/grpc_client_test.go @@ -113,13 +113,11 @@ func TestMessageClientBasics(t *testing.T) { grpcStream.On("Recv").Return(nil, nil) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(ctx, "", "", "node-2", &security.Credential{}) require.Error(t, err) require.Regexp(t, "context canceled", err.Error()) - }() + }) // wait for the stream meta to be received require.Eventuallyf(t, func() bool { @@ -263,13 +261,11 @@ func TestClientPermanentFailure(t *testing.T) { }, nil) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(ctx, "", "", "node-2", &security.Credential{}) require.Error(t, err) require.Regexp(t, ".*ErrPeerMessageClientPermanentFail.*", err.Error()) - }() + }) wg.Wait() @@ -324,13 +320,11 @@ func TestClientSendAnomalies(t *testing.T) { sender.On("Append", mock.Anything).Return(nil) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(runCtx, "", "", "node-2", &security.Credential{}) require.Error(t, err) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) // Test point 1: ErrPeerMessageSendTryAgain _, err := client.TrySendMessage(ctx, "test-topic", &testMessage{Value: 1}) diff --git a/pkg/p2p/internal/send_chan_test.go b/pkg/p2p/internal/send_chan_test.go index f35d4814ba..c7e1dab0a0 100644 --- a/pkg/p2p/internal/send_chan_test.go +++ b/pkg/p2p/internal/send_chan_test.go @@ -40,10 +40,8 @@ func TestSendChanBasics(t *testing.T) { var wg sync.WaitGroup // Runs the producers - for i := 0; i < numProducers; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range numProducers { + wg.Go(func() { lastSeq := int64(0) for j := 0; j < numMsgPerProducer; { ok, seq := c.SendAsync( @@ -59,13 +57,11 @@ func TestSendChanBasics(t *testing.T) { require.Greater(t, seq, lastSeq) lastSeq = seq } - }() + }) } // Runs the consumer - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { ticker := time.NewTicker(time.Millisecond * 10) recvCount := 0 @@ -83,7 +79,7 @@ func TestSendChanBasics(t *testing.T) { return } } - }() + }) wg.Wait() cancel() @@ -101,12 +97,10 @@ func TestSendChanSendSync(t *testing.T) { var wg sync.WaitGroup // Runs the producers - for i := 0; i < numProducers; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range numProducers { + wg.Go(func() { lastSeq := int64(0) - for j := 0; j < numMsgPerProducerForSync; j++ { + for range numMsgPerProducerForSync { seq, err := c.SendSync( ctx, "test-topic", @@ -119,13 +113,11 @@ func TestSendChanSendSync(t *testing.T) { require.Greater(t, seq, lastSeq) lastSeq = seq } - }() + }) } // Runs the consumer - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { ticker := time.NewTicker(time.Millisecond * 10) recvCount := 0 @@ -143,7 +135,7 @@ func TestSendChanSendSync(t *testing.T) { return } } - }() + }) wg.Wait() cancel() @@ -155,9 +147,7 @@ func BenchmarkSendChanSendAsyncSPSC(b *testing.B) { seq := atomic.NewInt64(0) c := NewSendChan(defaultSendChanCap) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for j := 0; j < b.N; { ok, _ := c.SendAsync("test-topic", []byte("test-value"), func() int64 { return seq.Inc() @@ -167,7 +157,7 @@ func BenchmarkSendChanSendAsyncSPSC(b *testing.B) { } j++ } - }() + }) recvCount := 0 dummyTicker := make(chan time.Time) @@ -196,9 +186,7 @@ func BenchmarkSendChanSendSyncSPSC(b *testing.B) { seq := atomic.NewInt64(0) c := NewSendChan(defaultSendChanCap) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for j := 0; j < b.N; j++ { _, _ = c.SendSync( context.TODO(), @@ -208,7 +196,7 @@ func BenchmarkSendChanSendSyncSPSC(b *testing.B) { return seq.Inc() }) } - }() + }) recvCount := 0 dummyTicker := make(chan time.Time) @@ -235,10 +223,8 @@ func BenchmarkSendChanSendAsyncMPSC8(b *testing.B) { seq := atomic.NewInt64(0) c := NewSendChan(defaultSendChanCap) - for i := 0; i < 8; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 8 { + wg.Go(func() { for j := 0; j < b.N; { ok, _ := c.SendAsync("test-topic", []byte("test-value"), func() int64 { return seq.Inc() @@ -248,7 +234,7 @@ func BenchmarkSendChanSendAsyncMPSC8(b *testing.B) { } j++ } - }() + }) } recvCount := 0 @@ -277,10 +263,8 @@ func BenchmarkSendChanSendSyncMPSC8(b *testing.B) { c := NewSendChan(defaultSendChanCap) dummyCloseCh := make(chan struct{}) - for i := 0; i < 8; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 8 { + wg.Go(func() { for j := 0; j < b.N; j++ { _, _ = c.SendSync( context.TODO(), @@ -290,7 +274,7 @@ func BenchmarkSendChanSendSyncMPSC8(b *testing.B) { return seq.Inc() }) } - }() + }) } recvCount := 0 diff --git a/pkg/p2p/message_router.go b/pkg/p2p/message_router.go index 6178bb73e2..3276a424e0 100644 --- a/pkg/p2p/message_router.go +++ b/pkg/p2p/message_router.go @@ -171,9 +171,7 @@ func (m *messageRouterImpl) GetClient(target NodeID) MessageClient { MessageClient: client, cancelFn: cancel, } - m.wg.Add(1) - go func() { - defer m.wg.Done() + m.wg.Go(func() { defer cancel() err := client.Run(ctx, "tcp", addr, target, m.credentials) if err != nil { @@ -198,7 +196,7 @@ func (m *messageRouterImpl) GetClient(target NodeID) MessageClient { m.mu.Lock() defer m.mu.Unlock() delete(m.clients, target) - }() + }) } m.clients[target] = cliWrapper diff --git a/pkg/p2p/message_router_test.go b/pkg/p2p/message_router_test.go index 355c92c9ff..359b964fcd 100644 --- a/pkg/p2p/message_router_test.go +++ b/pkg/p2p/message_router_test.go @@ -78,22 +78,18 @@ func (s *messageRouterTestSuite) addServer(ctx context.Context, t *testing.T, id s.messageRouter.AddPeer(id, addr) - s.wg.Add(1) - go func() { - defer s.wg.Done() + s.wg.Go(func() { _ = grpcServer.Serve(lis) - }() + }) - s.wg.Add(1) - go func() { - defer s.wg.Done() + s.wg.Go(func() { defer grpcServer.Stop() defer s.messageRouter.RemovePeer(id) err := newServer.Run(ctx, nil) if err != nil { require.Regexp(t, ".*context canceled.*", err.Error()) } - }() + }) } func (s *messageRouterTestSuite) close() { @@ -123,7 +119,7 @@ func TestMessageRouterBasic(t *testing.T) { require.Nilf(t, noClient, "no client should have been created") var lastIndex [3]int64 - mustAddHandler(ctx, t, suite.getServer("server-1"), "test-topic", &testTopicContent{}, func(senderID string, i interface{}) error { + mustAddHandler(ctx, t, suite.getServer("server-1"), "test-topic", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -132,7 +128,7 @@ func TestMessageRouterBasic(t *testing.T) { return nil }) - mustAddHandler(ctx, t, suite.getServer("server-2"), "test-topic", &testTopicContent{}, func(senderID string, i interface{}) error { + mustAddHandler(ctx, t, suite.getServer("server-2"), "test-topic", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -141,7 +137,7 @@ func TestMessageRouterBasic(t *testing.T) { return nil }) - mustAddHandler(ctx, t, suite.getServer("server-3"), "test-topic", &testTopicContent{}, func(senderID string, i interface{}) error { + mustAddHandler(ctx, t, suite.getServer("server-3"), "test-topic", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -151,7 +147,7 @@ func TestMessageRouterBasic(t *testing.T) { }) var lastSeq [3]Seq - for i := 0; i < defaultMessageBatchSizeLarge; i++ { + for i := range defaultMessageBatchSizeLarge { serverIdx := i % 3 serverID := fmt.Sprintf("server-%d", serverIdx+1) Seq, err := suite.messageRouter.GetClient(serverID).SendMessage(ctx, "test-topic", &testTopicContent{int64(i/3) + 1}) @@ -197,7 +193,7 @@ func TestMessageRouterRemovePeer(t *testing.T) { suite.addServer(ctx, t, "server-2") var lastIndex [3]int64 - mustAddHandler(ctx, t, suite.getServer("server-1"), "test-topic", &testTopicContent{}, func(senderID string, i interface{}) error { + mustAddHandler(ctx, t, suite.getServer("server-1"), "test-topic", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -206,7 +202,7 @@ func TestMessageRouterRemovePeer(t *testing.T) { return nil }) - mustAddHandler(ctx, t, suite.getServer("server-2"), "test-topic", &testTopicContent{}, func(senderID string, i interface{}) error { + mustAddHandler(ctx, t, suite.getServer("server-2"), "test-topic", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -216,11 +212,9 @@ func TestMessageRouterRemovePeer(t *testing.T) { }) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { var lastSeq Seq - for i := 0; i < defaultMessageBatchSizeLarge; i++ { + for i := range defaultMessageBatchSizeLarge { var err error lastSeq, err = suite.messageRouter.GetClient("server-1"). SendMessage(ctx, "test-topic", &testTopicContent{int64(i + 1)}) @@ -233,14 +227,12 @@ func TestMessageRouterRemovePeer(t *testing.T) { } return seq >= lastSeq }, time.Second*10, time.Millisecond*20) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { client := suite.messageRouter.GetClient("server-2") require.NotNil(t, client) - for i := 0; i < defaultMessageBatchSizeSmall; i++ { + for i := range defaultMessageBatchSizeSmall { var err error _, err = client.SendMessage(ctx, "test-topic", &testTopicContent{int64(i + 1)}) require.NoError(t, err) @@ -253,7 +245,7 @@ func TestMessageRouterRemovePeer(t *testing.T) { return err != nil }, time.Millisecond*500, time.Millisecond*50) require.Regexp(t, ".*ErrPeerMessageClientClosed.*", err.Error()) - }() + }) wg.Wait() suite.close() diff --git a/pkg/p2p/mock_cluster.go b/pkg/p2p/mock_cluster.go index 1c9a28c1ae..3aa2fde44e 100644 --- a/pkg/p2p/mock_cluster.go +++ b/pkg/p2p/mock_cluster.go @@ -85,28 +85,22 @@ func newMockNode(t *testing.T, id NodeID) *MockNode { grpcServer := grpc.NewServer() proto.RegisterCDCPeerToPeerServer(grpcServer, ret.Server) - ret.wg.Add(1) - go func() { - defer ret.wg.Done() + ret.wg.Go(func() { lis, err := net.Listen("tcp", addr) require.NoError(t, err) _ = grpcServer.Serve(lis) - }() + }) - ret.wg.Add(1) - go func() { - defer ret.wg.Done() + ret.wg.Go(func() { err := ret.Server.Run(ctx, nil) require.Error(t, err) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) - ret.wg.Add(1) - go func() { - defer ret.wg.Done() + ret.wg.Go(func() { <-ctx.Done() grpcServer.Stop() - }() + }) return ret } @@ -124,7 +118,7 @@ func NewMockCluster(t *testing.T, nodeCount int) *MockCluster { Nodes: make(map[NodeID]*MockNode), } - for i := 0; i < nodeCount; i++ { + for i := range nodeCount { id := fmt.Sprintf("capture-%d", i) ret.Nodes[id] = newMockNode(t, id) } diff --git a/pkg/p2p/model.go b/pkg/p2p/model.go index 0de5676421..71c42e17fd 100644 --- a/pkg/p2p/model.go +++ b/pkg/p2p/model.go @@ -37,5 +37,5 @@ type MessageEntry = *proto.MessageEntry // RawMessageEntry is an alias for the protobuf-generated type for a message. type RawMessageEntry struct { topic Topic - value interface{} + value any } diff --git a/pkg/p2p/serializer.go b/pkg/p2p/serializer.go index bf787c6fad..aa43721896 100644 --- a/pkg/p2p/serializer.go +++ b/pkg/p2p/serializer.go @@ -22,14 +22,14 @@ type Serializable interface { Unmarshal(data []byte) error } -func marshalMessage(value interface{}) ([]byte, error) { +func marshalMessage(value any) ([]byte, error) { if value, ok := value.(Serializable); ok { return value.Marshal() } return json.Marshal(value) } -func unmarshalMessage(data []byte, value interface{}) error { +func unmarshalMessage(data []byte, value any) error { if value, ok := value.(Serializable); ok { return value.Unmarshal(data) } diff --git a/pkg/p2p/server.go b/pkg/p2p/server.go index 8c88467669..e93106620c 100755 --- a/pkg/p2p/server.go +++ b/pkg/p2p/server.go @@ -150,7 +150,7 @@ type MessageServer struct { // taskQueue is used to store internal tasks MessageServer // needs to execute serially. - taskQueue chan interface{} + taskQueue chan any // The WorkerPool instance used to execute message handlers. pool workerpool.WorkerPool @@ -204,7 +204,7 @@ func NewMessageServer(serverID NodeID, config *MessageServerConfig) *MessageServ peers: make(map[string]*cdcPeer), pendingMessages: make(map[topicSenderPair][]pendingMessageEntry), acks: newAckManager(), - taskQueue: make(chan interface{}, config.MaxPendingTaskCount), + taskQueue: make(chan any, config.MaxPendingTaskCount), pool: workerpool.NewDefaultWorkerPool(config.WorkerPoolSize), closeCh: make(chan struct{}), config: config, @@ -406,7 +406,7 @@ func (m *MessageServer) ScheduleDeregisterPeerTask(ctx context.Context, peerID s // We pass an object of the desired type, and use `reflect.TypeOf` to extract the type, // and then when we need it, we can use `reflect.New` to allocate a new object of this // type. -type typeInformation = interface{} +type typeInformation = any // SyncAddHandler registers a handler for messages in a given topic and waits for the operation // to complete. @@ -414,7 +414,7 @@ func (m *MessageServer) SyncAddHandler( ctx context.Context, topic string, tpi typeInformation, - fn func(string, interface{}) error, + fn func(string, any) error, ) (<-chan error, error) { doneCh, errCh, err := m.AddHandler(ctx, topic, tpi, fn) if err != nil { @@ -435,7 +435,7 @@ func (m *MessageServer) AddHandler( ctx context.Context, topic string, tpi typeInformation, - fn func(string, interface{}) error, + fn func(string, any) error, ) (chan struct{}, <-chan error, error) { tp := reflect.TypeOf(tpi) @@ -443,7 +443,7 @@ func (m *MessageServer) AddHandler( "topic": topic, }) - poolHandle := m.pool.RegisterEvent(func(ctx context.Context, argsI interface{}) error { + poolHandle := m.pool.RegisterEvent(func(ctx context.Context, argsI any) error { args, ok := argsI.(poolEventArgs) if !ok { // Handle message from local. @@ -637,7 +637,7 @@ func (m *MessageServer) registerPeer( return nil } -func (m *MessageServer) scheduleTask(ctx context.Context, task interface{}) error { +func (m *MessageServer) scheduleTask(ctx context.Context, task any) error { select { case <-ctx.Done(): return errors.Trace(ctx.Err()) @@ -648,7 +648,7 @@ func (m *MessageServer) scheduleTask(ctx context.Context, task interface{}) erro return nil } -func (m *MessageServer) scheduleTaskBlocking(ctx context.Context, task interface{}) error { +func (m *MessageServer) scheduleTaskBlocking(ctx context.Context, task any) error { select { case <-ctx.Done(): return errors.Trace(ctx.Err()) diff --git a/pkg/p2p/server_ack_manager.go b/pkg/p2p/server_ack_manager.go index 54789fefa1..7e49adcd33 100644 --- a/pkg/p2p/server_ack_manager.go +++ b/pkg/p2p/server_ack_manager.go @@ -101,7 +101,7 @@ func (m *ackManager) Range(senderID NodeID, fn func(topic Topic, seq Seq) bool) // RemoveTopic removes a topic for all nodes. // We do not support removing a topic from a specific node. func (m *ackManager) RemoveTopic(topic Topic) { - m.peers.Range(func(key, value interface{}) bool { + m.peers.Range(func(key, value any) bool { ackList := value.(*peerAckList) ackList.mu.Lock() defer ackList.mu.Unlock() diff --git a/pkg/p2p/server_client_integration_test.go b/pkg/p2p/server_client_integration_test.go index d0206461c2..3560b94ba1 100644 --- a/pkg/p2p/server_client_integration_test.go +++ b/pkg/p2p/server_client_integration_test.go @@ -65,11 +65,9 @@ func newServerForIntegrationTesting(t *testing.T, serverID string, configOpts .. p2p.RegisterCDCPeerToPeerServer(grpcServer, server) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { _ = grpcServer.Serve(lis) - }() + }) cancel = func() { grpcServer.Stop() @@ -95,9 +93,7 @@ func runP2PIntegrationTest( defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { err := server.Run(ctx, nil) if cerror.ErrPeerMessageInjectedServerRestart.Equal(err) { @@ -107,12 +103,12 @@ func runP2PIntegrationTest( require.Regexp(t, ".*context canceled.*", err.Error()) break } - }() + }) - for j := 0; j < numTopics; j++ { + for j := range numTopics { topicName := fmt.Sprintf("test-topic-%d", j) var lastIndex int64 - errCh := mustAddHandler(ctx, t, server, topicName, &testTopicContent{}, func(senderID string, i interface{}) error { + errCh := mustAddHandler(ctx, t, server, topicName, &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -123,27 +119,23 @@ func runP2PIntegrationTest( return nil }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case <-ctx.Done(): case err := <-errCh: require.NoError(t, err) } - }() + }) } client := NewGrpcMessageClient("test-client-1", clientConfig4Testing) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(ctx, "tcp", addr, "test-server-1", &security.Credential{}) if err != nil { log.Warn("client returned error", zap.Error(err)) require.Regexp(t, ".*context canceled.*", err.Error()) } - }() + }) var wg1 sync.WaitGroup wg1.Add(numTopics * clientConcurrency) @@ -152,7 +144,7 @@ func runP2PIntegrationTest( go func() { defer wg1.Done() var oldSeq Seq - for i := 0; i < size; i++ { + for i := range size { content := &testTopicContent{Index: int64(i + 1)} seq, err := client.SendMessage(ctx, topicName, content) require.NoError(t, err) @@ -260,17 +252,15 @@ func TestMessageClientBasicNonblocking(t *testing.T) { defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) if err != nil { require.Regexp(t, ".*context canceled.*", err.Error()) } - }() + }) var lastIndex int64 - errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i interface{}) error { + errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -279,27 +269,23 @@ func TestMessageClientBasicNonblocking(t *testing.T) { return nil }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case <-ctx.Done(): case err := <-errCh: require.NoError(t, err) } - }() + }) client := NewGrpcMessageClient("test-client-1", clientConfig4Testing) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(ctx, "tcp", addr, "test-server-1", &security.Credential{}) require.Error(t, err) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) var oldSeq Seq - for i := 0; i < defaultMessageBatchSizeSmall; i++ { + for i := range defaultMessageBatchSizeSmall { content := &testTopicContent{Index: int64(i + 1)} var ( seq Seq @@ -337,38 +323,32 @@ func TestMessageBackPressure(t *testing.T) { defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) if err != nil { require.Regexp(t, ".*context canceled.*", err.Error()) } - }() + }) // No-op handler. We are only testing for back-pressure. - errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i interface{}) error { + errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i any) error { return nil }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case <-ctx.Done(): case err := <-errCh: require.NoError(t, err) } - }() + }) client := NewGrpcMessageClient("test-client-1", clientConfig4Testing) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(ctx, "tcp", addr, "test-server-1", &security.Credential{}) require.Error(t, err) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) _ = failpoint.Enable("github.com/pingcap/tiflow/pkg/p2p/ServerInjectTaskDelay", "sleep(1)") defer func() { @@ -376,7 +356,7 @@ func TestMessageBackPressure(t *testing.T) { }() var lastSeq Seq - for i := 0; i < defaultMessageBatchSizeLarge; i++ { + for range defaultMessageBatchSizeLarge { seq, err := client.SendMessage(ctx, "test-topic-1", &testTopicContent{}) require.NoError(t, err) atomic.StoreInt64(&lastSeq, seq) @@ -405,43 +385,37 @@ func TestTopicCongested(t *testing.T) { defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) if err != nil { require.Regexp(t, ".*context canceled.*", err.Error()) } - }() + }) newClientConfig := *clientConfig4Testing newClientConfig.MaxBatchCount = 1 newClientConfig.RetryRateLimitPerSecond = 100 client := NewGrpcMessageClient("test-client-1", clientConfig4Testing) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := client.Run(ctx, "tcp", addr, "test-server-1", &security.Credential{}) require.Error(t, err) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) var lastSeq Seq - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { - for i := 0; i < 100; i++ { + for range 100 { seq, err := client.SendMessage(ctx, "test-topic-1", &testTopicContent{}) require.NoError(t, err) atomic.StoreInt64(&lastSeq, seq) time.Sleep(10 * time.Millisecond) } - }() + }) // No-op handler. _ = mustAddHandler(ctx, t, server, "test-topic-1", - &testTopicContent{}, func(senderID string, i interface{}) error { + &testTopicContent{}, func(senderID string, i any) error { return nil }) @@ -453,7 +427,7 @@ func TestTopicCongested(t *testing.T) { // No-op handler. _ = mustAddHandler(ctx, t, server, "test-topic-1", - &testTopicContent{}, func(senderID string, i interface{}) error { + &testTopicContent{}, func(senderID string, i any) error { return nil }) diff --git a/pkg/p2p/server_stream_handle_test.go b/pkg/p2p/server_stream_handle_test.go index 1034c5811a..a5221e1365 100644 --- a/pkg/p2p/server_stream_handle_test.go +++ b/pkg/p2p/server_stream_handle_test.go @@ -39,12 +39,10 @@ func TestStreamHandleSend(t *testing.T) { defer cancel() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { msg := <-sendCh require.Equal(t, "test", msg.ErrorMessage) - }() + }) err := h.Send(ctx, proto.SendMessageResponse{ ErrorMessage: "test", @@ -68,13 +66,11 @@ func TestStreamHandleCloseWhileSending(t *testing.T) { defer cancel() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := h.Send(ctx, proto.SendMessageResponse{}) require.Error(t, err) require.Regexp(t, "ErrPeerMessageInternalSenderClosed", err.Error()) - }() + }) time.Sleep(100 * time.Millisecond) h.Close() diff --git a/pkg/p2p/server_test.go b/pkg/p2p/server_test.go index 017991e413..ae570c28a5 100644 --- a/pkg/p2p/server_test.go +++ b/pkg/p2p/server_test.go @@ -65,11 +65,9 @@ func newServerForTesting(t *testing.T, serverID string) (server *MessageServer, p2p.RegisterCDCPeerToPeerServer(grpcServer, server) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { _ = grpcServer.Serve(lis) - }() + }) cancel = func() { grpcServer.Stop() @@ -93,7 +91,7 @@ func newServerForTesting(t *testing.T, serverID string) (server *MessageServer, return } -func mustAddHandler(ctx context.Context, t *testing.T, server *MessageServer, topic string, tpi interface{}, f func(string, interface{}) error) <-chan error { +func mustAddHandler(ctx context.Context, t *testing.T, server *MessageServer, topic string, tpi any, f func(string, any) error) <-chan error { doneCh, errCh, err := server.AddHandler(ctx, topic, tpi, f) require.NoError(t, err) @@ -123,15 +121,13 @@ func TestServerMultiClientSingleTopic(t *testing.T) { localCh := make(chan RawMessageEntry, defaultMessageBatchSizeMedium) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, localCh) require.Regexp(t, ".*context canceled.*", err) - }() + }) var ackWg sync.WaitGroup - for i := 0; i < defaultMultiClientCount; i++ { + for i := range defaultMultiClientCount { wg.Add(1) ackWg.Add(1) i := i @@ -170,7 +166,7 @@ func TestServerMultiClientSingleTopic(t *testing.T) { } }() - for j := 0; j < defaultMessageBatchSizeMedium; j++ { + for j := range defaultMessageBatchSizeMedium { content := &testTopicContent{Index: int64(j + 1)} bytes, err := json.Marshal(content) require.NoError(t, err) @@ -192,7 +188,7 @@ func TestServerMultiClientSingleTopic(t *testing.T) { time.Sleep(1 * time.Second) lastIndices := sync.Map{} - errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i interface{}) error { + errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i any) error { if strings.Contains(senderID, "server") { require.Equal(t, serverID, senderID) } else { @@ -216,7 +212,7 @@ func TestServerMultiClientSingleTopic(t *testing.T) { ackWg.Add(1) go func() { defer wg.Done() - for j := 0; j < defaultMessageBatchSizeLarge; j++ { + for j := range defaultMessageBatchSizeLarge { content := &testTopicContent{Index: int64(j + 1)} select { case <-ctx.Done(): @@ -249,16 +245,14 @@ func TestServerMultiClientSingleTopic(t *testing.T) { }() }() - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case <-ctx.Done(): case err := <-errCh: require.Error(t, err) require.Regexp(t, ".*ErrWorkerPoolHandleCancelled.*", err.Error()) } - }() + }) ackWg.Wait() @@ -283,18 +277,16 @@ func TestServerDeregisterHandler(t *testing.T) { defer closer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) var ( lastIndex int64 removed int32 ) - errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i interface{}) error { + errCh := mustAddHandler(ctx, t, server, "test-topic-1", &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, int32(0), atomic.LoadInt32(&removed)) require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) @@ -304,15 +296,13 @@ func TestServerDeregisterHandler(t *testing.T) { return nil }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case <-ctx.Done(): case err := <-errCh: require.Regexp(t, ".*ErrWorkerPoolHandleCancelled.*", err.Error()) } - }() + }) client, closeClient := newClient() defer closeClient() @@ -330,9 +320,7 @@ func TestServerDeregisterHandler(t *testing.T) { require.NoError(t, err) removeHandler := func() { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { doneCh, err := server.RemoveHandler(ctx, "test-topic-1") require.NoError(t, err) select { @@ -341,12 +329,10 @@ func TestServerDeregisterHandler(t *testing.T) { case <-doneCh: } atomic.StoreInt32(&removed, 1) - }() + }) } - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer cancel() defer closer() var lastAck int64 @@ -367,9 +353,9 @@ func TestServerDeregisterHandler(t *testing.T) { return } } - }() + }) - for i := 0; i < defaultMessageBatchSizeSmall; i++ { + for i := range defaultMessageBatchSizeSmall { content := &testTopicContent{Index: int64(i + 1)} bytes, err := json.Marshal(content) require.NoError(t, err) @@ -398,12 +384,10 @@ func TestServerClosed(t *testing.T) { cctx, cancelServer := context.WithCancel(ctx) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(cctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) client, closeClient := newClient() defer closeClient() @@ -440,12 +424,10 @@ func TestServerTopicCongestedDueToNoHandler(t *testing.T) { defer closer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) client, closeClient := newClient() defer closeClient() @@ -462,9 +444,7 @@ func TestServerTopicCongestedDueToNoHandler(t *testing.T) { }) require.NoError(t, err) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { resp, err := stream.Recv() require.NoError(t, err) @@ -475,9 +455,9 @@ func TestServerTopicCongestedDueToNoHandler(t *testing.T) { cancel() return } - }() + }) - for i := 0; i < defaultMessageBatchSizeMedium; i++ { + for i := range defaultMessageBatchSizeMedium { content := &testTopicContent{Index: int64(i + 1)} bytes, err := json.Marshal(content) require.NoError(t, err) @@ -508,12 +488,10 @@ func TestServerIncomingConnectionStale(t *testing.T) { defer closer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) client, closeClient := newClient() defer closeClient() @@ -574,12 +552,10 @@ func TestServerOldConnectionStale(t *testing.T) { defer closer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) client, closeClient := newClient() defer closeClient() @@ -639,16 +615,14 @@ func TestServerRepeatedMessages(t *testing.T) { defer closer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) var lastIndex int64 _ = mustAddHandler(ctx, t, server, "test-topic-1", - &testTopicContent{}, func(senderID string, i interface{}) error { + &testTopicContent{}, func(senderID string, i any) error { require.Equal(t, "test-client-1", senderID) require.IsType(t, &testTopicContent{}, i) content := i.(*testTopicContent) @@ -672,9 +646,7 @@ func TestServerRepeatedMessages(t *testing.T) { }) require.NoError(t, err) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer cancel() for { resp, err := stream.Recv() @@ -690,9 +662,9 @@ func TestServerRepeatedMessages(t *testing.T) { return } } - }() + }) - for i := 0; i < defaultMessageBatchSizeSmall; i++ { + for i := range defaultMessageBatchSizeSmall { content := &testTopicContent{Index: int64(i + 1)} bytes, err := json.Marshal(content) require.NoError(t, err) @@ -740,41 +712,33 @@ func TestServerExitWhileAddingHandler(t *testing.T) { defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(serverCtx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) waitCh := make(chan struct{}) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.scheduleTask(ctx, taskDebugDelay{ doneCh: waitCh, }) require.NoError(t, err) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { time.Sleep(time.Millisecond * 100) - _, err := server.SyncAddHandler(ctx, "test-topic", &testTopicContent{}, func(s string, i interface{}) error { + _, err := server.SyncAddHandler(ctx, "test-topic", &testTopicContent{}, func(s string, i any) error { return nil }) require.Error(t, err) require.Regexp(t, ".*ErrPeerMessageServerClosed.*", err.Error()) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { time.Sleep(time.Millisecond * 300) cancelServer() - }() + }) wg.Wait() } @@ -790,19 +754,15 @@ func TestServerExitWhileRemovingHandler(t *testing.T) { defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(serverCtx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) waitCh := make(chan struct{}) - wg.Add(1) - go func() { - defer wg.Done() - _, err := server.SyncAddHandler(ctx, "test-topic", &testTopicContent{}, func(s string, i interface{}) error { + wg.Go(func() { + _, err := server.SyncAddHandler(ctx, "test-topic", &testTopicContent{}, func(s string, i any) error { return nil }) require.NoError(t, err) @@ -813,14 +773,12 @@ func TestServerExitWhileRemovingHandler(t *testing.T) { time.Sleep(time.Millisecond * 100) err = server.SyncRemoveHandler(ctx, "test-topic") require.NoError(t, err) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { time.Sleep(time.Millisecond * 500) cancelServer() - }() + }) wg.Wait() } @@ -833,12 +791,10 @@ func TestReceiverIDMismatch(t *testing.T) { defer closer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) client, closeClient := newClient() defer closeClient() @@ -874,15 +830,13 @@ func TestServerDataLossAfterUnregisterHandle(t *testing.T) { defer cancelServer() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(serverCtx, nil) require.Regexp(t, ".*context canceled.*", err.Error()) - }() + }) var called int32 - mustAddHandler(ctx, t, server, "blocking-handler", &testTopicContent{}, func(_ string, _ interface{}) error { + mustAddHandler(ctx, t, server, "blocking-handler", &testTopicContent{}, func(_ string, _ any) error { if atomic.AddInt32(&called, 1) == 2 { time.Sleep(1 * time.Second) } @@ -934,7 +888,7 @@ func TestServerDataLossAfterUnregisterHandle(t *testing.T) { require.NoError(t, err) // re-registers the handler - errCh := mustAddHandler(ctx, t, server, "blocking-handler", &testTopicContent{}, func(_ string, msg interface{}) error { + errCh := mustAddHandler(ctx, t, server, "blocking-handler", &testTopicContent{}, func(_ string, msg any) error { require.Fail(t, "should not have been called", "value: %v", msg) return nil }) @@ -975,12 +929,10 @@ func TestServerDeregisterPeer(t *testing.T) { server.config.MaxPendingMessageCountPerTopic = math.MaxInt64 var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx, nil) require.Regexp(t, ".*context canceled.*", err) - }() + }) var sendGroup sync.WaitGroup sendGroup.Add(1) diff --git a/pkg/p2p/server_wrapper_test.go b/pkg/p2p/server_wrapper_test.go index af517ab24f..cd7111a491 100644 --- a/pkg/p2p/server_wrapper_test.go +++ b/pkg/p2p/server_wrapper_test.go @@ -75,11 +75,9 @@ func newServerWrapperForTesting(t *testing.T) (server *ServerWrapper, newClient p2p.RegisterCDCPeerToPeerServer(grpcServer, server) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { _ = grpcServer.Serve(lis) - }() + }) cancel = func() { grpcServer.Stop() diff --git a/pkg/pdutil/api_client_test.go b/pkg/pdutil/api_client_test.go index 2331d9b4e5..6c3c703cde 100644 --- a/pkg/pdutil/api_client_test.go +++ b/pkg/pdutil/api_client_test.go @@ -68,8 +68,7 @@ func TestMetaLabelNormal(t *testing.T) { require.NoError(t, err) defer pc.Close() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() err = pc.UpdateMetaLabel(ctx) require.NoError(t, err) mockClient.testServer.Close() @@ -84,8 +83,7 @@ func TestMetaLabelFail(t *testing.T) { defer pc.Close() mockClient.url = "http://127.0.1.1:2345" - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() // test url error err = pc.(*pdAPIClient).patchMetaLabel(ctx) require.Error(t, err) @@ -105,8 +103,7 @@ func TestListGcServiceSafePoint(t *testing.T) { mockClient := newMockPDClient(true) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() pc, err := NewPDAPIClient(mockClient, nil) require.NoError(t, err) @@ -132,7 +129,7 @@ type LabelRule struct { Index int `json:"index"` Labels []RegionLabel `json:"labels"` RuleType string `json:"rule_type"` - Data interface{} `json:"data"` + Data any `json:"data"` } // RegionLabel is the label of a region. @@ -149,7 +146,7 @@ func TestMetaLabelDecodeJSON(t *testing.T) { meta := LabelRulePatch{} require.Nil(t, json.Unmarshal([]byte(addMetaJSON), &meta)) require.Len(t, meta.SetRules, 2) - keys := meta.SetRules[1].Data.([]interface{})[0].(map[string]interface{}) + keys := meta.SetRules[1].Data.([]any)[0].(map[string]any) startKey, err := hex.DecodeString(keys["start_key"].(string)) require.NoError(t, err) endKey, err := hex.DecodeString(keys["end_key"].(string)) diff --git a/pkg/pdutil/clock_test.go b/pkg/pdutil/clock_test.go index 57f7c56360..8d9cf8c61b 100644 --- a/pkg/pdutil/clock_test.go +++ b/pkg/pdutil/clock_test.go @@ -55,8 +55,7 @@ func TestTimeFromPD(t *testing.T) { func TestEventTimeAndProcessingTime(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() mockPDClient := &MockPDClient{} clock, err := NewClock(ctx, mockPDClient) require.NoError(t, err) diff --git a/pkg/retry/retry_test.go b/pkg/retry/retry_test.go index 2080e7cb34..8a36a05807 100644 --- a/pkg/retry/retry_test.go +++ b/pkg/retry/retry_test.go @@ -148,7 +148,7 @@ func TestDoCornerCases(t *testing.T) { require.Equal(t, callCount, 2) var i uint64 - for i = 0; i < 10; i++ { + for i = range 10 { callCount = 0 err = Do(context.Background(), f, WithBackoffBaseDelay(int64(i)), WithBackoffMaxDelay(int64(i)), WithMaxTries(i)) diff --git a/pkg/security/credential.go b/pkg/security/credential.go index ef454bacb6..ea507f411d 100644 --- a/pkg/security/credential.go +++ b/pkg/security/credential.go @@ -54,7 +54,7 @@ func (s Credential) Value() (driver.Value, error) { } // Scan implements the sql.Scanner interface -func (s *Credential) Scan(value interface{}) error { +func (s *Credential) Scan(value any) error { b, ok := value.([]byte) if !ok { return errors.New("type assertion to []byte failed") diff --git a/pkg/security/sasl_test.go b/pkg/security/sasl_test.go index ad8546965b..71f3c90754 100644 --- a/pkg/security/sasl_test.go +++ b/pkg/security/sasl_test.go @@ -76,7 +76,6 @@ func TestSASLMechanismFromString(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() mechanism, err := SASLMechanismFromString(test.s) @@ -129,7 +128,6 @@ func TestAuthTypeFromString(t *testing.T) { } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() diff --git a/pkg/sink/cloudstorage/path_test.go b/pkg/sink/cloudstorage/path_test.go index 691c1346b7..0829064807 100644 --- a/pkg/sink/cloudstorage/path_test.go +++ b/pkg/sink/cloudstorage/path_test.go @@ -58,8 +58,7 @@ func testFilePathGenerator(ctx context.Context, t *testing.T, dir string) *FileP func TestGenerateDataFilePath(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() + ctx := t.Context() table := VersionedTableName{ TableNameWithPhysicTableID: model.TableName{ @@ -159,8 +158,7 @@ func TestGenerateDataFilePath(t *testing.T) { func TestFetchIndexFromFileName(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() + ctx := t.Context() dir := t.TempDir() f := testFilePathGenerator(ctx, t, dir) @@ -207,8 +205,7 @@ func TestFetchIndexFromFileName(t *testing.T) { func TestGenerateDataFilePathWithIndexFile(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() + ctx := t.Context() dir := t.TempDir() f := testFilePathGenerator(ctx, t, dir) @@ -291,8 +288,7 @@ func TestIsSchemaFile(t *testing.T) { func TestCheckOrWriteSchema(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() dir := t.TempDir() f := testFilePathGenerator(ctx, t, dir) @@ -355,8 +351,7 @@ func TestCheckOrWriteSchema(t *testing.T) { func TestRemoveExpiredFilesWithoutPartition(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() dir := t.TempDir() uri := fmt.Sprintf("file:///%s?flush-interval=2s", dir) storage, err := util.GetExternalStorageFromURI(ctx, uri) diff --git a/pkg/sink/cloudstorage/table_definition.go b/pkg/sink/cloudstorage/table_definition.go index 8913f1a4f0..841b9a9bd1 100644 --- a/pkg/sink/cloudstorage/table_definition.go +++ b/pkg/sink/cloudstorage/table_definition.go @@ -38,14 +38,14 @@ const ( // TableCol denotes the column info for a table definition. type TableCol struct { - ID string `json:"ColumnId,omitempty"` - Name string `json:"ColumnName" ` - Tp string `json:"ColumnType"` - Default interface{} `json:"ColumnDefault,omitempty"` - Precision string `json:"ColumnPrecision,omitempty"` - Scale string `json:"ColumnScale,omitempty"` - Nullable string `json:"ColumnNullable,omitempty"` - IsPK string `json:"ColumnIsPk,omitempty"` + ID string `json:"ColumnId,omitempty"` + Name string `json:"ColumnName" ` + Tp string `json:"ColumnType"` + Default any `json:"ColumnDefault,omitempty"` + Precision string `json:"ColumnPrecision,omitempty"` + Scale string `json:"ColumnScale,omitempty"` + Nullable string `json:"ColumnNullable,omitempty"` + IsPK string `json:"ColumnIsPk,omitempty"` } // FromTiColumnInfo converts from TiDB ColumnInfo to TableCol. diff --git a/pkg/sink/cloudstorage/table_definition_test.go b/pkg/sink/cloudstorage/table_definition_test.go index d7b774ce5b..90defaf271 100644 --- a/pkg/sink/cloudstorage/table_definition_test.go +++ b/pkg/sink/cloudstorage/table_definition_test.go @@ -515,7 +515,7 @@ func TestTableDefinitionSum32(t *testing.T) { newDef := def newDef.Columns = newCol - for i := 0; i < n; i++ { + for i := range n { target := rand.Intn(n) newDef.Columns[i], newDef.Columns[target] = newDef.Columns[target], newDef.Columns[i] newChecksum, err := newDef.Sum32(nil) diff --git a/pkg/sink/codec/avro/avro.go b/pkg/sink/codec/avro/avro.go index 52cc83da4c..86a344adc7 100644 --- a/pkg/sink/codec/avro/avro.go +++ b/pkg/sink/codec/avro/avro.go @@ -256,7 +256,7 @@ func (a *BatchEncoder) AppendRowChangedEvent( func (a *BatchEncoder) EncodeCheckpointEvent(ts uint64) (*common.Message, error) { if a.config.EnableTiDBExtension && a.config.AvroEnableWatermark { buf := new(bytes.Buffer) - data := []interface{}{checkpointByte, ts} + data := []any{checkpointByte, ts} for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { @@ -327,9 +327,9 @@ func getOperation(e *model.RowChangedEvent) string { } func (a *BatchEncoder) nativeValueWithExtension( - native map[string]interface{}, + native map[string]any, e *model.RowChangedEvent, -) map[string]interface{} { +) map[string]any { native[tidbOp] = getOperation(e) native[tidbCommitTs] = int64(e.CommitTs) native[tidbPhysicalTime] = oracle.ExtractPhysical(e.CommitTs) @@ -343,10 +343,10 @@ func (a *BatchEncoder) nativeValueWithExtension( } type avroSchemaTop struct { - Tp string `json:"type"` - Name string `json:"name"` - Namespace string `json:"namespace"` - Fields []map[string]interface{} `json:"fields"` + Tp string `json:"type"` + Name string `json:"name"` + Namespace string `json:"namespace"` + Fields []map[string]any `json:"fields"` } const ( @@ -474,26 +474,26 @@ type avroSchema struct { type avroLogicalTypeSchema struct { avroSchema - LogicalType string `json:"logicalType"` - Precision interface{} `json:"precision,omitempty"` - Scale interface{} `json:"scale,omitempty"` + LogicalType string `json:"logicalType"` + Precision any `json:"precision,omitempty"` + Scale any `json:"scale,omitempty"` } func (a *BatchEncoder) schemaWithExtension( top *avroSchemaTop, ) *avroSchemaTop { top.Fields = append(top.Fields, - map[string]interface{}{ + map[string]any{ "name": tidbOp, "type": "string", "default": "", }, - map[string]interface{}{ + map[string]any{ "name": tidbCommitTs, "type": "long", "default": 0, }, - map[string]interface{}{ + map[string]any{ "name": tidbPhysicalTime, "type": "long", "default": 0, @@ -502,17 +502,17 @@ func (a *BatchEncoder) schemaWithExtension( if a.config.EnableRowChecksum { top.Fields = append(top.Fields, - map[string]interface{}{ + map[string]any{ "name": tidbRowLevelChecksum, "type": "string", "default": "", }, - map[string]interface{}{ + map[string]any{ "name": tidbCorrupted, "type": "boolean", "default": false, }, - map[string]interface{}{ + map[string]any{ "name": tidbChecksumVersion, "type": "int", "default": 0, @@ -539,7 +539,7 @@ func (a *BatchEncoder) columns2AvroSchema(tableName model.TableName, input avroE if err != nil { return nil, err } - field := make(map[string]interface{}) + field := make(map[string]any) field["name"] = common.SanitizeName(colx.GetName()) copied := colx @@ -553,7 +553,7 @@ func (a *BatchEncoder) columns2AvroSchema(tableName model.TableName, input avroE // https://github.com/linkedin/goavro/issues/202 if _, ok := avroType.(avroLogicalTypeSchema); ok { if colx.GetFlag().IsNullable() { - field["type"] = []interface{}{"null", avroType} + field["type"] = []any{"null", avroType} field["default"] = nil } else { field["type"] = avroType @@ -561,9 +561,9 @@ func (a *BatchEncoder) columns2AvroSchema(tableName model.TableName, input avroE } else { if colx.GetFlag().IsNullable() { if defaultValue == nil { - field["type"] = []interface{}{"null", avroType} + field["type"] = []any{"null", avroType} } else { - field["type"] = []interface{}{avroType, "null"} + field["type"] = []any{avroType, "null"} } field["default"] = defaultValue } else { @@ -617,8 +617,8 @@ func (a *BatchEncoder) key2AvroSchema(tableName model.TableName, keyColumns avro return string(str), nil } -func (a *BatchEncoder) columns2AvroData(input avroEncodeInput) (map[string]interface{}, error) { - ret := make(map[string]interface{}, len(input.columns)) +func (a *BatchEncoder) columns2AvroData(input avroEncodeInput) (map[string]any, error) { + ret := make(map[string]any, len(input.columns)) for _, col := range input.columns { colx := model.GetColumnDataX(col, input.TableInfo) if colx.ColumnData == nil { @@ -642,7 +642,7 @@ func (a *BatchEncoder) columns2AvroData(input avroEncodeInput) (map[string]inter return ret, nil } -func (a *BatchEncoder) columnToAvroSchema(col model.ColumnDataX) (interface{}, error) { +func (a *BatchEncoder) columnToAvroSchema(col model.ColumnDataX) (any, error) { tt := getTiDBTypeFromColumn(col) switch col.GetType() { @@ -779,7 +779,7 @@ func (a *BatchEncoder) columnToAvroSchema(col model.ColumnDataX) (interface{}, e } } -func (a *BatchEncoder) columnToAvroData(col model.ColumnDataX) (interface{}, string, error) { +func (a *BatchEncoder) columnToAvroData(col model.ColumnDataX) (any, string, error) { if col.Value == nil { return nil, "null", nil } @@ -949,7 +949,7 @@ const ( func (r *avroEncodeResult) toEnvelope() ([]byte, error) { buf := new(bytes.Buffer) - data := []interface{}{r.header, r.data} + data := []any{r.header, r.data} for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { diff --git a/pkg/sink/codec/avro/avro_test.go b/pkg/sink/codec/avro/avro_test.go index 54b11ae4cc..591297181e 100644 --- a/pkg/sink/codec/avro/avro_test.go +++ b/pkg/sink/codec/avro/avro_test.go @@ -14,7 +14,6 @@ package avro import ( - "context" "math/rand" "testing" "time" @@ -33,8 +32,7 @@ import ( func TestDMLEventE2E(t *testing.T) { codecConfig := common.NewConfig(config.ProtocolAvro) codecConfig.EnableTiDBExtension = true - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() _, event, _, _ := utils.NewLargeEvent4Test(t, config.GetDefaultReplicaConfig()) colInfos := event.TableInfo.GetColInfosForRowChangedEvent() @@ -151,8 +149,7 @@ func TestAvroEncode4EnableChecksum(t *testing.T) { codecConfig.AvroDecimalHandlingMode = "string" codecConfig.AvroBigintUnsignedHandlingMode = "string" - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() encoder, err := SetupEncoderAndSchemaRegistry4Testing(ctx, codecConfig) defer TeardownEncoderAndSchemaRegistry4Testing() @@ -174,7 +171,7 @@ func TestAvroEncode4EnableChecksum(t *testing.T) { require.NoError(t, err) require.NotNil(t, res) - m, ok := res.(map[string]interface{}) + m, ok := res.(map[string]any) require.True(t, ok) _, found := m[tidbRowLevelChecksum] @@ -191,8 +188,7 @@ func TestAvroEncode(t *testing.T) { codecConfig := common.NewConfig(config.ProtocolAvro) codecConfig.EnableTiDBExtension = true - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() encoder, err := SetupEncoderAndSchemaRegistry4Testing(ctx, codecConfig) defer TeardownEncoderAndSchemaRegistry4Testing() @@ -213,12 +209,12 @@ func TestAvroEncode(t *testing.T) { res, _, err := avroKeyCodec.NativeFromBinary(data) require.NoError(t, err) require.NotNil(t, res) - for k := range res.(map[string]interface{}) { + for k := range res.(map[string]any) { if k == "_tidb_commit_ts" || k == "_tidb_op" || k == "_tidb_commit_physical_time" { require.Fail(t, "key shall not include extension fields") } } - require.Equal(t, int32(127), res.(map[string]interface{})["tu1"]) + require.Equal(t, int32(127), res.(map[string]any)["tu1"]) bin, err = encoder.encodeValue(ctx, topic, event) require.NoError(t, err) @@ -233,7 +229,7 @@ func TestAvroEncode(t *testing.T) { require.NoError(t, err) require.NotNil(t, res) - for k, v := range res.(map[string]interface{}) { + for k, v := range res.(map[string]any) { if k == "_tidb_op" { require.Equal(t, "c", v.(string)) } @@ -258,7 +254,7 @@ func TestAvroEnvelope(t *testing.T) { require.NoError(t, err) - testNativeData := make(map[string]interface{}) + testNativeData := make(map[string]any) testNativeData["id"] = 7 bin, err := avroCodec.BinaryFromNative(nil, testNativeData) @@ -280,7 +276,7 @@ func TestAvroEnvelope(t *testing.T) { require.NoError(t, err) require.NotNil(t, parsed) - id, exists := parsed.(map[string]interface{})["id"] + id, exists := parsed.(map[string]any)["id"] require.True(t, exists) require.Equal(t, int32(7), id) @@ -300,7 +296,7 @@ func TestAvroEnvelope(t *testing.T) { parsed, _, err = avroCodec.NativeFromBinary(evlp[18:]) require.NoError(t, err) require.NotNil(t, parsed) - id, exists = parsed.(map[string]interface{})["id"] + id, exists = parsed.(map[string]any)["id"] require.True(t, exists) require.Equal(t, int32(7), id) } @@ -348,8 +344,7 @@ func TestArvoAppendRowChangedEventWithCallback(t *testing.T) { codecConfig := common.NewConfig(config.ProtocolAvro) codecConfig.EnableTiDBExtension = true - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() encoder, err := SetupEncoderAndSchemaRegistry4Testing(ctx, codecConfig) defer TeardownEncoderAndSchemaRegistry4Testing() require.NoError(t, err) @@ -376,7 +371,7 @@ func TestArvoAppendRowChangedEventWithCallback(t *testing.T) { expected := 0 count := 0 - for i := 0; i < 5; i++ { + for i := range 5 { expected += i bit := i err := encoder.AppendRowChangedEvent(ctx, "", row, func() { diff --git a/pkg/sink/codec/avro/confluent_schema_registry_test.go b/pkg/sink/codec/avro/confluent_schema_registry_test.go index 596323f791..4b358aa9f5 100644 --- a/pkg/sink/codec/avro/confluent_schema_registry_test.go +++ b/pkg/sink/codec/avro/confluent_schema_registry_test.go @@ -125,7 +125,7 @@ func TestSchemaRegistryIdempotent(t *testing.T) { topic := "cdctest" - for i := 0; i < 20; i++ { + for range 20 { err = manager.ClearRegistry(ctx, topic) require.NoError(t, err) } @@ -152,7 +152,7 @@ func TestSchemaRegistryIdempotent(t *testing.T) { require.NoError(t, err) id := 0 - for i := 0; i < 20; i++ { + for range 20 { id1, err := manager.Register(ctx, topic, codec.Schema()) require.NoError(t, err) require.True(t, id == 0 || id == id1.confluentSchemaID) @@ -236,12 +236,10 @@ func TestGetCachedOrRegister(t *testing.T) { } var wg sync.WaitGroup - for i := 0; i < 20; i++ { + for i := range 20 { finalI := i - wg.Add(1) - go func() { - defer wg.Done() - for j := 0; j < 100; j++ { + wg.Go(func() { + for range 100 { codec, header, err := manager.GetCachedOrRegister( ctx, topic, @@ -254,7 +252,7 @@ func TestGetCachedOrRegister(t *testing.T) { require.Greater(t, cID, uint32(0)) require.NotNil(t, codec) } - }() + }) } wg.Wait() } diff --git a/pkg/sink/codec/avro/decoder.go b/pkg/sink/codec/avro/decoder.go index a8474e238f..ea8e2b2c37 100644 --- a/pkg/sink/codec/avro/decoder.go +++ b/pkg/sink/codec/avro/decoder.go @@ -97,8 +97,8 @@ func (d *decoder) HasNext() (model.MessageType, bool, error) { // NextRowChangedEvent returns the next row changed event if exists func (d *decoder) NextRowChangedEvent() (*model.RowChangedEvent, error) { var ( - valueMap map[string]interface{} - valueSchema map[string]interface{} + valueMap map[string]any + valueSchema map[string]any err error ) @@ -175,9 +175,9 @@ func (d *decoder) NextRowChangedEvent() (*model.RowChangedEvent, error) { // valueMap hold all columns information // schema is corresponding to the valueMap, it can be used to decode the valueMap to construct columns. func assembleEvent( - keyMap, valueMap, schema map[string]interface{}, isDelete bool, + keyMap, valueMap, schema map[string]any, isDelete bool, ) (*model.RowChangedEvent, error) { - fields, ok := schema["fields"].([]interface{}) + fields, ok := schema["fields"].([]any) if !ok { return nil, errors.New("schema fields should be a map") } @@ -186,7 +186,7 @@ func assembleEvent( // fields is ordered by the column id, so iterate over it to build columns // it's also the order to calculate the checksum. for _, item := range fields { - field, ok := item.(map[string]interface{}) + field, ok := item.(map[string]any) if !ok { return nil, errors.New("schema field should be a map") } @@ -199,18 +199,18 @@ func assembleEvent( } // query the field to get `tidbType`, and get the mysql type from it. - var holder map[string]interface{} + var holder map[string]any switch ty := field["type"].(type) { - case []interface{}: - if m, ok := ty[0].(map[string]interface{}); ok { - holder = m["connect.parameters"].(map[string]interface{}) - } else if m, ok := ty[1].(map[string]interface{}); ok { - holder = m["connect.parameters"].(map[string]interface{}) + case []any: + if m, ok := ty[0].(map[string]any); ok { + holder = m["connect.parameters"].(map[string]any) + } else if m, ok := ty[1].(map[string]any); ok { + holder = m["connect.parameters"].(map[string]any) } else { log.Panic("type info is anything else", zap.Any("typeInfo", field["type"])) } - case map[string]interface{}: - holder = ty["connect.parameters"].(map[string]interface{}) + case map[string]any: + holder = ty["connect.parameters"].(map[string]any) default: log.Panic("type info is anything else", zap.Any("typeInfo", field["type"])) } @@ -273,7 +273,7 @@ func assembleEvent( return event, nil } -func isCorrupted(valueMap map[string]interface{}) bool { +func isCorrupted(valueMap map[string]any) bool { o, ok := valueMap[tidbCorrupted] if !ok { return false @@ -285,7 +285,7 @@ func isCorrupted(valueMap map[string]interface{}) bool { // extract the checksum from the received value map // return true if the checksum found, and return error if the checksum is not valid -func extractExpectedChecksum(valueMap map[string]interface{}) (uint64, bool, error) { +func extractExpectedChecksum(valueMap map[string]any) (uint64, bool, error) { o, ok := valueMap[tidbRowLevelChecksum] if !ok { return 0, false, nil @@ -304,12 +304,12 @@ func extractExpectedChecksum(valueMap map[string]interface{}) (uint64, bool, err // value is an interface, need to convert it to the real value with the help of type info. // holder has the value's column info. func getColumnValue( - value interface{}, holder map[string]interface{}, mysqlType byte, -) (interface{}, error) { + value any, holder map[string]any, mysqlType byte, +) (any, error) { switch t := value.(type) { // for nullable columns, the value is encoded as a map with one pair. // key is the encoded type, value is the encoded value, only care about the value here. - case map[string]interface{}: + case map[string]any: for _, v := range t { value = v } @@ -422,7 +422,7 @@ func extractGlueSchemaIDAndBinaryData(data []byte) (string, []byte, error) { func decodeRawBytes( ctx context.Context, schemaM SchemaManager, data []byte, topic string, -) (map[string]interface{}, map[string]interface{}, error) { +) (map[string]any, map[string]any, error) { var schemaID schemaID var binary []byte var err error @@ -456,12 +456,12 @@ func decodeRawBytes( return nil, nil, err } - result, ok := native.(map[string]interface{}) + result, ok := native.(map[string]any) if !ok { return nil, nil, errors.New("raw avro message is not a map") } - schema := make(map[string]interface{}) + schema := make(map[string]any) if err := json.Unmarshal([]byte(codec.Schema()), &schema); err != nil { return nil, nil, errors.Trace(err) } @@ -469,13 +469,13 @@ func decodeRawBytes( return result, schema, nil } -func (d *decoder) decodeKey(ctx context.Context) (map[string]interface{}, map[string]interface{}, error) { +func (d *decoder) decodeKey(ctx context.Context) (map[string]any, map[string]any, error) { data := d.key d.key = nil return decodeRawBytes(ctx, d.schemaM, data, d.topic) } -func (d *decoder) decodeValue(ctx context.Context) (map[string]interface{}, map[string]interface{}, error) { +func (d *decoder) decodeValue(ctx context.Context) (map[string]any, map[string]any, error) { data := d.value d.value = nil return decodeRawBytes(ctx, d.schemaM, data, d.topic) diff --git a/pkg/sink/codec/bootstraper.go b/pkg/sink/codec/bootstraper.go index 32f52e3944..ffe49f6608 100644 --- a/pkg/sink/codec/bootstraper.go +++ b/pkg/sink/codec/bootstraper.go @@ -88,7 +88,7 @@ func (b *bootstrapWorker) run(ctx context.Context) error { case <-ctx.Done(): return ctx.Err() case <-sendTicker.C: - b.activeTables.Range(func(key, value interface{}) bool { + b.activeTables.Range(func(key, value any) bool { table := value.(*tableStatistic) err = b.sendBootstrapMsg(ctx, table) return err == nil @@ -180,7 +180,7 @@ func (b *bootstrapWorker) generateEvents( } func (b *bootstrapWorker) gcInactiveTables() { - b.activeTables.Range(func(key, value interface{}) bool { + b.activeTables.Range(func(key, value any) bool { table := value.(*tableStatistic) if table.isInactive(b.maxInactiveDuration) { log.Info("A table is removed from the bootstrap worker", diff --git a/pkg/sink/codec/bootstraper_test.go b/pkg/sink/codec/bootstraper_test.go index ae11bdc1e1..8555fa13e8 100644 --- a/pkg/sink/codec/bootstraper_test.go +++ b/pkg/sink/codec/bootstraper_test.go @@ -114,8 +114,7 @@ func TestBootstrapWorker(t *testing.T) { defaultMaxInactiveDuration) // Start the worker in a separate goroutine - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() go func() { _ = worker.run(ctx) }() diff --git a/pkg/sink/codec/canal/canal_entry.go b/pkg/sink/codec/canal/canal_entry.go index 8925ed8812..1252bcaed3 100644 --- a/pkg/sink/codec/canal/canal_entry.go +++ b/pkg/sink/codec/canal/canal_entry.go @@ -81,7 +81,7 @@ func (b *canalEntryBuilder) buildHeader(commitTs uint64, schema string, table st // see https://github.com/alibaba/canal/blob/b54bea5e3337c9597c427a53071d214ff04628d1/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogBuffer.java#L276-L1147 // all value will be represented in string type // see https://github.com/alibaba/canal/blob/b54bea5e3337c9597c427a53071d214ff04628d1/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/LogEventConvert.java#L760-L855 -func (b *canalEntryBuilder) formatValue(value interface{}, isBinary bool) (result string, err error) { +func (b *canalEntryBuilder) formatValue(value any, isBinary bool) (result string, err error) { // value would be nil, if no value insert for the column. if value == nil { return "", nil @@ -301,7 +301,7 @@ func isCanalDDL(t canal.EventType) bool { return false } -func getJavaSQLType(value interface{}, tp byte, flag model.ColumnFlagType) (result internal.JavaSQLType, err error) { +func getJavaSQLType(value any, tp byte, flag model.ColumnFlagType) (result internal.JavaSQLType, err error) { javaType := internal.MySQLType2JavaType(tp, flag.IsBinary()) // flag `isUnsigned` only for `numerical` and `bit`, `year` data type. if !flag.IsUnsigned() { diff --git a/pkg/sink/codec/canal/canal_json_decoder.go b/pkg/sink/codec/canal/canal_json_decoder.go index 5e3114c054..30a1a37242 100644 --- a/pkg/sink/codec/canal/canal_json_decoder.go +++ b/pkg/sink/codec/canal/canal_json_decoder.go @@ -69,7 +69,7 @@ func (b *bufferedJSONDecoder) Write(data []byte) (n int, err error) { } // Decode decodes the buffer into the original message. -func (b *bufferedJSONDecoder) Decode(v interface{}) error { +func (b *bufferedJSONDecoder) Decode(v any) error { return b.decoder.Decode(v) } @@ -202,12 +202,12 @@ func (b *batchDecoder) assembleClaimCheckRowChangedEvent(ctx context.Context, cl return b.NextRowChangedEvent() } -func (b *batchDecoder) buildData(holder *common.ColumnsHolder) (map[string]interface{}, map[string]string, error) { +func (b *batchDecoder) buildData(holder *common.ColumnsHolder) (map[string]any, map[string]string, error) { columnsCount := holder.Length() - data := make(map[string]interface{}, columnsCount) + data := make(map[string]any, columnsCount) mysqlTypeMap := make(map[string]string, columnsCount) - for i := 0; i < columnsCount; i++ { + for i := range columnsCount { t := holder.Types[i] name := holder.Types[i].Name() mysqlType := strings.ToLower(t.DatabaseTypeName()) @@ -242,7 +242,7 @@ func (b *batchDecoder) assembleHandleKeyOnlyRowChangedEvent( table = message.Table eventType = message.EventType ) - conditions := make(map[string]interface{}, len(message.pkNameSet())) + conditions := make(map[string]any, len(message.pkNameSet())) for name := range message.pkNameSet() { conditions[name] = message.getData()[name] } @@ -266,7 +266,7 @@ func (b *batchDecoder) assembleHandleKeyOnlyRowChangedEvent( return nil, err } result.MySQLType = mysqlType - result.Data = []map[string]interface{}{data} + result.Data = []map[string]any{data} case "UPDATE": holder := common.MustSnapshotQuery(ctx, b.upstreamTiDB, commitTs, schema, table, conditions) data, mysqlType, err := b.buildData(holder) @@ -274,14 +274,14 @@ func (b *batchDecoder) assembleHandleKeyOnlyRowChangedEvent( return nil, err } result.MySQLType = mysqlType - result.Data = []map[string]interface{}{data} + result.Data = []map[string]any{data} holder = common.MustSnapshotQuery(ctx, b.upstreamTiDB, commitTs-1, schema, table, conditions) old, _, err := b.buildData(holder) if err != nil { return nil, err } - result.Old = []map[string]interface{}{old} + result.Old = []map[string]any{old} case "DELETE": holder := common.MustSnapshotQuery(ctx, b.upstreamTiDB, commitTs-1, schema, table, conditions) data, mysqlType, err := b.buildData(holder) @@ -289,7 +289,7 @@ func (b *batchDecoder) assembleHandleKeyOnlyRowChangedEvent( return nil, err } result.MySQLType = mysqlType - result.Data = []map[string]interface{}{data} + result.Data = []map[string]any{data} } b.msg = result @@ -298,7 +298,7 @@ func (b *batchDecoder) assembleHandleKeyOnlyRowChangedEvent( func setColumnInfos( tableInfo *timodel.TableInfo, - rawColumns map[string]interface{}, + rawColumns map[string]any, mysqlType map[string]string, pkNames map[string]struct{}, ) { diff --git a/pkg/sink/codec/canal/canal_json_message.go b/pkg/sink/codec/canal/canal_json_message.go index e4610f061c..7024e1335c 100644 --- a/pkg/sink/codec/canal/canal_json_message.go +++ b/pkg/sink/codec/canal/canal_json_message.go @@ -41,8 +41,8 @@ type canalJSONMessageInterface interface { getPhysicalTableID() int64 getTableID() int64 getQuery() string - getOld() map[string]interface{} - getData() map[string]interface{} + getOld() map[string]any + getData() map[string]any getMySQLType() map[string]string getJavaSQLType() map[string]int32 messageType() model.MessageType @@ -70,8 +70,8 @@ type JSONMessage struct { // only works for INSERT / UPDATE / DELETE events, records each column's mysql representation type. MySQLType map[string]string `json:"mysqlType"` // A Datum should be a string or nil - Data []map[string]interface{} `json:"data"` - Old []map[string]interface{} `json:"old"` + Data []map[string]any `json:"data"` + Old []map[string]any `json:"old"` } func (c *JSONMessage) getSchema() *string { @@ -99,14 +99,14 @@ func (c *JSONMessage) getQuery() string { return c.Query } -func (c *JSONMessage) getOld() map[string]interface{} { +func (c *JSONMessage) getOld() map[string]any { if c.Old == nil { return nil } return c.Old[0] } -func (c *JSONMessage) getData() map[string]interface{} { +func (c *JSONMessage) getData() map[string]any { if c.Data == nil { return nil } @@ -328,7 +328,7 @@ func (b *batchDecoder) canalJSONMessage2RowChange() (*model.RowChangedEvent, err } func canalJSONColumnMap2RowChangeColumns( - cols map[string]interface{}, + cols map[string]any, mysqlType map[string]string, tableInfo *model.TableInfo, ) ([]*model.ColumnData, error) { @@ -352,7 +352,7 @@ func canalJSONColumnMap2RowChangeColumns( return result, nil } -func canalJSONFormatColumn(columnID int64, value interface{}, mysqlTypeStr string) *model.ColumnData { +func canalJSONFormatColumn(columnID int64, value any, mysqlTypeStr string) *model.ColumnData { mysqlType := utils.ExtractBasicMySQLType(mysqlTypeStr) result := &model.ColumnData{ ColumnID: columnID, diff --git a/pkg/sink/codec/common/helper.go b/pkg/sink/codec/common/helper.go index b42599a7c4..f2737ecf66 100644 --- a/pkg/sink/codec/common/helper.go +++ b/pkg/sink/codec/common/helper.go @@ -31,8 +31,8 @@ import ( // ColumnsHolder read columns from sql.Rows type ColumnsHolder struct { - Values []interface{} - ValuePointers []interface{} + Values []any + ValuePointers []any Types []*sql.ColumnType } @@ -42,8 +42,8 @@ func newColumnHolder(rows *sql.Rows) (*ColumnsHolder, error) { return nil, errors.Trace(err) } - values := make([]interface{}, len(columnTypes)) - valuePointers := make([]interface{}, len(columnTypes)) + values := make([]any, len(columnTypes)) + valuePointers := make([]any, len(columnTypes)) for i := range values { valuePointers[i] = &values[i] } @@ -105,7 +105,7 @@ func queryRowChecksum( defer conn.Close() if event.Checksum.Current != 0 { - conditions := make(map[string]interface{}) + conditions := make(map[string]any) for _, name := range pkNames { for _, col := range event.Columns { if event.TableInfo.ForceGetColumnName(col.ColumnID) == name { @@ -123,7 +123,7 @@ func queryRowChecksum( } if event.Checksum.Previous != 0 { - conditions := make(map[string]interface{}) + conditions := make(map[string]any) for _, name := range pkNames { for _, col := range event.PreColumns { if event.TableInfo.ForceGetColumnName(col.ColumnID) == name { @@ -144,7 +144,7 @@ func queryRowChecksum( } func queryRowChecksumAux( - ctx context.Context, conn *sql.Conn, commitTs uint64, schema string, table string, conditions map[string]interface{}, + ctx context.Context, conn *sql.Conn, commitTs uint64, schema string, table string, conditions map[string]any, ) uint32 { var result uint32 // 1. set snapshot read @@ -193,7 +193,7 @@ func queryRowChecksumAux( // MustSnapshotQuery query the db by the snapshot read with the given commitTs func MustSnapshotQuery( - ctx context.Context, db *sql.DB, commitTs uint64, schema, table string, conditions map[string]interface{}, + ctx context.Context, db *sql.DB, commitTs uint64, schema, table string, conditions map[string]any, ) *ColumnsHolder { conn, err := db.Conn(ctx) if err != nil { diff --git a/pkg/sink/codec/common/verify_checksum.go b/pkg/sink/codec/common/verify_checksum.go index 589ae8680d..723b9edd5f 100644 --- a/pkg/sink/codec/common/verify_checksum.go +++ b/pkg/sink/codec/common/verify_checksum.go @@ -104,7 +104,7 @@ func calculateChecksum(columns []*model.ColumnData, columnInfo []*timodel.Column // buildChecksumBytes append value to the buf, mysqlType is used to convert value interface to concrete type. // by follow: https://github.com/pingcap/tidb/blob/e3417913f58cdd5a136259b902bf177eaf3aa637/util/rowcodec/common.go#L308 -func buildChecksumBytes(buf []byte, value interface{}, mysqlType byte) ([]byte, error) { +func buildChecksumBytes(buf []byte, value any, mysqlType byte) ([]byte, error) { if value == nil { return buf, nil } @@ -133,7 +133,7 @@ func buildChecksumBytes(buf []byte, value interface{}, mysqlType byte) ([]byte, if err != nil { return nil, errors.Trace(err) } - case map[string]interface{}: + case map[string]any: // this may only happen for bigint larger than math.uint64 v = uint64(a["value"].(int64)) default: @@ -191,7 +191,7 @@ func buildChecksumBytes(buf []byte, value interface{}, mysqlType byte) ([]byte, location := "Local" var ts string switch data := value.(type) { - case map[string]interface{}: + case map[string]any: ts = data["value"].(string) location = data["location"].(string) case string: diff --git a/pkg/sink/codec/craft/craft_encoder_test.go b/pkg/sink/codec/craft/craft_encoder_test.go index c676429b48..c4cff962a1 100644 --- a/pkg/sink/codec/craft/craft_encoder_test.go +++ b/pkg/sink/codec/craft/craft_encoder_test.go @@ -35,7 +35,7 @@ func TestCraftMaxMessageBytes(t *testing.T) { _ = helper.DDL2Event(`create table test.t(a varchar(10) primary key)`) testEvent := helper.DML2Event(`insert into test.t values ("aa")`, "test", "t") - for i := 0; i < 10000; i++ { + for range 10000 { err := encoder.AppendRowChangedEvent(context.Background(), "", testEvent, nil) require.Nil(t, err) } @@ -57,7 +57,7 @@ func TestCraftMaxBatchSize(t *testing.T) { _ = helper.DDL2Event(`create table test.t(a varchar(10) primary key)`) testEvent := helper.DML2Event(`insert into test.t values ("aa")`, "test", "t") - for i := 0; i < 10000; i++ { + for range 10000 { err := encoder.AppendRowChangedEvent(context.Background(), "", testEvent, nil) require.Nil(t, err) } diff --git a/pkg/sink/codec/craft/message_decoder.go b/pkg/sink/codec/craft/message_decoder.go index c104277e82..e90506b536 100644 --- a/pkg/sink/codec/craft/message_decoder.go +++ b/pkg/sink/codec/craft/message_decoder.go @@ -146,7 +146,7 @@ func decodeStringChunk(bits []byte, size int, allocator *SliceAllocator) ([]byte newBits := bits var bl int var err error - for i := 0; i < size; i++ { + for i := range size { newBits, bl, err = decodeUvarintLength(newBits) if err != nil { return bits, nil, errors.Trace(err) @@ -155,7 +155,7 @@ func decodeStringChunk(bits []byte, size int, allocator *SliceAllocator) ([]byte } data := allocator.stringSlice(size) - for i := 0; i < size; i++ { + for i := range size { data[i] = common.UnsafeBytesToString(newBits[:larray[i]]) newBits = newBits[larray[i]:] } @@ -167,7 +167,7 @@ func decodeNullableStringChunk(bits []byte, size int, allocator *SliceAllocator) newBits := bits var bl int var err error - for i := 0; i < size; i++ { + for i := range size { newBits, bl, err = decodeVarintLength(newBits) if err != nil { return bits, nil, errors.Trace(err) @@ -176,7 +176,7 @@ func decodeNullableStringChunk(bits []byte, size int, allocator *SliceAllocator) } data := allocator.nullableStringSlice(size) - for i := 0; i < size; i++ { + for i := range size { if larray[i] == -1 { continue } @@ -197,7 +197,7 @@ func doDecodeBytesChunk(bits []byte, size int, lengthDecoder func([]byte) ([]byt newBits := bits var bl int var err error - for i := 0; i < size; i++ { + for i := range size { newBits, bl, err = lengthDecoder(newBits) if err != nil { return bits, nil, errors.Trace(err) @@ -206,7 +206,7 @@ func doDecodeBytesChunk(bits []byte, size int, lengthDecoder func([]byte) ([]byt } data := allocator.bytesSlice(size) - for i := 0; i < size; i++ { + for i := range size { if larray[i] != -1 { data[i] = newBits[:larray[i]] newBits = newBits[larray[i]:] @@ -224,7 +224,7 @@ func decodeVarintChunk(bits []byte, size int, allocator *SliceAllocator) ([]byte newBits := bits var i64 int64 var err error - for i := 0; i < size; i++ { + for i := range size { newBits, i64, err = decodeVarint(newBits) if err != nil { return bits, nil, errors.Trace(err) @@ -239,7 +239,7 @@ func decodeUvarintChunk(bits []byte, size int, allocator *SliceAllocator) ([]byt newBits := bits var u64 uint64 var err error - for i := 0; i < size; i++ { + for i := range size { newBits, u64, err = decodeUvarint(newBits) if err != nil { return bits, nil, errors.Trace(err) @@ -312,7 +312,7 @@ func decodeSizeTables(bits []byte, allocator *SliceAllocator) (int, [][]int64, e } // DecodeTiDBType decodes TiDB types. -func DecodeTiDBType(ty byte, flag model.ColumnFlagType, bits []byte) (interface{}, error) { +func DecodeTiDBType(ty byte, flag model.ColumnFlagType, bits []byte) (any, error) { if bits == nil { return nil, nil } diff --git a/pkg/sink/codec/craft/message_encoder.go b/pkg/sink/codec/craft/message_encoder.go index f09c9e6016..11138f842f 100644 --- a/pkg/sink/codec/craft/message_encoder.go +++ b/pkg/sink/codec/craft/message_encoder.go @@ -176,7 +176,7 @@ func encodeSizeTables(bits []byte, tables [][]int64) []byte { } // EncodeTiDBType encodes TiDB types -func EncodeTiDBType(allocator *SliceAllocator, ty byte, flag model.ColumnFlagType, value interface{}) []byte { +func EncodeTiDBType(allocator *SliceAllocator, ty byte, flag model.ColumnFlagType, value any) []byte { if value == nil { return nil } diff --git a/pkg/sink/codec/csv/csv_decoder_test.go b/pkg/sink/codec/csv/csv_decoder_test.go index 81e77ae5e6..d9b6d6bc70 100644 --- a/pkg/sink/codec/csv/csv_decoder_test.go +++ b/pkg/sink/codec/csv/csv_decoder_test.go @@ -46,7 +46,7 @@ func TestCSVBatchDecoder(t *testing.T) { decoder, err := NewBatchDecoder(ctx, codecConfig, createTableDDL.TableInfo, []byte(csvData)) require.NoError(t, err) - for i := 0; i < 5; i++ { + for range 5 { tp, hasNext, err := decoder.HasNext() require.Nil(t, err) require.True(t, hasNext) diff --git a/pkg/sink/codec/csv/csv_message_test.go b/pkg/sink/codec/csv/csv_message_test.go index 4718cd6e39..4fd592f92d 100644 --- a/pkg/sink/codec/csv/csv_message_test.go +++ b/pkg/sink/codec/csv/csv_message_test.go @@ -32,7 +32,7 @@ import ( type csvTestColumnTuple struct { col model.Column colInfo rowcodec.ColInfo - want interface{} + want any BinaryEncodingMethod string } diff --git a/pkg/sink/codec/debezium/codec.go b/pkg/sink/codec/debezium/codec.go index deaf4eed65..bc139b2d3a 100644 --- a/pkg/sink/codec/debezium/codec.go +++ b/pkg/sink/codec/debezium/codec.go @@ -42,7 +42,7 @@ type dbzCodec struct { // truncateValueForLog truncates large values to avoid log flooding. // Returns the original value if it's small enough, otherwise returns a truncated string representation. -func truncateValueForLog(value interface{}, maxLen int) interface{} { +func truncateValueForLog(value any, maxLen int) any { switch v := value.(type) { case []byte: if len(v) > maxLen { diff --git a/pkg/sink/codec/debezium/debezium_test.go b/pkg/sink/codec/debezium/debezium_test.go index aa39bfe211..a5fbee750d 100644 --- a/pkg/sink/codec/debezium/debezium_test.go +++ b/pkg/sink/codec/debezium/debezium_test.go @@ -87,7 +87,7 @@ func (h *SQLTestHelper) Close() { h.helper.Close() } -func (h *SQLTestHelper) MustExec(query string, args ...interface{}) { +func (h *SQLTestHelper) MustExec(query string, args ...any) { h.helper.Tk().MustExec(query, args...) } diff --git a/pkg/sink/codec/debezium/decoder.go b/pkg/sink/codec/debezium/decoder.go index 462a12cf3a..d5152aff82 100644 --- a/pkg/sink/codec/debezium/decoder.go +++ b/pkg/sink/codec/debezium/decoder.go @@ -45,10 +45,10 @@ type Decoder struct { upstreamTiDB *sql.DB tableIDAllocator *common.FakeTableIDAllocator - keyPayload map[string]interface{} - keySchema map[string]interface{} - valuePayload map[string]interface{} - valueSchema map[string]interface{} + keyPayload map[string]any + keySchema map[string]any + valuePayload map[string]any + valueSchema map[string]any } // NewDecoder return an debezium decoder @@ -153,10 +153,10 @@ func (d *Decoder) NextRowChangedEvent() (*model.RowChangedEvent, error) { CommitTs: commitTs, TableInfo: tableInfo, } - if before, ok := d.valuePayload["before"].(map[string]interface{}); ok { + if before, ok := d.valuePayload["before"].(map[string]any); ok { event.PreColumns = assembleColumnData(before, tableInfo) } - if after, ok := d.valuePayload["after"].(map[string]interface{}); ok { + if after, ok := d.valuePayload["after"].(map[string]any); ok { event.Columns = assembleColumnData(after, tableInfo) } event.PhysicalTableID = d.tableIDAllocator.AllocateTableID(tableInfo.GetSchemaName(), tableInfo.GetTableName()) @@ -164,7 +164,7 @@ func (d *Decoder) NextRowChangedEvent() (*model.RowChangedEvent, error) { } func (d *Decoder) getCommitTs() uint64 { - source := d.valuePayload["source"].(map[string]interface{}) + source := d.valuePayload["source"].(map[string]any) commitTs, err := source["commit_ts"].(json.Number).Int64() if err != nil { log.Error("decode value failed", zap.Error(err), zap.Any("value", source)) @@ -173,13 +173,13 @@ func (d *Decoder) getCommitTs() uint64 { } func (d *Decoder) getSchemaName() string { - source := d.valuePayload["source"].(map[string]interface{}) + source := d.valuePayload["source"].(map[string]any) schemaName := source["db"].(string) return schemaName } func (d *Decoder) getTableName() string { - source := d.valuePayload["source"].(map[string]interface{}) + source := d.valuePayload["source"].(map[string]any) tableName := source["table"].(string) return tableName } @@ -195,12 +195,12 @@ func (d *Decoder) getTableInfo() *model.TableInfo { tidbTableInfo := new(timodel.TableInfo) tidbTableInfo.Name = pmodel.NewCIStr(d.getTableName()) columnIDAllocator := model.NewIncrementalColumnIDAllocator() - fields := d.valueSchema["fields"].([]interface{}) - after := fields[1].(map[string]interface{}) - columnsField := after["fields"].([]interface{}) + fields := d.valueSchema["fields"].([]any) + after := fields[1].(map[string]any) + columnsField := after["fields"].([]any) indexColumns := make([]*timodel.IndexColumn, 0, len(d.keyPayload)) for idx, column := range columnsField { - col := column.(map[string]interface{}) + col := column.(map[string]any) colName := col["field"].(string) tidbType := col["tidb_type"].(string) optional := col["optional"].(bool) @@ -235,7 +235,7 @@ func (d *Decoder) getTableInfo() *model.TableInfo { return model.WrapTableInfo(100, d.getSchemaName(), 100, tidbTableInfo) } -func assembleColumnData(data map[string]interface{}, tableInfo *model.TableInfo) []*model.ColumnData { +func assembleColumnData(data map[string]any, tableInfo *model.TableInfo) []*model.ColumnData { result := make([]*model.ColumnData, 0, len(data)) for key, value := range data { columnID := tableInfo.ForceGetColumnIDByName(key) @@ -248,7 +248,7 @@ func assembleColumnData(data map[string]interface{}, tableInfo *model.TableInfo) return result } -func decodeColumn(value interface{}, colInfo *timodel.ColumnInfo) *model.ColumnData { +func decodeColumn(value any, colInfo *timodel.ColumnInfo) *model.ColumnData { result := &model.ColumnData{ ColumnID: colInfo.ID, Value: value, @@ -357,18 +357,18 @@ func parseTiDBType(tidbType string, optional bool) *ptypes.FieldType { return ft } -func decodeRawBytes(data []byte) (map[string]interface{}, map[string]interface{}, error) { - var v map[string]interface{} +func decodeRawBytes(data []byte) (map[string]any, map[string]any, error) { + var v map[string]any d := json.NewDecoder(bytes.NewBuffer(data)) d.UseNumber() if err := d.Decode(&v); err != nil { return nil, nil, errors.Trace(err) } - payload, ok := v["payload"].(map[string]interface{}) + payload, ok := v["payload"].(map[string]any) if !ok { return nil, nil, fmt.Errorf("decode payload failed, data: %+v", v) } - schema, ok := v["schema"].(map[string]interface{}) + schema, ok := v["schema"].(map[string]any) if !ok { return nil, nil, fmt.Errorf("decode payload failed, data: %+v", v) } diff --git a/pkg/sink/codec/encoder.go b/pkg/sink/codec/encoder.go index e3b232c9f0..421f281238 100644 --- a/pkg/sink/codec/encoder.go +++ b/pkg/sink/codec/encoder.go @@ -73,7 +73,7 @@ type TxnEventEncoderBuilder interface { } // IsColumnValueEqual checks whether the preValue and updatedValue are equal. -func IsColumnValueEqual(preValue, updatedValue interface{}) bool { +func IsColumnValueEqual(preValue, updatedValue any) bool { if preValue == nil || updatedValue == nil { return preValue == updatedValue } diff --git a/pkg/sink/codec/maxwell/maxwell_message.go b/pkg/sink/codec/maxwell/maxwell_message.go index f673ad5b4f..8d13d1ba96 100644 --- a/pkg/sink/codec/maxwell/maxwell_message.go +++ b/pkg/sink/codec/maxwell/maxwell_message.go @@ -26,16 +26,16 @@ import ( ) type maxwellMessage struct { - Database string `json:"database"` - Table string `json:"table"` - Type string `json:"type"` - Ts int64 `json:"ts"` - Xid int `json:"xid,omitempty"` - Xoffset int `json:"xoffset,omitempty"` - Position string `json:"position,omitempty"` - Gtid string `json:"gtid,omitempty"` - Data map[string]interface{} `json:"data,omitempty"` - Old map[string]interface{} `json:"old,omitempty"` + Database string `json:"database"` + Table string `json:"table"` + Type string `json:"type"` + Ts int64 `json:"ts"` + Xid int `json:"xid,omitempty"` + Xoffset int `json:"xoffset,omitempty"` + Position string `json:"position,omitempty"` + Gtid string `json:"gtid,omitempty"` + Data map[string]any `json:"data,omitempty"` + Old map[string]any `json:"old,omitempty"` } // Encode encodes the message to bytes @@ -61,8 +61,8 @@ func rowChangeToMaxwellMsg(e *model.RowChangedEvent, onlyHandleKeyColumns bool) Ts: 0, Database: e.TableInfo.GetSchemaName(), Table: e.TableInfo.GetTableName(), - Data: make(map[string]interface{}), - Old: make(map[string]interface{}), + Data: make(map[string]any), + Old: make(map[string]any), } physicalTime := oracle.GetTimeFromTS(e.CommitTs) value.Ts = physicalTime.Unix() @@ -178,8 +178,8 @@ type ddlMaxwellMessage struct { Type string `json:"type"` Database string `json:"database"` Table string `json:"table"` - Old tableStruct `json:"old,omitempty"` - Def tableStruct `json:"def,omitempty"` + Old tableStruct `json:"old"` + Def tableStruct `json:"def"` Ts uint64 `json:"ts"` SQL string `json:"sql"` Position string `json:"position,omitempty"` diff --git a/pkg/sink/codec/maxwell/maxwell_message_test.go b/pkg/sink/codec/maxwell/maxwell_message_test.go index f2631c36f0..3cdb784077 100644 --- a/pkg/sink/codec/maxwell/maxwell_message_test.go +++ b/pkg/sink/codec/maxwell/maxwell_message_test.go @@ -31,7 +31,7 @@ func TestMaxwellFormatCol(t *testing.T) { Xoffset: 1, Position: "", Gtid: "", - Data: map[string]interface{}{ + Data: map[string]any{ "id": "1", }, } diff --git a/pkg/sink/codec/open/open_protocol_decoder.go b/pkg/sink/codec/open/open_protocol_decoder.go index db449f29ad..9ec3ddd739 100644 --- a/pkg/sink/codec/open/open_protocol_decoder.go +++ b/pkg/sink/codec/open/open_protocol_decoder.go @@ -218,16 +218,16 @@ func (b *BatchDecoder) NextRowChangedEvent() (*model.RowChangedEvent, error) { } func (b *BatchDecoder) buildColumns( - holder *common.ColumnsHolder, handleKeyColumns map[string]interface{}, + holder *common.ColumnsHolder, handleKeyColumns map[string]any, ) []*model.Column { columnsCount := holder.Length() columns := make([]*model.Column, 0, columnsCount) - for i := 0; i < columnsCount; i++ { + for i := range columnsCount { columnType := holder.Types[i] name := columnType.Name() mysqlType := types.StrToType(strings.ToLower(columnType.DatabaseTypeName())) - var value interface{} + var value any value = holder.Values[i].([]uint8) switch mysqlType { @@ -262,7 +262,7 @@ func (b *BatchDecoder) assembleHandleKeyOnlyEvent( tableInfo := handleKeyOnlyEvent.TableInfo if handleKeyOnlyEvent.IsInsert() { - conditions := make(map[string]interface{}, len(handleKeyOnlyEvent.Columns)) + conditions := make(map[string]any, len(handleKeyOnlyEvent.Columns)) for _, col := range handleKeyOnlyEvent.Columns { colName := tableInfo.ForceGetColumnName(col.ColumnID) conditions[colName] = col.Value @@ -273,7 +273,7 @@ func (b *BatchDecoder) assembleHandleKeyOnlyEvent( handleKeyOnlyEvent.TableInfo = model.BuildTableInfo(schema, table, columns, indexColumns) handleKeyOnlyEvent.Columns = model.Columns2ColumnDatas(columns, handleKeyOnlyEvent.TableInfo) } else if handleKeyOnlyEvent.IsDelete() { - conditions := make(map[string]interface{}, len(handleKeyOnlyEvent.PreColumns)) + conditions := make(map[string]any, len(handleKeyOnlyEvent.PreColumns)) for _, col := range handleKeyOnlyEvent.PreColumns { colName := tableInfo.ForceGetColumnName(col.ColumnID) conditions[colName] = col.Value @@ -284,7 +284,7 @@ func (b *BatchDecoder) assembleHandleKeyOnlyEvent( handleKeyOnlyEvent.TableInfo = model.BuildTableInfo(schema, table, preColumns, indexColumns) handleKeyOnlyEvent.PreColumns = model.Columns2ColumnDatas(preColumns, handleKeyOnlyEvent.TableInfo) } else if handleKeyOnlyEvent.IsUpdate() { - conditions := make(map[string]interface{}, len(handleKeyOnlyEvent.Columns)) + conditions := make(map[string]any, len(handleKeyOnlyEvent.Columns)) for _, col := range handleKeyOnlyEvent.Columns { colName := tableInfo.ForceGetColumnName(col.ColumnID) conditions[colName] = col.Value @@ -295,7 +295,7 @@ func (b *BatchDecoder) assembleHandleKeyOnlyEvent( handleKeyOnlyEvent.TableInfo = model.BuildTableInfo(schema, table, columns, indexColumns) handleKeyOnlyEvent.Columns = model.Columns2ColumnDatas(columns, handleKeyOnlyEvent.TableInfo) - conditions = make(map[string]interface{}, len(handleKeyOnlyEvent.PreColumns)) + conditions = make(map[string]any, len(handleKeyOnlyEvent.PreColumns)) for _, col := range handleKeyOnlyEvent.PreColumns { colName := tableInfo.ForceGetColumnName(col.ColumnID) conditions[colName] = col.Value diff --git a/pkg/sink/codec/open/open_protocol_encoder_test.go b/pkg/sink/codec/open/open_protocol_encoder_test.go index e781819134..0a391cf19b 100644 --- a/pkg/sink/codec/open/open_protocol_encoder_test.go +++ b/pkg/sink/codec/open/open_protocol_encoder_test.go @@ -71,7 +71,7 @@ func TestMaxMessageBytes(t *testing.T) { builder, err = NewBatchEncoderBuilder(ctx, codecConfig) require.NoError(t, err) encoder = builder.Build() - for i := 0; i < 10000; i++ { + for range 10000 { err := encoder.AppendRowChangedEvent(ctx, topic, event, nil) require.NoError(t, err) } @@ -96,7 +96,7 @@ func TestMaxBatchSize(t *testing.T) { require.NoError(t, err) encoder := builder.Build() - for i := 0; i < 10000; i++ { + for range 10000 { err := encoder.AppendRowChangedEvent(ctx, "", event, nil) require.NoError(t, err) } diff --git a/pkg/sink/codec/simple/avro.go b/pkg/sink/codec/simple/avro.go index 8fd93b61a6..79111c49d3 100644 --- a/pkg/sink/codec/simple/avro.go +++ b/pkg/sink/codec/simple/avro.go @@ -23,11 +23,11 @@ import ( "github.com/pingcap/tiflow/cdc/model" ) -func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { +func newTableSchemaMap(tableInfo *model.TableInfo) any { pkInIndexes := false - indexesSchema := make([]interface{}, 0, len(tableInfo.Indices)) + indexesSchema := make([]any, 0, len(tableInfo.Indices)) for _, idx := range tableInfo.Indices { - index := map[string]interface{}{ + index := map[string]any{ "name": idx.Name.O, "unique": idx.Unique, "primary": idx.Primary, @@ -53,7 +53,7 @@ func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { if !pkInIndexes { pkColumns := tableInfo.GetPrimaryKeyColumnNames() if len(pkColumns) != 0 { - index := map[string]interface{}{ + index := map[string]any{ "name": "primary", "nullable": false, "primary": true, @@ -68,9 +68,9 @@ func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { return tableInfo.Columns[i].ID < tableInfo.Columns[j].ID }) - columnsSchema := make([]interface{}, 0, len(tableInfo.Columns)) + columnsSchema := make([]any, 0, len(tableInfo.Columns)) for _, col := range tableInfo.Columns { - mysqlType := map[string]interface{}{ + mysqlType := map[string]any{ "mysqlType": types.TypeToStr(col.GetType(), col.GetCharset()), "charset": col.GetCharset(), "collate": col.GetCollate(), @@ -80,30 +80,30 @@ func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { switch col.GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeFloat, mysql.TypeDouble, mysql.TypeBit, mysql.TypeYear: - mysqlType["unsigned"] = map[string]interface{}{ + mysqlType["unsigned"] = map[string]any{ "boolean": mysql.HasUnsignedFlag(col.GetFlag()), } - mysqlType["zerofill"] = map[string]interface{}{ + mysqlType["zerofill"] = map[string]any{ "boolean": mysql.HasZerofillFlag(col.GetFlag()), } case mysql.TypeEnum, mysql.TypeSet: - mysqlType["elements"] = map[string]interface{}{ + mysqlType["elements"] = map[string]any{ "array": col.GetElems(), } case mysql.TypeNewDecimal: - mysqlType["decimal"] = map[string]interface{}{ + mysqlType["decimal"] = map[string]any{ "int": col.GetDecimal(), } - mysqlType["unsigned"] = map[string]interface{}{ + mysqlType["unsigned"] = map[string]any{ "boolean": mysql.HasUnsignedFlag(col.GetFlag()), } - mysqlType["zerofill"] = map[string]interface{}{ + mysqlType["zerofill"] = map[string]any{ "boolean": mysql.HasZerofillFlag(col.GetFlag()), } default: } - column := map[string]interface{}{ + column := map[string]any{ "name": col.Name.O, "dataType": mysqlType, "nullable": !mysql.HasNotNullFlag(col.GetFlag()), @@ -112,7 +112,7 @@ func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { defaultValue := col.GetDefaultValue() if defaultValue != nil { // according to TiDB source code, the default value is converted to string if not nil. - column["default"] = map[string]interface{}{ + column["default"] = map[string]any{ "string": defaultValue, } } @@ -120,7 +120,7 @@ func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { columnsSchema = append(columnsSchema, column) } - result := map[string]interface{}{ + result := map[string]any{ "database": tableInfo.TableName.Schema, "table": tableInfo.TableName.Table, "tableID": tableInfo.ID, @@ -132,51 +132,51 @@ func newTableSchemaMap(tableInfo *model.TableInfo) interface{} { return result } -func newResolvedMessageMap(ts uint64) map[string]interface{} { - watermark := map[string]interface{}{ +func newResolvedMessageMap(ts uint64) map[string]any { + watermark := map[string]any{ "version": defaultVersion, "type": string(MessageTypeWatermark), "commitTs": int64(ts), "buildTs": time.Now().UnixMilli(), } - watermark = map[string]interface{}{ + watermark = map[string]any{ "com.pingcap.simple.avro.Watermark": watermark, } - payload := map[string]interface{}{ + payload := map[string]any{ "type": string(MessageTypeWatermark), "payload": watermark, } - return map[string]interface{}{ + return map[string]any{ "com.pingcap.simple.avro.Message": payload, } } -func newBootstrapMessageMap(tableInfo *model.TableInfo) map[string]interface{} { - m := map[string]interface{}{ +func newBootstrapMessageMap(tableInfo *model.TableInfo) map[string]any { + m := map[string]any{ "version": defaultVersion, "type": string(MessageTypeBootstrap), "tableSchema": newTableSchemaMap(tableInfo), "buildTs": time.Now().UnixMilli(), } - m = map[string]interface{}{ + m = map[string]any{ "com.pingcap.simple.avro.Bootstrap": m, } - payload := map[string]interface{}{ + payload := map[string]any{ "type": string(MessageTypeBootstrap), "payload": m, } - return map[string]interface{}{ + return map[string]any{ "com.pingcap.simple.avro.Message": payload, } } -func newDDLMessageMap(ddl *model.DDLEvent) map[string]interface{} { - result := map[string]interface{}{ +func newDDLMessageMap(ddl *model.DDLEvent) map[string]any { + result := map[string]any{ "version": defaultVersion, "type": string(getDDLType(ddl.Type)), "sql": ddl.Query, @@ -186,25 +186,25 @@ func newDDLMessageMap(ddl *model.DDLEvent) map[string]interface{} { if ddl.TableInfo != nil && ddl.TableInfo.TableInfo != nil { tableSchema := newTableSchemaMap(ddl.TableInfo) - result["tableSchema"] = map[string]interface{}{ + result["tableSchema"] = map[string]any{ "com.pingcap.simple.avro.TableSchema": tableSchema, } } if ddl.PreTableInfo != nil && ddl.PreTableInfo.TableInfo != nil { tableSchema := newTableSchemaMap(ddl.PreTableInfo) - result["preTableSchema"] = map[string]interface{}{ + result["preTableSchema"] = map[string]any{ "com.pingcap.simple.avro.TableSchema": tableSchema, } } - result = map[string]interface{}{ + result = map[string]any{ "com.pingcap.simple.avro.DDL": result, } - payload := map[string]interface{}{ + payload := map[string]any{ "type": string(MessageTypeDDL), "payload": result, } - return map[string]interface{}{ + return map[string]any{ "com.pingcap.simple.avro.Message": payload, } } @@ -213,32 +213,32 @@ var ( // genericMapPool return holder for each column and checksum genericMapPool = sync.Pool{ New: func() any { - return make(map[string]interface{}) + return make(map[string]any) }, } // rowMapPool return map for each row rowMapPool = sync.Pool{ New: func() any { - return make(map[string]interface{}) + return make(map[string]any) }, } dmlMessagePayloadPool = sync.Pool{ New: func() any { - return make(map[string]interface{}) + return make(map[string]any) }, } // dmlMessagePool return a map for the dml message dmlMessagePool = sync.Pool{ New: func() any { - return make(map[string]interface{}) + return make(map[string]any) }, } messageHolderPool = sync.Pool{ New: func() any { - return make(map[string]interface{}) + return make(map[string]any) }, } ) @@ -247,8 +247,8 @@ func (a *avroMarshaller) newDMLMessageMap( event *model.RowChangedEvent, onlyHandleKey bool, claimCheckFileName string, -) map[string]interface{} { - dmlMessagePayload := dmlMessagePayloadPool.Get().(map[string]interface{}) +) map[string]any { + dmlMessagePayload := dmlMessagePayloadPool.Get().(map[string]any) dmlMessagePayload["version"] = defaultVersion dmlMessagePayload["database"] = event.TableInfo.GetSchemaName() dmlMessagePayload["table"] = event.TableInfo.GetTableName() @@ -258,26 +258,26 @@ func (a *avroMarshaller) newDMLMessageMap( dmlMessagePayload["schemaVersion"] = int64(event.TableInfo.UpdateTS) if !a.config.LargeMessageHandle.Disabled() && onlyHandleKey { - dmlMessagePayload["handleKeyOnly"] = map[string]interface{}{ + dmlMessagePayload["handleKeyOnly"] = map[string]any{ "boolean": true, } } if a.config.LargeMessageHandle.EnableClaimCheck() && claimCheckFileName != "" { - dmlMessagePayload["claimCheckLocation"] = map[string]interface{}{ + dmlMessagePayload["claimCheckLocation"] = map[string]any{ "string": claimCheckFileName, } } if a.config.EnableRowChecksum && event.Checksum != nil { - cc := map[string]interface{}{ + cc := map[string]any{ "version": event.Checksum.Version, "corrupted": event.Checksum.Corrupted, "current": int64(event.Checksum.Current), "previous": int64(event.Checksum.Previous), } - holder := genericMapPool.Get().(map[string]interface{}) + holder := genericMapPool.Get().(map[string]any) holder["com.pingcap.simple.avro.Checksum"] = cc dmlMessagePayload["checksum"] = holder } @@ -298,36 +298,36 @@ func (a *avroMarshaller) newDMLMessageMap( dmlMessagePayload["type"] = string(DMLTypeUpdate) } - dmlMessagePayload = map[string]interface{}{ + dmlMessagePayload = map[string]any{ "com.pingcap.simple.avro.DML": dmlMessagePayload, } - dmlMessage := dmlMessagePool.Get().(map[string]interface{}) + dmlMessage := dmlMessagePool.Get().(map[string]any) dmlMessage["type"] = string(MessageTypeDML) dmlMessage["payload"] = dmlMessagePayload - messageHolder := messageHolderPool.Get().(map[string]interface{}) + messageHolder := messageHolderPool.Get().(map[string]any) messageHolder["com.pingcap.simple.avro.Message"] = dmlMessage return messageHolder } -func recycleMap(m map[string]interface{}) { - dmlMessage := m["com.pingcap.simple.avro.Message"].(map[string]interface{}) - dml := dmlMessage["payload"].(map[string]interface{})["com.pingcap.simple.avro.DML"].(map[string]interface{}) +func recycleMap(m map[string]any) { + dmlMessage := m["com.pingcap.simple.avro.Message"].(map[string]any) + dml := dmlMessage["payload"].(map[string]any)["com.pingcap.simple.avro.DML"].(map[string]any) checksum := dml["checksum"] if checksum != nil { - checksum := checksum.(map[string]interface{}) + checksum := checksum.(map[string]any) clear(checksum) genericMapPool.Put(checksum) } dataMap := dml["data"] if dataMap != nil { - dataMap := dataMap.(map[string]interface{})["map"].(map[string]interface{}) + dataMap := dataMap.(map[string]any)["map"].(map[string]any) for _, col := range dataMap { - colMap := col.(map[string]interface{}) + colMap := col.(map[string]any) clear(colMap) genericMapPool.Put(col) } @@ -337,9 +337,9 @@ func recycleMap(m map[string]interface{}) { oldDataMap := dml["old"] if oldDataMap != nil { - oldDataMap := oldDataMap.(map[string]interface{})["map"].(map[string]interface{}) + oldDataMap := oldDataMap.(map[string]any)["map"].(map[string]any) for _, col := range oldDataMap { - colMap := col.(map[string]interface{}) + colMap := col.(map[string]any) clear(colMap) genericMapPool.Put(col) } @@ -359,8 +359,8 @@ func recycleMap(m map[string]interface{}) { func (a *avroMarshaller) collectColumns( columns []*model.ColumnData, tableInfo *model.TableInfo, onlyHandleKey bool, -) map[string]interface{} { - result := rowMapPool.Get().(map[string]interface{}) +) map[string]any { + result := rowMapPool.Get().(map[string]any) for _, col := range columns { if col != nil { colFlag := tableInfo.ForceGetColumnFlagType(col.ColumnID) @@ -369,22 +369,22 @@ func (a *avroMarshaller) collectColumns( } colInfo := tableInfo.ForceGetColumnInfo(col.ColumnID) value, avroType := a.encodeValue4Avro(col.Value, &colInfo.FieldType) - holder := genericMapPool.Get().(map[string]interface{}) + holder := genericMapPool.Get().(map[string]any) holder[avroType] = value result[colInfo.Name.O] = holder } } - return map[string]interface{}{ + return map[string]any{ "map": result, } } -func newTableSchemaFromAvroNative(native map[string]interface{}) *TableSchema { - rawColumns := native["columns"].([]interface{}) +func newTableSchemaFromAvroNative(native map[string]any) *TableSchema { + rawColumns := native["columns"].([]any) columns := make([]*columnSchema, 0, len(rawColumns)) for _, raw := range rawColumns { - raw := raw.(map[string]interface{}) - rawDataType := raw["dataType"].(map[string]interface{}) + raw := raw.(map[string]any) + rawDataType := raw["dataType"].(map[string]any) var ( decimal int @@ -394,19 +394,19 @@ func newTableSchemaFromAvroNative(native map[string]interface{}) *TableSchema { ) if rawDataType["elements"] != nil { - rawElements := rawDataType["elements"].(map[string]interface{})["array"].([]interface{}) + rawElements := rawDataType["elements"].(map[string]any)["array"].([]any) for _, rawElement := range rawElements { elements = append(elements, rawElement.(string)) } } if rawDataType["decimal"] != nil { - decimal = int(rawDataType["decimal"].(map[string]interface{})["int"].(int32)) + decimal = int(rawDataType["decimal"].(map[string]any)["int"].(int32)) } if rawDataType["unsigned"] != nil { - unsigned = rawDataType["unsigned"].(map[string]interface{})["boolean"].(bool) + unsigned = rawDataType["unsigned"].(map[string]any)["boolean"].(bool) } if rawDataType["zerofill"] != nil { - zerofill = rawDataType["zerofill"].(map[string]interface{})["boolean"].(bool) + zerofill = rawDataType["zerofill"].(map[string]any)["boolean"].(bool) } dt := dataType{ @@ -420,11 +420,11 @@ func newTableSchemaFromAvroNative(native map[string]interface{}) *TableSchema { Zerofill: zerofill, } - var defaultValue interface{} + var defaultValue any rawDefault := raw["default"] switch v := rawDefault.(type) { case nil: - case map[string]interface{}: + case map[string]any: defaultValue = v["string"].(string) } @@ -437,11 +437,11 @@ func newTableSchemaFromAvroNative(native map[string]interface{}) *TableSchema { columns = append(columns, column) } - rawIndexes := native["indexes"].([]interface{}) + rawIndexes := native["indexes"].([]any) indexes := make([]*IndexSchema, 0, len(rawIndexes)) for _, raw := range rawIndexes { - raw := raw.(map[string]interface{}) - rawColumns := raw["columns"].([]interface{}) + raw := raw.(map[string]any) + rawColumns := raw["columns"].([]any) keyColumns := make([]string, 0, len(rawColumns)) for _, rawColumn := range rawColumns { keyColumns = append(keyColumns, rawColumn.(string)) @@ -465,13 +465,13 @@ func newTableSchemaFromAvroNative(native map[string]interface{}) *TableSchema { } } -func newMessageFromAvroNative(native interface{}, m *message) { - rawValues := native.(map[string]interface{})["com.pingcap.simple.avro.Message"].(map[string]interface{}) - rawPayload := rawValues["payload"].(map[string]interface{}) +func newMessageFromAvroNative(native any, m *message) { + rawValues := native.(map[string]any)["com.pingcap.simple.avro.Message"].(map[string]any) + rawPayload := rawValues["payload"].(map[string]any) rawMessage := rawPayload["com.pingcap.simple.avro.Watermark"] if rawMessage != nil { - rawValues = rawMessage.(map[string]interface{}) + rawValues = rawMessage.(map[string]any) m.Version = int(rawValues["version"].(int32)) m.Type = MessageTypeWatermark m.CommitTs = uint64(rawValues["commitTs"].(int64)) @@ -481,17 +481,17 @@ func newMessageFromAvroNative(native interface{}, m *message) { rawMessage = rawPayload["com.pingcap.simple.avro.Bootstrap"] if rawMessage != nil { - rawValues = rawMessage.(map[string]interface{}) + rawValues = rawMessage.(map[string]any) m.Version = int(rawValues["version"].(int32)) m.Type = MessageTypeBootstrap m.BuildTs = rawValues["buildTs"].(int64) - m.TableSchema = newTableSchemaFromAvroNative(rawValues["tableSchema"].(map[string]interface{})) + m.TableSchema = newTableSchemaFromAvroNative(rawValues["tableSchema"].(map[string]any)) return } rawMessage = rawPayload["com.pingcap.simple.avro.DDL"] if rawMessage != nil { - rawValues = rawMessage.(map[string]interface{}) + rawValues = rawMessage.(map[string]any) m.Version = int(rawValues["version"].(int32)) m.Type = MessageType(rawValues["type"].(string)) m.SQL = rawValues["sql"].(string) @@ -500,21 +500,21 @@ func newMessageFromAvroNative(native interface{}, m *message) { rawTableSchemaValues := rawValues["tableSchema"] if rawTableSchemaValues != nil { - rawTableSchema := rawTableSchemaValues.(map[string]interface{}) - rawTableSchema = rawTableSchema["com.pingcap.simple.avro.TableSchema"].(map[string]interface{}) + rawTableSchema := rawTableSchemaValues.(map[string]any) + rawTableSchema = rawTableSchema["com.pingcap.simple.avro.TableSchema"].(map[string]any) m.TableSchema = newTableSchemaFromAvroNative(rawTableSchema) } rawPreTableSchemaValue := rawValues["preTableSchema"] if rawPreTableSchemaValue != nil { - rawPreTableSchema := rawPreTableSchemaValue.(map[string]interface{}) - rawPreTableSchema = rawPreTableSchema["com.pingcap.simple.avro.TableSchema"].(map[string]interface{}) + rawPreTableSchema := rawPreTableSchemaValue.(map[string]any) + rawPreTableSchema = rawPreTableSchema["com.pingcap.simple.avro.TableSchema"].(map[string]any) m.PreTableSchema = newTableSchemaFromAvroNative(rawPreTableSchema) } return } - rawValues = rawPayload["com.pingcap.simple.avro.DML"].(map[string]interface{}) + rawValues = rawPayload["com.pingcap.simple.avro.DML"].(map[string]any) m.Type = MessageType(rawValues["type"].(string)) m.Version = int(rawValues["version"].(int32)) m.CommitTs = uint64(rawValues["commitTs"].(int64)) @@ -525,10 +525,10 @@ func newMessageFromAvroNative(native interface{}, m *message) { m.SchemaVersion = uint64(rawValues["schemaVersion"].(int64)) if rawValues["handleKeyOnly"] != nil { - m.HandleKeyOnly = rawValues["handleKeyOnly"].(map[string]interface{})["boolean"].(bool) + m.HandleKeyOnly = rawValues["handleKeyOnly"].(map[string]any)["boolean"].(bool) } if rawValues["claimCheckLocation"] != nil { - m.ClaimCheckLocation = rawValues["claimCheckLocation"].(map[string]interface{})["string"].(string) + m.ClaimCheckLocation = rawValues["claimCheckLocation"].(map[string]any)["string"].(string) } m.Checksum = newChecksum(rawValues) @@ -536,13 +536,13 @@ func newMessageFromAvroNative(native interface{}, m *message) { m.Old = newDataMap(rawValues["old"]) } -func newChecksum(raw map[string]interface{}) *checksum { +func newChecksum(raw map[string]any) *checksum { rawValue := raw["checksum"] if rawValue == nil { return nil } - rawChecksum := rawValue.(map[string]interface{}) - rawChecksum = rawChecksum["com.pingcap.simple.avro.Checksum"].(map[string]interface{}) + rawChecksum := rawValue.(map[string]any) + rawChecksum = rawChecksum["com.pingcap.simple.avro.Checksum"].(map[string]any) return &checksum{ Version: int(rawChecksum["version"].(int32)), Corrupted: rawChecksum["corrupted"].(bool), @@ -551,18 +551,18 @@ func newChecksum(raw map[string]interface{}) *checksum { } } -func newDataMap(rawValues interface{}) map[string]interface{} { +func newDataMap(rawValues any) map[string]any { if rawValues == nil { return nil } - data := make(map[string]interface{}) - rawDataMap := rawValues.(map[string]interface{})["map"].(map[string]interface{}) + data := make(map[string]any) + rawDataMap := rawValues.(map[string]any)["map"].(map[string]any) for key, value := range rawDataMap { if value == nil { data[key] = nil continue } - valueMap := value.(map[string]interface{}) + valueMap := value.(map[string]any) for _, v := range valueMap { data[key] = v } diff --git a/pkg/sink/codec/simple/decoder.go b/pkg/sink/codec/simple/decoder.go index 30101beca7..f9e1f9fe7d 100644 --- a/pkg/sink/codec/simple/decoder.go +++ b/pkg/sink/codec/simple/decoder.go @@ -244,11 +244,11 @@ func (d *Decoder) assembleHandleKeyOnlyRowChangedEvent(m *message) (*model.RowCh func (d *Decoder) buildData( holder *common.ColumnsHolder, fieldTypeMap map[string]*types.FieldType, timezone string, -) map[string]interface{} { +) map[string]any { columnsCount := holder.Length() - result := make(map[string]interface{}, columnsCount) + result := make(map[string]any, columnsCount) - for i := 0; i < columnsCount; i++ { + for i := range columnsCount { col := holder.Types[i] value := holder.Values[i] diff --git a/pkg/sink/codec/simple/encoder_test.go b/pkg/sink/codec/simple/encoder_test.go index d76c6ec25e..ef4f28f0b8 100644 --- a/pkg/sink/codec/simple/encoder_test.go +++ b/pkg/sink/codec/simple/encoder_test.go @@ -17,6 +17,7 @@ import ( "context" "database/sql/driver" "fmt" + "maps" "math/rand" "sort" "strconv" @@ -1485,7 +1486,7 @@ func TestEncodeLargeEventsNormal(t *testing.T) { require.NoError(t, err) require.NotNil(t, obtainedDDL) - obtainedDefaultValues := make(map[string]interface{}, len(obtainedDDL.TableInfo.Columns)) + obtainedDefaultValues := make(map[string]any, len(obtainedDDL.TableInfo.Columns)) for _, col := range obtainedDDL.TableInfo.Columns { obtainedDefaultValues[col.Name.O] = col.GetDefaultValue() switch col.GetType() { @@ -1790,10 +1791,8 @@ func TestLargeMessageHandleKeyOnly(t *testing.T) { require.Equal(t, model.MessageTypeRow, messageType) require.True(t, dec.msg.HandleKeyOnly) - obtainedValues := make(map[string]interface{}, len(dec.msg.Data)) - for name, value := range dec.msg.Data { - obtainedValues[name] = value - } + obtainedValues := make(map[string]any, len(dec.msg.Data)) + maps.Copy(obtainedValues, dec.msg.Data) for _, col := range event.Columns { colName := event.TableInfo.ForceGetColumnName(col.ColumnID) colFlag := event.TableInfo.ForceGetColumnFlagType(col.ColumnID) @@ -1813,9 +1812,7 @@ func TestLargeMessageHandleKeyOnly(t *testing.T) { } clear(obtainedValues) - for name, value := range dec.msg.Old { - obtainedValues[name] = value - } + maps.Copy(obtainedValues, dec.msg.Old) for _, col := range event.PreColumns { colName := event.TableInfo.ForceGetColumnName(col.ColumnID) colFlag := event.TableInfo.ForceGetColumnFlagType(col.ColumnID) diff --git a/pkg/sink/codec/simple/marshaller.go b/pkg/sink/codec/simple/marshaller.go index cac4a48c14..343c3ce32f 100644 --- a/pkg/sink/codec/simple/marshaller.go +++ b/pkg/sink/codec/simple/marshaller.go @@ -121,7 +121,7 @@ func (m *avroMarshaller) MarshalCheckpoint(ts uint64) ([]byte, error) { // MarshalDDLEvent implement the marshaller interface func (m *avroMarshaller) MarshalDDLEvent(event *model.DDLEvent) ([]byte, error) { - var msg map[string]interface{} + var msg map[string]any if event.IsBootstrap { msg = newBootstrapMessageMap(event.TableInfo) } else { diff --git a/pkg/sink/codec/simple/message.go b/pkg/sink/codec/simple/message.go index 4bba13e0e0..b5c2b1a2bb 100644 --- a/pkg/sink/codec/simple/message.go +++ b/pkg/sink/codec/simple/message.go @@ -102,10 +102,10 @@ func getDDLType(t timodel.ActionType) MessageType { // columnSchema is the schema of the column. type columnSchema struct { - Name string `json:"name"` - DataType dataType `json:"dataType"` - Nullable bool `json:"nullable"` - Default interface{} `json:"default"` + Name string `json:"name"` + DataType dataType `json:"dataType"` + Nullable bool `json:"nullable"` + Default any `json:"default"` } type dataType struct { @@ -428,7 +428,7 @@ func adjustTimestampValue(column *model.ColumnData, flag types.FieldType) { switch v := column.Value.(type) { case map[string]string: ts = v["value"] - case map[string]interface{}: + case map[string]any: ts = v["value"].(string) } column.Value = ts @@ -436,7 +436,7 @@ func adjustTimestampValue(column *model.ColumnData, flag types.FieldType) { } func decodeColumns( - rawData map[string]interface{}, tableInfo *model.TableInfo, + rawData map[string]any, tableInfo *model.TableInfo, ) []*model.ColumnData { if rawData == nil { return nil @@ -492,9 +492,9 @@ type message struct { Checksum *checksum `json:"checksum,omitempty"` // Data is available for the Insert and Update event. - Data map[string]interface{} `json:"data,omitempty"` + Data map[string]any `json:"data,omitempty"` // Old is available for the Update and Delete event. - Old map[string]interface{} `json:"old,omitempty"` + Old map[string]any `json:"old,omitempty"` // TableSchema is for the DDL and Bootstrap event. TableSchema *TableSchema `json:"tableSchema,omitempty"` // PreTableSchema holds schema information before the DDL executed. @@ -586,8 +586,8 @@ func (a *jsonMarshaller) newDMLMessage( func (a *jsonMarshaller) formatColumns( columns []*model.ColumnData, tableInfo *model.TableInfo, onlyHandleKey bool, -) map[string]interface{} { - result := make(map[string]interface{}, len(columns)) +) map[string]any { + result := make(map[string]any, len(columns)) colInfos := tableInfo.GetColInfosForRowChangedEvent() for i, col := range columns { if col != nil { @@ -603,21 +603,21 @@ func (a *jsonMarshaller) formatColumns( } func (a *avroMarshaller) encodeValue4Avro( - value interface{}, ft *types.FieldType, -) (interface{}, string) { + value any, ft *types.FieldType, +) (any, string) { if value == nil { return nil, "null" } switch ft.GetType() { case mysql.TypeTimestamp: - return map[string]interface{}{ + return map[string]any{ "location": a.config.TimeZone.String(), "value": value.(string), }, "com.pingcap.simple.avro.Timestamp" case mysql.TypeLonglong: if mysql.HasUnsignedFlag(ft.GetFlag()) { - return map[string]interface{}{ + return map[string]any{ "value": int64(value.(uint64)), }, "com.pingcap.simple.avro.UnsignedBigint" } @@ -648,8 +648,8 @@ func (a *avroMarshaller) encodeValue4Avro( } func encodeValue( - value interface{}, ft *types.FieldType, location string, -) interface{} { + value any, ft *types.FieldType, location string, +) any { if value == nil { return nil } @@ -725,7 +725,7 @@ func encodeValue( return result } -func decodeColumn(value interface{}, id int64, fieldType *types.FieldType) *model.ColumnData { +func decodeColumn(value any, id int64, fieldType *types.FieldType) *model.ColumnData { result := &model.ColumnData{ ColumnID: id, Value: value, @@ -784,7 +784,7 @@ func decodeColumn(value interface{}, id int64, fieldType *types.FieldType) *mode } else { value, err = strconv.ParseInt(v, 10, 64) } - case map[string]interface{}: + case map[string]any: value = uint64(v["value"].(int64)) default: value = v diff --git a/pkg/sink/codec/utils/test_utils.go b/pkg/sink/codec/utils/test_utils.go index 18c38c8918..c24408f6c8 100644 --- a/pkg/sink/codec/utils/test_utils.go +++ b/pkg/sink/codec/utils/test_utils.go @@ -165,7 +165,7 @@ func LargeColumnKeyValues() ([]string, []driver.Value) { } // LargeTableColumns is the columns of large table -var LargeTableColumns = map[string]interface{}{ +var LargeTableColumns = map[string]any{ "t": []uint8("127"), "tu1": []uint8("127"), "tu2": []uint8("128"), diff --git a/pkg/sink/kafka/options_test.go b/pkg/sink/kafka/options_test.go index c9b34bb580..10a3443cef 100644 --- a/pkg/sink/kafka/options_test.go +++ b/pkg/sink/kafka/options_test.go @@ -437,7 +437,7 @@ func TestCreateProducerFailed(t *testing.T) { func TestConfigurationCombinations(t *testing.T) { combinations := []struct { uriTemplate string - uriParams []interface{} + uriParams []any brokerMessageMaxBytes string topicMaxMessageBytes string expectedMaxMessageBytes string @@ -447,7 +447,7 @@ func TestConfigurationCombinations(t *testing.T) { // expected = min(`max-message-bytes`, `message.max.bytes`) = `message.max.bytes` { "kafka://127.0.0.1:9092/%s", - []interface{}{"not-exist-topic"}, + []any{"not-exist-topic"}, BrokerMessageMaxBytes, TopicMaxMessageBytes, BrokerMessageMaxBytes, @@ -457,7 +457,7 @@ func TestConfigurationCombinations(t *testing.T) { // expected = min(`max-message-bytes`, `message.max.bytes`) = `max-message-bytes` { "kafka://127.0.0.1:9092/%s", - []interface{}{"not-exist-topic"}, + []any{"not-exist-topic"}, strconv.Itoa(config.DefaultMaxMessageBytes), TopicMaxMessageBytes, strconv.Itoa(config.DefaultMaxMessageBytes), @@ -467,7 +467,7 @@ func TestConfigurationCombinations(t *testing.T) { // expected = min(`max-message-bytes`, `message.max.bytes`) = `max-message-bytes` { "kafka://127.0.0.1:9092/%s", - []interface{}{"no-params"}, + []any{"no-params"}, strconv.Itoa(config.DefaultMaxMessageBytes + 1), TopicMaxMessageBytes, strconv.Itoa(config.DefaultMaxMessageBytes), @@ -477,7 +477,7 @@ func TestConfigurationCombinations(t *testing.T) { // user set `max-message-bytes` < `message.max.bytes` < default `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{"not-created-topic", strconv.Itoa(1024*1024 - 1)}, + []any{"not-created-topic", strconv.Itoa(1024*1024 - 1)}, BrokerMessageMaxBytes, TopicMaxMessageBytes, strconv.Itoa(1024*1024 - 1), @@ -486,7 +486,7 @@ func TestConfigurationCombinations(t *testing.T) { // user set `max-message-bytes` < default `max-message-bytes` < `message.max.bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes - 1)}, + []any{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes - 1)}, strconv.Itoa(config.DefaultMaxMessageBytes + 1), TopicMaxMessageBytes, strconv.Itoa(config.DefaultMaxMessageBytes - 1), @@ -495,7 +495,7 @@ func TestConfigurationCombinations(t *testing.T) { // `message.max.bytes` < user set `max-message-bytes` < default `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{"not-created-topic", strconv.Itoa(1024*1024 + 1)}, + []any{"not-created-topic", strconv.Itoa(1024*1024 + 1)}, BrokerMessageMaxBytes, TopicMaxMessageBytes, BrokerMessageMaxBytes, @@ -504,7 +504,7 @@ func TestConfigurationCombinations(t *testing.T) { // `message.max.bytes` < default `max-message-bytes` < user set `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes + 1)}, + []any{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes + 1)}, BrokerMessageMaxBytes, TopicMaxMessageBytes, BrokerMessageMaxBytes, @@ -513,7 +513,7 @@ func TestConfigurationCombinations(t *testing.T) { // default `max-message-bytes` < user set `max-message-bytes` < `message.max.bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes + 1)}, + []any{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes + 1)}, strconv.Itoa(config.DefaultMaxMessageBytes + 2), TopicMaxMessageBytes, strconv.Itoa(config.DefaultMaxMessageBytes + 1), @@ -522,7 +522,7 @@ func TestConfigurationCombinations(t *testing.T) { // default `max-message-bytes` < `message.max.bytes` < user set `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes + 2)}, + []any{"not-created-topic", strconv.Itoa(config.DefaultMaxMessageBytes + 2)}, strconv.Itoa(config.DefaultMaxMessageBytes + 1), TopicMaxMessageBytes, strconv.Itoa(config.DefaultMaxMessageBytes + 1), @@ -533,7 +533,7 @@ func TestConfigurationCombinations(t *testing.T) { // expected = min(`max-message-bytes`, `max.message.bytes`) = `max.message.bytes` { "kafka://127.0.0.1:9092/%s", - []interface{}{DefaultMockTopicName}, + []any{DefaultMockTopicName}, BrokerMessageMaxBytes, TopicMaxMessageBytes, TopicMaxMessageBytes, @@ -543,7 +543,7 @@ func TestConfigurationCombinations(t *testing.T) { // expected = min(`max-message-bytes`, `max.message.bytes`) = `max-message-bytes` { "kafka://127.0.0.1:9092/%s", - []interface{}{DefaultMockTopicName}, + []any{DefaultMockTopicName}, BrokerMessageMaxBytes, strconv.Itoa(config.DefaultMaxMessageBytes), strconv.Itoa(config.DefaultMaxMessageBytes), @@ -553,7 +553,7 @@ func TestConfigurationCombinations(t *testing.T) { // expected = min(`max-message-bytes`, `max.message.bytes`) = `max-message-bytes` { "kafka://127.0.0.1:9092/%s", - []interface{}{DefaultMockTopicName}, + []any{DefaultMockTopicName}, BrokerMessageMaxBytes, strconv.Itoa(config.DefaultMaxMessageBytes + 1), strconv.Itoa(config.DefaultMaxMessageBytes), @@ -563,7 +563,7 @@ func TestConfigurationCombinations(t *testing.T) { // user set `max-message-bytes` < `max.message.bytes` < default `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{DefaultMockTopicName, strconv.Itoa(1024*1024 - 1)}, + []any{DefaultMockTopicName, strconv.Itoa(1024*1024 - 1)}, BrokerMessageMaxBytes, TopicMaxMessageBytes, strconv.Itoa(1024*1024 - 1), @@ -572,7 +572,7 @@ func TestConfigurationCombinations(t *testing.T) { // user set `max-message-bytes` < default `max-message-bytes` < `max.message.bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{ + []any{ DefaultMockTopicName, strconv.Itoa(config.DefaultMaxMessageBytes - 1), }, @@ -584,7 +584,7 @@ func TestConfigurationCombinations(t *testing.T) { // `max.message.bytes` < user set `max-message-bytes` < default `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{DefaultMockTopicName, strconv.Itoa(1024*1024 + 1)}, + []any{DefaultMockTopicName, strconv.Itoa(1024*1024 + 1)}, BrokerMessageMaxBytes, TopicMaxMessageBytes, TopicMaxMessageBytes, @@ -593,7 +593,7 @@ func TestConfigurationCombinations(t *testing.T) { // `max.message.bytes` < default `max-message-bytes` < user set `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{ + []any{ DefaultMockTopicName, strconv.Itoa(config.DefaultMaxMessageBytes + 1), }, @@ -605,7 +605,7 @@ func TestConfigurationCombinations(t *testing.T) { // default `max-message-bytes` < user set `max-message-bytes` < `max.message.bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{ + []any{ DefaultMockTopicName, strconv.Itoa(config.DefaultMaxMessageBytes + 1), }, @@ -617,7 +617,7 @@ func TestConfigurationCombinations(t *testing.T) { // default `max-message-bytes` < `max.message.bytes` < user set `max-message-bytes` { "kafka://127.0.0.1:9092/%s?max-message-bytes=%s", - []interface{}{ + []any{ DefaultMockTopicName, strconv.Itoa(config.DefaultMaxMessageBytes + 2), }, diff --git a/pkg/sink/kafka/sarama_test.go b/pkg/sink/kafka/sarama_test.go index 97136db65e..81547241ad 100644 --- a/pkg/sink/kafka/sarama_test.go +++ b/pkg/sink/kafka/sarama_test.go @@ -303,7 +303,6 @@ func TestApplySASL(t *testing.T) { } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() options := NewOptions() @@ -374,7 +373,6 @@ func TestApplyTLS(t *testing.T) { } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() options := NewOptions() diff --git a/pkg/sink/observer/observer_test.go b/pkg/sink/observer/observer_test.go index 225218f2ec..fb691da7e3 100644 --- a/pkg/sink/observer/observer_test.go +++ b/pkg/sink/observer/observer_test.go @@ -14,6 +14,7 @@ package observer import ( + context0 "context" "database/sql" "testing" @@ -23,7 +24,6 @@ import ( "github.com/pingcap/tiflow/pkg/config" pmysql "github.com/pingcap/tiflow/pkg/sink/mysql" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func newTestMockDB(t *testing.T) (db *sql.DB, mock sqlmock.Sqlmock) { @@ -40,7 +40,7 @@ func TestNewObserver(t *testing.T) { t.Parallel() dbIndex := 0 - mockGetDBConn := func(ctx context.Context, dsnStr string) (*sql.DB, error) { + mockGetDBConn := func(ctx context0.Context, dsnStr string) (*sql.DB, error) { defer func() { dbIndex++ }() if dbIndex == 0 { @@ -57,13 +57,13 @@ func TestNewObserver(t *testing.T) { return db, nil } - ctx := context.Background() + ctx := context0.Background() sinkURI := "mysql://127.0.0.1:21347/" obs, err := NewObserver(ctx, model.DefaultChangeFeedID("test"), sinkURI, config.GetDefaultReplicaConfig(), WithDBConnFactory(mockGetDBConn)) require.NoError(t, err) - for i := 0; i < 10; i++ { + for range 10 { err = obs.Tick(ctx) require.NoError(t, err) } diff --git a/pkg/sink/observer/tidb.go b/pkg/sink/observer/tidb.go index 8a39faca83..5355a7bf27 100644 --- a/pkg/sink/observer/tidb.go +++ b/pkg/sink/observer/tidb.go @@ -186,8 +186,8 @@ type tidbConnIdleDuration struct { duration sql.NullFloat64 } -func (m *tidbConnIdleDuration) columns() []interface{} { - return []interface{}{&m.ts, &m.instance, &m.inTxn, &m.quantile, &m.duration} +func (m *tidbConnIdleDuration) columns() []any { + return []any{&m.ts, &m.instance, &m.inTxn, &m.quantile, &m.duration} } type tidbConnCount struct { @@ -196,8 +196,8 @@ type tidbConnCount struct { count sql.NullInt32 } -func (m *tidbConnCount) columns() []interface{} { - return []interface{}{&m.ts, &m.instance, &m.count} +func (m *tidbConnCount) columns() []any { + return []any{&m.ts, &m.instance, &m.count} } type tidbQueryDuration struct { @@ -207,8 +207,8 @@ type tidbQueryDuration struct { duration sql.NullFloat64 } -func (m *tidbQueryDuration) columns() []interface{} { - return []interface{}{&m.ts, &m.instance, &m.queryType, &m.duration} +func (m *tidbQueryDuration) columns() []any { + return []any{&m.ts, &m.instance, &m.queryType, &m.duration} } type tidbTxnDuration struct { @@ -218,8 +218,8 @@ type tidbTxnDuration struct { duration sql.NullFloat64 } -func (m *tidbTxnDuration) columns() []interface{} { - return []interface{}{&m.ts, &m.instance, &m.opType, &m.duration} +func (m *tidbTxnDuration) columns() []any { + return []any{&m.ts, &m.instance, &m.opType, &m.duration} } type metricColumnImpl interface { @@ -228,7 +228,7 @@ type metricColumnImpl interface { type metricColumnIface[T metricColumnImpl] interface { *T - columns() []interface{} + columns() []any } func queryMetrics[T metricColumnImpl, F metricColumnIface[T]]( diff --git a/pkg/sink/pulsar/logger.go b/pkg/sink/pulsar/logger.go index 2b07ece570..e5a31717bc 100644 --- a/pkg/sink/pulsar/logger.go +++ b/pkg/sink/pulsar/logger.go @@ -38,7 +38,7 @@ func (p *Logger) WithFields(fields log.Fields) log.Entry { } // WithField with field -func (p *Logger) WithField(name string, value interface{}) log.Entry { +func (p *Logger) WithField(name string, value any) log.Entry { return &Logger{p.zapLogger.With(zap.Any(name, value))} } @@ -48,42 +48,42 @@ func (p *Logger) WithError(err error) log.Entry { } // Debug debug -func (p *Logger) Debug(args ...interface{}) { +func (p *Logger) Debug(args ...any) { p.zapLogger.Sugar().Debug(args...) } // Info info -func (p *Logger) Info(args ...interface{}) { +func (p *Logger) Info(args ...any) { p.zapLogger.Sugar().Info(args...) } // Warn warn -func (p *Logger) Warn(args ...interface{}) { +func (p *Logger) Warn(args ...any) { p.zapLogger.Sugar().Warn(args...) } // Error error -func (p *Logger) Error(args ...interface{}) { +func (p *Logger) Error(args ...any) { p.zapLogger.Sugar().Error(args...) } // Debugf debugf -func (p *Logger) Debugf(format string, args ...interface{}) { +func (p *Logger) Debugf(format string, args ...any) { p.zapLogger.Sugar().Debugf(format, args...) } // Infof infof -func (p *Logger) Infof(format string, args ...interface{}) { +func (p *Logger) Infof(format string, args ...any) { p.zapLogger.Sugar().Infof(format, args...) } // Warnf warnf -func (p *Logger) Warnf(format string, args ...interface{}) { +func (p *Logger) Warnf(format string, args ...any) { p.zapLogger.Sugar().Warnf(format, args...) } // Errorf errorf -func (p *Logger) Errorf(format string, args ...interface{}) { +func (p *Logger) Errorf(format string, args ...any) { p.zapLogger.Sugar().Errorf(format, args...) } diff --git a/pkg/spanz/btree_map_test.go b/pkg/spanz/btree_map_test.go index dc5d4aeb8e..647529808f 100644 --- a/pkg/spanz/btree_map_test.go +++ b/pkg/spanz/btree_map_test.go @@ -78,7 +78,7 @@ func TestMapAscend(t *testing.T) { t.Parallel() m := NewBtreeMap[int]() - for i := 0; i < 4; i++ { + for i := range 4 { m.ReplaceOrInsert(tablepb.Span{TableID: int64(i)}, i) } diff --git a/pkg/spanz/convert.go b/pkg/spanz/convert.go index 442f6ad736..94b8dcb03d 100644 --- a/pkg/spanz/convert.go +++ b/pkg/spanz/convert.go @@ -17,6 +17,7 @@ import ( "fmt" "reflect" "sort" + "strings" "unsafe" "github.com/pingcap/log" @@ -27,11 +28,11 @@ import ( // HexKey returns a hex string generated from the key. func HexKey(key []byte) string { // TODO(qupeng): improve the function. - str := "" + var str strings.Builder for _, c := range key { - str += fmt.Sprintf("%02X", c) + str.WriteString(fmt.Sprintf("%02X", c)) } - return str + return str.String() } // ArrayToSpan converts an array of TableID to an array of Span. diff --git a/pkg/spanz/convert_test.go b/pkg/spanz/convert_test.go index f3e7c8db8b..6c797334af 100644 --- a/pkg/spanz/convert_test.go +++ b/pkg/spanz/convert_test.go @@ -34,7 +34,7 @@ func TestHashableSpan(t *testing.T) { func TestHashableSpanHeapAlloc(t *testing.T) { span := tablepb.Span{TableID: 1} - for i := 0; i < 10; i++ { + for i := range 10 { span.StartKey = append(span.StartKey, byte(i)) span.EndKey = append(span.EndKey, byte(i)) } diff --git a/pkg/spanz/hash_map_test.go b/pkg/spanz/hash_map_test.go index ea9d8b3827..f2ebf7fcbe 100644 --- a/pkg/spanz/hash_map_test.go +++ b/pkg/spanz/hash_map_test.go @@ -74,7 +74,7 @@ func TestHashMapIter(t *testing.T) { t.Parallel() m := NewHashMap[int]() - for i := 0; i < 4; i++ { + for i := range 4 { m.ReplaceOrInsert(tablepb.Span{TableID: int64(i)}, i) } diff --git a/pkg/spanz/map_bench_test.go b/pkg/spanz/map_bench_test.go index 96335245ee..d7c71f1dba 100644 --- a/pkg/spanz/map_bench_test.go +++ b/pkg/spanz/map_bench_test.go @@ -25,7 +25,7 @@ func BenchmarkMap(b *testing.B) { sm := SyncMap{} spans := [100]tablepb.Span{} - for i := 0; i < len(spans); i++ { + for i := range len(spans) { spans[i] = TableIDToComparableSpan(int64(i)) } for i, span := range spans { diff --git a/pkg/sqlmodel/causality.go b/pkg/sqlmodel/causality.go index b2c60f0b1b..725b71a387 100644 --- a/pkg/sqlmodel/causality.go +++ b/pkg/sqlmodel/causality.go @@ -57,7 +57,7 @@ func collationNeeds2LowerCase(collation string) bool { return strings.HasSuffix(collation, "_ci") } -func columnValue2String(value interface{}) string { +func columnValue2String(value any) string { var data string switch v := value.(type) { case nil: @@ -104,7 +104,7 @@ func columnValue2String(value interface{}) string { func genKeyString( table string, columns []*timodel.ColumnInfo, - values []interface{}, + values []any, ) string { var buf strings.Builder for i, data := range values { @@ -140,9 +140,9 @@ func truncateIndexValues( ti *timodel.TableInfo, indexColumns *timodel.IndexInfo, tiColumns []*timodel.ColumnInfo, - data []interface{}, -) []interface{} { - values := make([]interface{}, 0, len(indexColumns.Columns)) + data []any, +) []any { + values := make([]any, 0, len(indexColumns.Columns)) datums, err := utils.AdjustBinaryProtocolForDatum(ctx, data, tiColumns) if err != nil { log.L().Warn("adjust binary protocol for datum error", zap.Error(err)) @@ -155,7 +155,7 @@ func truncateIndexValues( return values } -func (r *RowChange) getForeignKeyCausalityString(values []interface{}) []string { +func (r *RowChange) getForeignKeyCausalityString(values []any) []string { if len(r.foreignKeyRelations) == 0 { return nil } @@ -167,7 +167,7 @@ func (r *RowChange) getForeignKeyCausalityString(values []interface{}) []string continue } - relationValues := make([]interface{}, len(relation.ChildColumnIdx)) + relationValues := make([]any, len(relation.ChildColumnIdx)) skip := false for i, idx := range relation.ChildColumnIdx { if idx >= len(values) { @@ -200,7 +200,7 @@ func (r *RowChange) getForeignKeyCausalityString(values []interface{}) []string return keys } -func (r *RowChange) getCausalityString(values []interface{}) []string { +func (r *RowChange) getCausalityString(values []any) []string { sourceTable := r.sourceTable if r.causalityKeySourceTable != nil { // Only causality keys use this table name; r.sourceTable keeps the original source table. diff --git a/pkg/sqlmodel/causality_fk_test.go b/pkg/sqlmodel/causality_fk_test.go index dfce7685ef..a08e9dc4eb 100644 --- a/pkg/sqlmodel/causality_fk_test.go +++ b/pkg/sqlmodel/causality_fk_test.go @@ -38,7 +38,7 @@ func TestCausalityKeysWithForeignKey(t *testing.T) { &cdcmodel.TableName{Schema: "db", Table: "b"}, nil, nil, - []interface{}{2, 10}, + []any{2, 10}, childTable, nil, nil, @@ -65,7 +65,7 @@ func TestCausalityKeysWithNullForeignKey(t *testing.T) { &cdcmodel.TableName{Schema: "db", Table: "b"}, nil, nil, - []interface{}{3, nil}, + []any{3, nil}, childTable, nil, nil, diff --git a/pkg/sqlmodel/causality_test.go b/pkg/sqlmodel/causality_test.go index 0d17161191..348f104964 100644 --- a/pkg/sqlmodel/causality_test.go +++ b/pkg/sqlmodel/causality_test.go @@ -28,28 +28,28 @@ func TestCausalityKeys(t *testing.T) { cases := []struct { createSQL string - preValue []interface{} - postValue []interface{} + preValue []any + postValue []any causalityKeys []string }{ { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT, c3 VARCHAR(10) UNIQUE)", - []interface{}{1, 2, "abc"}, - []interface{}{3, 4, "abc"}, + []any{1, 2, "abc"}, + []any{3, 4, "abc"}, []string{"abc.c3.db.tb1", "1.c.db.tb1", "abc.c3.db.tb1", "3.c.db.tb1"}, }, { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT, c3 VARCHAR(10), UNIQUE INDEX(c3(1)))", - []interface{}{1, 2, "abc"}, - []interface{}{3, 4, "adef"}, + []any{1, 2, "abc"}, + []any{3, 4, "adef"}, []string{"a.c3.db.tb1", "1.c.db.tb1", "a.c3.db.tb1", "3.c.db.tb1"}, }, // test not string key { "CREATE TABLE tb1 (a INT, b INT, UNIQUE KEY a(a))", - []interface{}{100, 200}, + []any{100, 200}, nil, []string{"100.a.db.tb1"}, }, @@ -57,7 +57,7 @@ func TestCausalityKeys(t *testing.T) { // test text { "CREATE TABLE tb1 (a INT, b TEXT, UNIQUE KEY b(b(3)))", - []interface{}{1, "1234"}, + []any{1, "1234"}, nil, []string{"123.b.db.tb1"}, }, @@ -65,7 +65,7 @@ func TestCausalityKeys(t *testing.T) { // test composite keys { "CREATE TABLE tb1 (a INT, b TEXT, UNIQUE KEY c2(a, b(3)))", - []interface{}{1, "1234"}, + []any{1, "1234"}, nil, []string{"1.a.123.b.db.tb1"}, }, @@ -73,7 +73,7 @@ func TestCausalityKeys(t *testing.T) { // test value is null { "CREATE TABLE tb1 (a INT, b TEXT, UNIQUE KEY c2(a, b(3)))", - []interface{}{1, nil}, + []any{1, nil}, nil, []string{"1.a.db.tb1"}, }, @@ -92,7 +92,7 @@ func TestCausalityKeysWithCausalityKeySourceTable(t *testing.T) { source := &cdcmodel.TableName{Schema: "DB", Table: "Parent"} causalityKeySource := &cdcmodel.TableName{Schema: "db", Table: "parent"} ti := mockTableInfo(t, "CREATE TABLE parent (id INT PRIMARY KEY)") - change := NewRowChange(source, nil, nil, []interface{}{10}, ti, nil, nil) + change := NewRowChange(source, nil, nil, []any{10}, ti, nil, nil) change.SetCausalityKeySourceTable(causalityKeySource) require.Equal(t, []string{"10.id.db.parent"}, change.CausalityKeys()) @@ -105,13 +105,11 @@ func TestCausalityKeysNoRace(t *testing.T) { source := &cdcmodel.TableName{Schema: "db", Table: "tb1"} ti := mockTableInfo(t, "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT, c3 VARCHAR(10) UNIQUE)") var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(1) - go func() { - change := NewRowChange(source, nil, []interface{}{1, 2, "abc"}, []interface{}{3, 4, "abc"}, ti, nil, nil) + for range 100 { + wg.Go(func() { + change := NewRowChange(source, nil, []any{1, 2, "abc"}, []any{3, 4, "abc"}, ti, nil, nil) change.CausalityKeys() - wg.Done() - }() + }) } wg.Wait() } @@ -123,73 +121,73 @@ func TestGetCausalityString(t *testing.T) { testCases := []struct { schema string - values []interface{} + values []any keys []string }{ { // test no keys will use full row data instead of table name schema: `create table t1(a int)`, - values: []interface{}{10}, + values: []any{10}, keys: []string{"10.a.db.tbl"}, }, { // one primary key schema: `create table t2(a int primary key, b double)`, - values: []interface{}{60, 70.5}, + values: []any{60, 70.5}, keys: []string{"60.a.db.tbl"}, }, { // one unique key schema: `create table t3(a int unique, b double)`, - values: []interface{}{60, 70.5}, + values: []any{60, 70.5}, keys: []string{"60.a.db.tbl"}, }, { // one ordinary key schema: `create table t4(a int, b double, key(b))`, - values: []interface{}{60, 70.5}, + values: []any{60, 70.5}, keys: []string{"60.a.70.5.b.db.tbl"}, }, { // multiple keys schema: `create table t5(a int, b text, c int, key(a), key(b(3)))`, - values: []interface{}{13, "abcdef", 15}, + values: []any{13, "abcdef", 15}, keys: []string{"13.a.abcdef.b.15.c.db.tbl"}, }, { // multiple keys with primary key schema: `create table t6(a int primary key, b varchar(16) unique)`, - values: []interface{}{16, "xyz"}, + values: []any{16, "xyz"}, keys: []string{"xyz.b.db.tbl", "16.a.db.tbl"}, }, { // non-integer primary key schema: `create table t65(a int unique, b varchar(16) primary key)`, - values: []interface{}{16, "xyz"}, + values: []any{16, "xyz"}, keys: []string{"16.a.db.tbl", "xyz.b.db.tbl"}, }, { // case insensitive schema: `create table t_ci(a int unique, b varchar(16) primary key)default charset=utf8 collate=utf8_unicode_ci`, - values: []interface{}{16, "XyZ"}, + values: []any{16, "XyZ"}, keys: []string{"16.a.db.tbl", "xyz.b.db.tbl"}, }, { // case sensitive schema: `create table t_bin(a int unique, b varchar(16) primary key)default charset=utf8 collate=utf8_bin`, - values: []interface{}{16, "XyZ"}, + values: []any{16, "XyZ"}, keys: []string{"16.a.db.tbl", "XyZ.b.db.tbl"}, }, { // primary key of multiple columns schema: `create table t7(a int, b int, primary key(a, b))`, - values: []interface{}{59, 69}, + values: []any{59, 69}, keys: []string{"59.a.69.b.db.tbl"}, }, { // ordinary key of multiple columns schema: `create table t75(a int, b int, c int, key(a, b), key(c, b))`, - values: []interface{}{48, 58, 68}, + values: []any{48, 58, 68}, keys: []string{"48.a.58.b.68.c.db.tbl"}, }, { @@ -203,7 +201,7 @@ func TestGetCausalityString(t *testing.T) { unique key(c, a) ) `, - values: []interface{}{27, 37, 47}, + values: []any{27, 37, 47}, keys: []string{"27.a.37.b.db.tbl", "37.b.47.c.db.tbl", "47.c.27.a.db.tbl"}, }, { @@ -215,7 +213,7 @@ func TestGetCausalityString(t *testing.T) { unique key(b) ) `, - values: []interface{}{17, nil}, + values: []any{17, nil}, keys: []string{"17.a.db.tbl"}, }, } diff --git a/pkg/sqlmodel/multirow.go b/pkg/sqlmodel/multirow.go index b3dbfb8059..1d9ab5b285 100644 --- a/pkg/sqlmodel/multirow.go +++ b/pkg/sqlmodel/multirow.go @@ -76,7 +76,7 @@ func SameTypeTargetAndColumns(lhs *RowChange, rhs *RowChange) bool { // GenDeleteSQL generates the DELETE SQL and its arguments. // Input `changes` should have same target table and same columns for WHERE // (typically same PK/NOT NULL UK), otherwise the behaviour is undefined. -func GenDeleteSQL(changes ...*RowChange) (string, []interface{}) { +func GenDeleteSQL(changes ...*RowChange) (string, []any) { if len(changes) == 0 { log.L().DPanic("row changes is empty") return "", nil @@ -90,7 +90,7 @@ func GenDeleteSQL(changes ...*RowChange) (string, []interface{}) { buf.WriteString(first.targetTable.QuoteString()) buf.WriteString(" WHERE (") - allArgs := make([]interface{}, 0, len(changes)*CommonIndexColumnsCount) + allArgs := make([]any, 0, len(changes)*CommonIndexColumnsCount) for i, c := range changes { if i > 0 { @@ -123,7 +123,7 @@ func GenUpdateSQL(changes ...*RowChange) (string, []any) { // Pre-generate essential sub statements used after WHEN, WHERE. var ( whenCaseStmts = make([]string, len(changes)) - whenCaseArgs = make([][]interface{}, len(changes)) + whenCaseArgs = make([][]any, len(changes)) ) whereColumns, _ := first.whereColumnsAndValues() @@ -226,7 +226,7 @@ func GenUpdateSQL(changes ...*RowChange) (string, []any) { // GenInsertSQL generates the INSERT SQL and its arguments. // Input `changes` should have same target table and same modifiable columns, // otherwise the behaviour is undefined. -func GenInsertSQL(tp DMLType, changes ...*RowChange) (string, []interface{}) { +func GenInsertSQL(tp DMLType, changes ...*RowChange) (string, []any) { if len(changes) == 0 { log.L().DPanic("row changes is empty") return "", nil @@ -289,7 +289,7 @@ func GenInsertSQL(tp DMLType, changes ...*RowChange) (string, []interface{}) { } } - args := make([]interface{}, 0, len(changes)*(len(first.sourceTableInfo.Columns)-len(skipColIdx))) + args := make([]any, 0, len(changes)*(len(first.sourceTableInfo.Columns)-len(skipColIdx))) for _, change := range changes { i := 0 // used as index of skipColIdx for j, val := range change.postValues { diff --git a/pkg/sqlmodel/multirow_bench_test.go b/pkg/sqlmodel/multirow_bench_test.go index 507cec5dc3..e59632f37c 100644 --- a/pkg/sqlmodel/multirow_bench_test.go +++ b/pkg/sqlmodel/multirow_bench_test.go @@ -31,10 +31,10 @@ func prepareDataOneColoumnPK(t *testing.T, batch int) []*RowChange { c4 VARCHAR(10), c5 VARCHAR(100), c6 VARCHAR(1000), PRIMARY KEY (c))`) changes := make([]*RowChange, 0, batch) - for i := 0; i < batch; i++ { + for i := range batch { change := NewRowChange(source, target, - []interface{}{i + 1, i + 2, i + 3, "c4", "c5", "c6"}, - []interface{}{i + 10, i + 20, i + 30, "c4", "c5", "c6"}, + []any{i + 1, i + 2, i + 3, "c4", "c5", "c6"}, + []any{i + 10, i + 20, i + 30, "c4", "c5", "c6"}, sourceTI, targetTI, nil) changes = append(changes, change) } @@ -53,10 +53,10 @@ func prepareDataMultiColumnsPK(t *testing.T, batch int) []*RowChange { PRIMARY KEY (c1, c2, c3, c4))`) changes := make([]*RowChange, 0, batch) - for i := 0; i < batch; i++ { + for i := range batch { change := NewRowChange(source, target, - []interface{}{i + 1, i + 2, i + 3, i + 4, "c4", "c5", "c6", "c7", time.Time{}, time.Time{}}, - []interface{}{i + 10, i + 20, i + 30, i + 40, "c4", "c5", "c6", "c7", time.Time{}, time.Time{}}, + []any{i + 1, i + 2, i + 3, i + 4, "c4", "c5", "c6", "c7", time.Time{}, time.Time{}}, + []any{i + 10, i + 20, i + 30, i + 40, "c4", "c5", "c6", "c7", time.Time{}, time.Time{}}, sourceTI, targetTI, nil) changes = append(changes, change) } diff --git a/pkg/sqlmodel/multirow_test.go b/pkg/sqlmodel/multirow_test.go index 215a1d7f00..c8718e807a 100644 --- a/pkg/sqlmodel/multirow_test.go +++ b/pkg/sqlmodel/multirow_test.go @@ -20,7 +20,7 @@ import ( "github.com/stretchr/testify/require" ) -type genSQLFunc func(changes ...*RowChange) (string, []interface{}) +type genSQLFunc func(changes ...*RowChange) (string, []any) func TestGenDeleteMultiRows(t *testing.T) { t.Parallel() @@ -33,12 +33,12 @@ func TestGenDeleteMultiRows(t *testing.T) { sourceTI2 := mockTableInfo(t, "CREATE TABLE tb2 (c INT PRIMARY KEY, c2 INT)") targetTI := mockTableInfo(t, "CREATE TABLE tb (c INT PRIMARY KEY, c2 INT)") - change1 := NewRowChange(source1, target, []interface{}{1, 2}, nil, sourceTI1, targetTI, nil) - change2 := NewRowChange(source2, target, []interface{}{3, 4}, nil, sourceTI2, targetTI, nil) + change1 := NewRowChange(source1, target, []any{1, 2}, nil, sourceTI1, targetTI, nil) + change2 := NewRowChange(source2, target, []any{3, 4}, nil, sourceTI2, targetTI, nil) sql, args := GenDeleteSQL(change1, change2) require.Equal(t, "DELETE FROM `db`.`tb` WHERE (`c` = ?) OR (`c` = ?)", sql) - require.Equal(t, []interface{}{1, 3}, args) + require.Equal(t, []any{1, 3}, args) } func TestGenUpdateMultiRows(t *testing.T) { @@ -71,8 +71,8 @@ func testGenUpdateMultiRows(t *testing.T, genUpdate genSQLFunc) { sourceTI2 := mockTableInfo(t, "CREATE TABLE tb2 (c INT, c2 INT, c3 INT, UNIQUE KEY (c, c2))") targetTI := mockTableInfo(t, "CREATE TABLE tb (c INT, c2 INT, c3 INT, UNIQUE KEY (c, c2))") - change1 := NewRowChange(source1, target, []interface{}{1, 2, 3}, []interface{}{10, 20, 30}, sourceTI1, targetTI, nil) - change2 := NewRowChange(source2, target, []interface{}{4, 5, 6}, []interface{}{40, 50, 60}, sourceTI2, targetTI, nil) + change1 := NewRowChange(source1, target, []any{1, 2, 3}, []any{10, 20, 30}, sourceTI1, targetTI, nil) + change2 := NewRowChange(source2, target, []any{4, 5, 6}, []any{40, 50, 60}, sourceTI2, targetTI, nil) sql, args := genUpdate(change1, change2) expectedSQL := "UPDATE `db`.`tb` SET " + @@ -80,7 +80,7 @@ func testGenUpdateMultiRows(t *testing.T, genUpdate genSQLFunc) { "`c2`=CASE WHEN `c` = ? AND `c2` = ? THEN ? WHEN `c` = ? AND `c2` = ? THEN ? END, " + "`c3`=CASE WHEN `c` = ? AND `c2` = ? THEN ? WHEN `c` = ? AND `c2` = ? THEN ? END " + "WHERE (`c` = ? AND `c2` = ?) OR (`c` = ? AND `c2` = ?)" - expectedArgs := []interface{}{ + expectedArgs := []any{ 1, 2, 10, 4, 5, 40, 1, 2, 20, 4, 5, 50, 1, 2, 30, 4, 5, 60, @@ -100,8 +100,8 @@ func testGenUpdateMultiRowsOneColPK(t *testing.T, genUpdate genSQLFunc) { sourceTI2 := mockTableInfo(t, "CREATE TABLE tb2 (c INT, c2 INT, c3 INT, PRIMARY KEY (c))") targetTI := mockTableInfo(t, "CREATE TABLE tb (c INT, c2 INT, c3 INT, PRIMARY KEY (c))") - change1 := NewRowChange(source1, target, []interface{}{1, 2, 3}, []interface{}{10, 20, 30}, sourceTI1, targetTI, nil) - change2 := NewRowChange(source2, target, []interface{}{4, 5, 6}, []interface{}{40, 50, 60}, sourceTI2, targetTI, nil) + change1 := NewRowChange(source1, target, []any{1, 2, 3}, []any{10, 20, 30}, sourceTI1, targetTI, nil) + change2 := NewRowChange(source2, target, []any{4, 5, 6}, []any{40, 50, 60}, sourceTI2, targetTI, nil) sql, args := genUpdate(change1, change2) expectedSQL := "UPDATE `db`.`tb` SET " + @@ -109,7 +109,7 @@ func testGenUpdateMultiRowsOneColPK(t *testing.T, genUpdate genSQLFunc) { "`c2`=CASE WHEN `c` = ? THEN ? WHEN `c` = ? THEN ? END, " + "`c3`=CASE WHEN `c` = ? THEN ? WHEN `c` = ? THEN ? END " + "WHERE (`c` = ?) OR (`c` = ?)" - expectedArgs := []interface{}{ + expectedArgs := []any{ 1, 10, 4, 40, 1, 20, 4, 50, 1, 30, 4, 60, @@ -127,9 +127,9 @@ func testGenUpdateMultiRowsWithVirtualGeneratedColumn(t *testing.T, genUpdate ge sourceTI := mockTableInfo(t, "CREATE TABLE tb1 (c INT, c1 int as (c+100) virtual not null, c2 INT, c3 INT, PRIMARY KEY (c))") targetTI := mockTableInfo(t, "CREATE TABLE tb (c INT, c1 int as (c+100) virtual not null, c2 INT, c3 INT, PRIMARY KEY (c))") - change1 := NewRowChange(source, target, []interface{}{1, 101, 2, 3}, []interface{}{10, 110, 20, 30}, sourceTI, targetTI, nil) - change2 := NewRowChange(source, target, []interface{}{4, 104, 5, 6}, []interface{}{40, 140, 50, 60}, sourceTI, targetTI, nil) - change3 := NewRowChange(source, target, []interface{}{7, 107, 8, 9}, []interface{}{70, 170, 80, 90}, sourceTI, targetTI, nil) + change1 := NewRowChange(source, target, []any{1, 101, 2, 3}, []any{10, 110, 20, 30}, sourceTI, targetTI, nil) + change2 := NewRowChange(source, target, []any{4, 104, 5, 6}, []any{40, 140, 50, 60}, sourceTI, targetTI, nil) + change3 := NewRowChange(source, target, []any{7, 107, 8, 9}, []any{70, 170, 80, 90}, sourceTI, targetTI, nil) sql, args := genUpdate(change1, change2, change3) expectedSQL := "UPDATE `db`.`tb` SET " + @@ -137,7 +137,7 @@ func testGenUpdateMultiRowsWithVirtualGeneratedColumn(t *testing.T, genUpdate ge "`c2`=CASE WHEN `c` = ? THEN ? WHEN `c` = ? THEN ? WHEN `c` = ? THEN ? END, " + "`c3`=CASE WHEN `c` = ? THEN ? WHEN `c` = ? THEN ? WHEN `c` = ? THEN ? END " + "WHERE (`c` = ?) OR (`c` = ?) OR (`c` = ?)" - expectedArgs := []interface{}{ + expectedArgs := []any{ 1, 10, 4, 40, 7, 70, 1, 20, 4, 50, 7, 80, 1, 30, 4, 60, 7, 90, @@ -158,9 +158,9 @@ func testGenUpdateMultiRowsWithVirtualGeneratedColumns(t *testing.T, genUpdate g targetTI := mockTableInfo(t, `CREATE TABLE tb (c0 int as (c4*c4) virtual not null, c1 int as (c+100) virtual not null, c2 INT, c3 INT, c4 INT, PRIMARY KEY (c4))`) - change1 := NewRowChange(source, target, []interface{}{1, 101, 2, 3, 1}, []interface{}{100, 110, 20, 30, 10}, sourceTI, targetTI, nil) - change2 := NewRowChange(source, target, []interface{}{16, 104, 5, 6, 4}, []interface{}{1600, 140, 50, 60, 40}, sourceTI, targetTI, nil) - change3 := NewRowChange(source, target, []interface{}{49, 107, 8, 9, 7}, []interface{}{4900, 170, 80, 90, 70}, sourceTI, targetTI, nil) + change1 := NewRowChange(source, target, []any{1, 101, 2, 3, 1}, []any{100, 110, 20, 30, 10}, sourceTI, targetTI, nil) + change2 := NewRowChange(source, target, []any{16, 104, 5, 6, 4}, []any{1600, 140, 50, 60, 40}, sourceTI, targetTI, nil) + change3 := NewRowChange(source, target, []any{49, 107, 8, 9, 7}, []any{4900, 170, 80, 90, 70}, sourceTI, targetTI, nil) sql, args := genUpdate(change1, change2, change3) expectedSQL := "UPDATE `db`.`tb` SET " + @@ -168,7 +168,7 @@ func testGenUpdateMultiRowsWithVirtualGeneratedColumns(t *testing.T, genUpdate g "`c3`=CASE WHEN `c4` = ? THEN ? WHEN `c4` = ? THEN ? WHEN `c4` = ? THEN ? END, " + "`c4`=CASE WHEN `c4` = ? THEN ? WHEN `c4` = ? THEN ? WHEN `c4` = ? THEN ? END " + "WHERE (`c4` = ?) OR (`c4` = ?) OR (`c4` = ?)" - expectedArgs := []interface{}{ + expectedArgs := []any{ 1, 20, 4, 50, 7, 80, 1, 30, 4, 60, 7, 90, 1, 10, 4, 40, 7, 70, @@ -186,9 +186,9 @@ func testGenUpdateMultiRowsWithStoredGeneratedColumn(t *testing.T, genUpdate gen sourceTI := mockTableInfo(t, "CREATE TABLE tb1 (c INT, c1 int as (c+100) stored, c2 INT, c3 INT, PRIMARY KEY (c1))") targetTI := mockTableInfo(t, "CREATE TABLE tb (c INT, c1 int as (c+100) stored, c2 INT, c3 INT, PRIMARY KEY (c1))") - change1 := NewRowChange(source, target, []interface{}{1, 101, 2, 3}, []interface{}{10, 110, 20, 30}, sourceTI, targetTI, nil) - change2 := NewRowChange(source, target, []interface{}{4, 104, 5, 6}, []interface{}{40, 140, 50, 60}, sourceTI, targetTI, nil) - change3 := NewRowChange(source, target, []interface{}{7, 107, 8, 9}, []interface{}{70, 170, 80, 90}, sourceTI, targetTI, nil) + change1 := NewRowChange(source, target, []any{1, 101, 2, 3}, []any{10, 110, 20, 30}, sourceTI, targetTI, nil) + change2 := NewRowChange(source, target, []any{4, 104, 5, 6}, []any{40, 140, 50, 60}, sourceTI, targetTI, nil) + change3 := NewRowChange(source, target, []any{7, 107, 8, 9}, []any{70, 170, 80, 90}, sourceTI, targetTI, nil) sql, args := genUpdate(change1, change2, change3) expectedSQL := "UPDATE `db`.`tb` SET " + @@ -196,7 +196,7 @@ func testGenUpdateMultiRowsWithStoredGeneratedColumn(t *testing.T, genUpdate gen "`c2`=CASE WHEN `c1` = ? THEN ? WHEN `c1` = ? THEN ? WHEN `c1` = ? THEN ? END, " + "`c3`=CASE WHEN `c1` = ? THEN ? WHEN `c1` = ? THEN ? WHEN `c1` = ? THEN ? END " + "WHERE (`c1` = ?) OR (`c1` = ?) OR (`c1` = ?)" - expectedArgs := []interface{}{ + expectedArgs := []any{ 101, 10, 104, 40, 107, 70, 101, 20, 104, 50, 107, 80, 101, 30, 104, 60, 107, 90, @@ -218,18 +218,18 @@ func TestGenInsertMultiRows(t *testing.T) { sourceTI2 := mockTableInfo(t, "CREATE TABLE tb2 (gen INT AS (c+1), c INT PRIMARY KEY, c2 INT)") targetTI := mockTableInfo(t, "CREATE TABLE tb (gen INT AS (c+1), c INT PRIMARY KEY, c2 INT)") - change1 := NewRowChange(source1, target, nil, []interface{}{2, 1, 2}, sourceTI1, targetTI, nil) - change2 := NewRowChange(source2, target, nil, []interface{}{4, 3, 4}, sourceTI2, targetTI, nil) + change1 := NewRowChange(source1, target, nil, []any{2, 1, 2}, sourceTI1, targetTI, nil) + change2 := NewRowChange(source2, target, nil, []any{4, 3, 4}, sourceTI2, targetTI, nil) sql, args := GenInsertSQL(DMLInsert, change1, change2) require.Equal(t, "INSERT INTO `db`.`tb` (`c`,`c2`) VALUES (?,?),(?,?)", sql) - require.Equal(t, []interface{}{1, 2, 3, 4}, args) + require.Equal(t, []any{1, 2, 3, 4}, args) sql, args = GenInsertSQL(DMLReplace, change1, change2) require.Equal(t, "REPLACE INTO `db`.`tb` (`c`,`c2`) VALUES (?,?),(?,?)", sql) - require.Equal(t, []interface{}{1, 2, 3, 4}, args) + require.Equal(t, []any{1, 2, 3, 4}, args) sql, args = GenInsertSQL(DMLInsertOnDuplicateUpdate, change1, change2) require.Equal(t, "INSERT INTO `db`.`tb` (`c`,`c2`) VALUES (?,?),(?,?) ON DUPLICATE KEY UPDATE `c`=VALUES(`c`),`c2`=VALUES(`c2`)", sql) - require.Equal(t, []interface{}{1, 2, 3, 4}, args) + require.Equal(t, []any{1, 2, 3, 4}, args) } diff --git a/pkg/sqlmodel/reduce.go b/pkg/sqlmodel/reduce.go index f7cc25221f..be14958a19 100644 --- a/pkg/sqlmodel/reduce.go +++ b/pkg/sqlmodel/reduce.go @@ -33,7 +33,7 @@ func (r *RowChange) HasNotNullUniqueIdx() bool { // changes of one row. // We always use same index for same table structure to get IdentityValues. // two groups returned are from preValues and postValues. -func (r *RowChange) IdentityValues() ([]interface{}, []interface{}) { +func (r *RowChange) IdentityValues() ([]any, []any) { r.lazyInitWhereHandle() indexInfo := r.whereHandle.UniqueNotNullIdx @@ -49,7 +49,7 @@ func (r *RowChange) IdentityValues() ([]interface{}, []interface{}) { // make sure it's not updating the identity itself. // we extract identity from preValues for update/delete, postValues for insert. // if there's no primary key, return all values. -func (r *RowChange) RowIdentity() []interface{} { +func (r *RowChange) RowIdentity() []any { r.lazyInitWhereHandle() targetVals := r.preValues @@ -62,7 +62,7 @@ func (r *RowChange) RowIdentity() []interface{} { return targetVals } - identityVals := make([]interface{}, 0, len(indexInfo.Columns)) + identityVals := make([]any, 0, len(indexInfo.Columns)) for _, column := range indexInfo.Columns { identityVals = append(identityVals, targetVals[column.Offset]) } @@ -106,7 +106,7 @@ func (r *RowChange) IsPrimaryOrUniqueKeyUpdated() bool { } r.lazyInitWhereHandle() - identityUpdated := func(pre, post []interface{}) bool { + identityUpdated := func(pre, post []any) bool { if len(pre) != len(post) { // should not happen return true @@ -144,9 +144,9 @@ func (r *RowChange) IsPrimaryOrUniqueKeyUpdated() bool { } // identityValuesByIndex extra pre and post column values of given index -func (r *RowChange) identityValuesByIndex(indexInfo *timodel.IndexInfo) ([]interface{}, []interface{}) { - pre := make([]interface{}, 0, len(indexInfo.Columns)) - post := make([]interface{}, 0, len(indexInfo.Columns)) +func (r *RowChange) identityValuesByIndex(indexInfo *timodel.IndexInfo) ([]any, []any) { + pre := make([]any, 0, len(indexInfo.Columns)) + post := make([]any, 0, len(indexInfo.Columns)) for _, column := range indexInfo.Columns { if r.preValues != nil { @@ -160,7 +160,7 @@ func (r *RowChange) identityValuesByIndex(indexInfo *timodel.IndexInfo) ([]inter } // genKey gens key by values e.g. "a.1.b". -func genKey(values []interface{}) string { +func genKey(values []any) string { builder := new(strings.Builder) for i, v := range values { if i != 0 { diff --git a/pkg/sqlmodel/reduce_test.go b/pkg/sqlmodel/reduce_test.go index 85f4086ec1..3cafaa62da 100644 --- a/pkg/sqlmodel/reduce_test.go +++ b/pkg/sqlmodel/reduce_test.go @@ -26,22 +26,22 @@ func TestIdentity(t *testing.T) { source := &cdcmodel.TableName{Schema: "db", Table: "tb1"} sourceTI1 := mockTableInfo(t, "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT)") - change := NewRowChange(source, nil, []interface{}{1, 2}, nil, sourceTI1, nil, nil) + change := NewRowChange(source, nil, []any{1, 2}, nil, sourceTI1, nil, nil) pre, post := change.IdentityValues() - require.Equal(t, []interface{}{1}, pre) + require.Equal(t, []any{1}, pre) require.Len(t, post, 0) - change = NewRowChange(source, nil, []interface{}{1, 2}, []interface{}{1, 4}, sourceTI1, nil, nil) + change = NewRowChange(source, nil, []any{1, 2}, []any{1, 4}, sourceTI1, nil, nil) pre, post = change.IdentityValues() - require.Equal(t, []interface{}{1}, pre) - require.Equal(t, []interface{}{1}, post) + require.Equal(t, []any{1}, pre) + require.Equal(t, []any{1}, post) require.False(t, change.IsIdentityUpdated()) sourceTI2 := mockTableInfo(t, "CREATE TABLE tb1 (c INT, c2 INT)") - change = NewRowChange(source, nil, nil, []interface{}{5, 6}, sourceTI2, nil, nil) + change = NewRowChange(source, nil, nil, []any{5, 6}, sourceTI2, nil, nil) pre, post = change.IdentityValues() require.Len(t, pre, 0) - require.Equal(t, []interface{}{5, 6}, post) + require.Equal(t, []any{5, 6}, post) } func TestIdentityUpdatedWithUniqueKeys(t *testing.T) { @@ -50,23 +50,23 @@ func TestIdentityUpdatedWithUniqueKeys(t *testing.T) { source := &cdcmodel.TableName{Schema: "db", Table: "tb1"} sourceTI := mockTableInfo(t, "CREATE TABLE tb1 (id INT PRIMARY KEY, uk1 INT UNIQUE NOT NULL, uk2 INT UNIQUE, val INT)") - change := NewRowChange(source, nil, []interface{}{1, 10, 100, 7}, []interface{}{1, 10, 100, 9}, sourceTI, nil, nil) + change := NewRowChange(source, nil, []any{1, 10, 100, 7}, []any{1, 10, 100, 9}, sourceTI, nil, nil) require.False(t, change.IsIdentityUpdated()) require.False(t, change.IsPrimaryOrUniqueKeyUpdated()) - change = NewRowChange(source, nil, []interface{}{1, 10, 100, 7}, []interface{}{2, 10, 100, 7}, sourceTI, nil, nil) + change = NewRowChange(source, nil, []any{1, 10, 100, 7}, []any{2, 10, 100, 7}, sourceTI, nil, nil) require.True(t, change.IsIdentityUpdated()) require.True(t, change.IsPrimaryOrUniqueKeyUpdated()) - change = NewRowChange(source, nil, []interface{}{2, 10, 100, 7}, []interface{}{2, 20, 100, 7}, sourceTI, nil, nil) + change = NewRowChange(source, nil, []any{2, 10, 100, 7}, []any{2, 20, 100, 7}, sourceTI, nil, nil) require.False(t, change.IsIdentityUpdated()) require.True(t, change.IsPrimaryOrUniqueKeyUpdated()) - change = NewRowChange(source, nil, []interface{}{2, 20, 100, 7}, []interface{}{2, 20, 200, 7}, sourceTI, nil, nil) + change = NewRowChange(source, nil, []any{2, 20, 100, 7}, []any{2, 20, 200, 7}, sourceTI, nil, nil) require.False(t, change.IsIdentityUpdated()) require.True(t, change.IsPrimaryOrUniqueKeyUpdated()) - change = NewRowChange(source, nil, []interface{}{2, 20, nil, 7}, []interface{}{2, 20, 200, 7}, sourceTI, nil, nil) + change = NewRowChange(source, nil, []any{2, 20, nil, 7}, []any{2, 20, 200, 7}, sourceTI, nil, nil) require.False(t, change.IsIdentityUpdated()) require.True(t, change.IsPrimaryOrUniqueKeyUpdated()) } @@ -77,7 +77,7 @@ func TestSplit(t *testing.T) { source := &cdcmodel.TableName{Schema: "db", Table: "tb1"} sourceTI1 := mockTableInfo(t, "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT)") - change := NewRowChange(source, nil, []interface{}{1, 2}, []interface{}{3, 4}, sourceTI1, nil, nil) + change := NewRowChange(source, nil, []any{1, 2}, []any{3, 4}, sourceTI1, nil, nil) require.True(t, change.IsIdentityUpdated()) del, ins := change.SplitUpdate() delIDKey := del.IdentityKey() @@ -92,47 +92,47 @@ func (s *dpanicSuite) TestReduce() { sourceTI := mockTableInfo(s.T(), "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT)") cases := []struct { - pre1 []interface{} - post1 []interface{} - pre2 []interface{} - post2 []interface{} - preAfter []interface{} - postAfter []interface{} + pre1 []any + post1 []any + pre2 []any + post2 []any + preAfter []any + postAfter []any }{ // INSERT + UPDATE { nil, - []interface{}{1, 2}, - []interface{}{1, 2}, - []interface{}{3, 4}, + []any{1, 2}, + []any{1, 2}, + []any{3, 4}, nil, - []interface{}{3, 4}, + []any{3, 4}, }, // INSERT + DELETE { nil, - []interface{}{1, 2}, - []interface{}{1, 2}, + []any{1, 2}, + []any{1, 2}, nil, - []interface{}{1, 2}, + []any{1, 2}, nil, }, // UPDATE + UPDATE { - []interface{}{1, 2}, - []interface{}{1, 3}, - []interface{}{1, 3}, - []interface{}{1, 4}, - []interface{}{1, 2}, - []interface{}{1, 4}, + []any{1, 2}, + []any{1, 3}, + []any{1, 3}, + []any{1, 4}, + []any{1, 2}, + []any{1, 4}, }, // UPDATE + DELETE { - []interface{}{1, 2}, - []interface{}{1, 3}, - []interface{}{1, 3}, + []any{1, 2}, + []any{1, 3}, + []any{1, 3}, nil, - []interface{}{1, 2}, + []any{1, 2}, nil, }, } @@ -148,8 +148,8 @@ func (s *dpanicSuite) TestReduce() { } // test reduce on IdentityUpdated will DPanic - change1 := NewRowChange(source, nil, []interface{}{1, 2}, []interface{}{3, 4}, sourceTI, nil, nil) - change2 := NewRowChange(source, nil, []interface{}{3, 4}, []interface{}{5, 6}, sourceTI, nil, nil) + change1 := NewRowChange(source, nil, []any{1, 2}, []any{3, 4}, sourceTI, nil, nil) + change2 := NewRowChange(source, nil, []any{3, 4}, []any{5, 6}, sourceTI, nil, nil) s.Panics(func() { change2.Reduce(change1) }) diff --git a/pkg/sqlmodel/row_change.go b/pkg/sqlmodel/row_change.go index 700a8617d4..b4a458c128 100644 --- a/pkg/sqlmodel/row_change.go +++ b/pkg/sqlmodel/row_change.go @@ -61,8 +61,8 @@ type RowChange struct { // Optional source table name used only by CausalityKeys. causalityKeySourceTable *cdcmodel.TableName - preValues []interface{} - postValues []interface{} + preValues []any + postValues []any sourceTableInfo *timodel.TableInfo targetTableInfo *timodel.TableInfo @@ -92,8 +92,8 @@ type RowChange struct { func NewRowChange( sourceTable *cdcmodel.TableName, targetTable *cdcmodel.TableName, - preValues []interface{}, - postValues []interface{}, + preValues []any, + postValues []any, sourceTableInfo *timodel.TableInfo, downstreamTableInfo *timodel.TableInfo, tiCtx sessionctx.Context, @@ -241,7 +241,7 @@ func (r *RowChange) lazyInitWhereHandle() { // whereColumnsAndValues returns columns and values to identify the row, to form // the WHERE clause. -func (r *RowChange) whereColumnsAndValues() ([]string, []interface{}) { +func (r *RowChange) whereColumnsAndValues() ([]string, []any) { r.lazyInitWhereHandle() columns, values := r.sourceTableInfo.Columns, r.preValues @@ -271,7 +271,7 @@ func (r *RowChange) whereColumnsAndValues() ([]string, []interface{}) { // genWhere generates WHERE clause for UPDATE and DELETE to identify the row. // the SQL part is written to `buf` and the args part is returned. -func (r *RowChange) genWhere(buf *strings.Builder) []interface{} { +func (r *RowChange) genWhere(buf *strings.Builder) []any { whereColumns, whereValues := r.whereColumnsAndValues() for i, col := range whereColumns { @@ -288,7 +288,7 @@ func (r *RowChange) genWhere(buf *strings.Builder) []interface{} { return whereValues } -func (r *RowChange) genDeleteSQL() (string, []interface{}) { +func (r *RowChange) genDeleteSQL() (string, []any) { if r.tp != RowChangeDelete && r.tp != RowChangeUpdate { log.L().DPanic("illegal type for genDeleteSQL", zap.String("sourceTable", r.sourceTable.String()), @@ -307,7 +307,7 @@ func (r *RowChange) genDeleteSQL() (string, []interface{}) { return buf.String(), whereArgs } -func (r *RowChange) genUpdateSQL() (string, []interface{}) { +func (r *RowChange) genUpdateSQL() (string, []any) { if r.tp != RowChangeUpdate { log.L().DPanic("illegal type for genUpdateSQL", zap.String("sourceTable", r.sourceTable.String()), @@ -323,7 +323,7 @@ func (r *RowChange) genUpdateSQL() (string, []interface{}) { // Build target generated columns lower names set to accelerate following check generatedColumns := generatedColumnsNameSet(r.targetTableInfo.Columns) - args := make([]interface{}, 0, len(r.preValues)+len(r.postValues)) + args := make([]any, 0, len(r.preValues)+len(r.postValues)) writtenFirstCol := false for i, col := range r.sourceTableInfo.Columns { if _, ok := generatedColumns[col.Name.L]; ok { @@ -346,7 +346,7 @@ func (r *RowChange) genUpdateSQL() (string, []interface{}) { return buf.String(), args } -func (r *RowChange) genInsertSQL(tp DMLType) (string, []interface{}) { +func (r *RowChange) genInsertSQL(tp DMLType) (string, []any) { return GenInsertSQL(tp, r) } @@ -382,7 +382,7 @@ func (t DMLType) String() string { } // GenSQL generated a DML SQL for this RowChange. -func (r *RowChange) GenSQL(tp DMLType) (string, []interface{}) { +func (r *RowChange) GenSQL(tp DMLType) (string, []any) { switch tp { case DMLInsert, DMLReplace, DMLInsertOnDuplicateUpdate: return r.genInsertSQL(tp) @@ -398,19 +398,19 @@ func (r *RowChange) GenSQL(tp DMLType) (string, []interface{}) { } // GetPreValues is only used in tests. -func (r *RowChange) GetPreValues() []interface{} { +func (r *RowChange) GetPreValues() []any { return r.preValues } // GetPostValues is only used in tests. -func (r *RowChange) GetPostValues() []interface{} { +func (r *RowChange) GetPostValues() []any { return r.postValues } // RowValues returns the values of this row change // for INSERT and UPDATE, it is the post values. // for DELETE, it is the pre values. -func (r *RowChange) RowValues() []interface{} { +func (r *RowChange) RowValues() []any { switch r.tp { case RowChangeInsert, RowChangeUpdate: return r.postValues diff --git a/pkg/sqlmodel/row_change_test.go b/pkg/sqlmodel/row_change_test.go index a87e10dcd3..d09720bb95 100644 --- a/pkg/sqlmodel/row_change_test.go +++ b/pkg/sqlmodel/row_change_test.go @@ -68,8 +68,8 @@ func TestNewRowChange(t *testing.T) { expected := &RowChange{ sourceTable: source, targetTable: target, - preValues: []interface{}{1, 2}, - postValues: []interface{}{1, 3}, + preValues: []any{1, 2}, + postValues: []any{1, 3}, sourceTableInfo: sourceTI, targetTableInfo: targetTI, tiSessionCtx: tiSession, @@ -77,7 +77,7 @@ func TestNewRowChange(t *testing.T) { whereHandle: nil, } - actual := NewRowChange(source, target, []interface{}{1, 2}, []interface{}{1, 3}, sourceTI, targetTI, tiSession) + actual := NewRowChange(source, target, []any{1, 2}, []any{1, 3}, sourceTI, targetTI, tiSession) require.Equal(t, expected, actual) actual.lazyInitWhereHandle() @@ -89,18 +89,18 @@ func TestNewRowChange(t *testing.T) { expected.targetTableInfo = expected.sourceTableInfo expected.tiSessionCtx = utils.ZeroSessionCtx expected.whereHandle = nil - actual = NewRowChange(source, nil, []interface{}{1, 2}, []interface{}{1, 3}, sourceTI, nil, nil) + actual = NewRowChange(source, nil, []any{1, 2}, []any{1, 3}, sourceTI, nil, nil) require.Equal(t, expected, actual) } func (s *dpanicSuite) TestRowChangeType() { - change := &RowChange{preValues: []interface{}{1}} + change := &RowChange{preValues: []any{1}} change.calculateType() s.Equal(RowChangeDelete, change.tp) - change = &RowChange{preValues: []interface{}{1}, postValues: []interface{}{2}} + change = &RowChange{preValues: []any{1}, postValues: []any{2}} change.calculateType() s.Equal(RowChangeUpdate, change.tp) - change = &RowChange{postValues: []interface{}{1}} + change = &RowChange{postValues: []any{1}} change.calculateType() s.Equal(RowChangeInsert, change.tp) @@ -117,60 +117,60 @@ func (s *dpanicSuite) TestGenDelete() { cases := []struct { sourceCreateSQL string targetCreateSQL string - preValues []interface{} + preValues []any expectedSQL string - expectedArgs []interface{} + expectedArgs []any }{ { "CREATE TABLE tb1 (id INT PRIMARY KEY, name INT)", "CREATE TABLE tb2 (id INT PRIMARY KEY, name INT, extra VARCHAR(20))", - []interface{}{1, 2}, + []any{1, 2}, "DELETE FROM `db`.`tb2` WHERE `id` = ? LIMIT 1", - []interface{}{1}, + []any{1}, }, { "CREATE TABLE tb1 (c INT, c2 INT UNIQUE)", "CREATE TABLE tb2 (c INT, c2 INT UNIQUE)", - []interface{}{1, 2}, + []any{1, 2}, "DELETE FROM `db`.`tb2` WHERE `c2` = ? LIMIT 1", - []interface{}{2}, + []any{2}, }, // next 2 cases test NULL value { "CREATE TABLE tb1 (c INT, c2 INT UNIQUE)", "CREATE TABLE tb2 (c INT, c2 INT UNIQUE)", - []interface{}{1, nil}, + []any{1, nil}, "DELETE FROM `db`.`tb2` WHERE `c` = ? AND `c2` IS ? LIMIT 1", - []interface{}{1, nil}, + []any{1, nil}, }, { "CREATE TABLE tb1 (c INT, c2 INT)", "CREATE TABLE tb2 (c INT, c2 INT)", - []interface{}{1, nil}, + []any{1, nil}, "DELETE FROM `db`.`tb2` WHERE `c` = ? AND `c2` IS ? LIMIT 1", - []interface{}{1, nil}, + []any{1, nil}, }, // next 2 cases test using downstream table to generate WHERE { "CREATE TABLE tb1 (id INT PRIMARY KEY, user_id INT NOT NULL UNIQUE)", "CREATE TABLE tb2 (new_id INT PRIMARY KEY, id INT, user_id INT NOT NULL UNIQUE)", - []interface{}{1, 2}, + []any{1, 2}, "DELETE FROM `db`.`tb2` WHERE `user_id` = ? LIMIT 1", - []interface{}{2}, + []any{2}, }, { "CREATE TABLE tb1 (id INT PRIMARY KEY, c2 INT)", "CREATE TABLE tb2 (new_id INT PRIMARY KEY, id INT, c2 INT)", - []interface{}{1, 2}, + []any{1, 2}, "DELETE FROM `db`.`tb2` WHERE `id` = ? AND `c2` = ? LIMIT 1", - []interface{}{1, 2}, + []any{1, 2}, }, } @@ -185,12 +185,12 @@ func (s *dpanicSuite) TestGenDelete() { // a RowChangeUpdate can still generate DELETE SQL sourceTI := mockTableInfo(s.T(), "CREATE TABLE tb1 (id INT PRIMARY KEY, name INT)") - change := NewRowChange(source, nil, []interface{}{1, 2}, []interface{}{3, 4}, sourceTI, nil, nil) + change := NewRowChange(source, nil, []any{1, 2}, []any{3, 4}, sourceTI, nil, nil) sql, args := change.GenSQL(DMLDelete) s.Equal("DELETE FROM `db`.`tb1` WHERE `id` = ? LIMIT 1", sql) - s.Equal([]interface{}{1}, args) + s.Equal([]any{1}, args) - change = NewRowChange(source, nil, nil, []interface{}{3, 4}, sourceTI, nil, nil) + change = NewRowChange(source, nil, nil, []any{3, 4}, sourceTI, nil, nil) s.Panics(func() { change.GenSQL(DMLDelete) }) @@ -203,57 +203,57 @@ func (s *dpanicSuite) TestGenUpdate() { cases := []struct { sourceCreateSQL string targetCreateSQL string - preValues []interface{} - postValues []interface{} + preValues []any + postValues []any expectedSQL string - expectedArgs []interface{} + expectedArgs []any }{ { "CREATE TABLE tb1 (id INT PRIMARY KEY, name INT)", "CREATE TABLE tb2 (id INT PRIMARY KEY, name INT, extra VARCHAR(20))", - []interface{}{1, 2}, - []interface{}{3, 4}, + []any{1, 2}, + []any{3, 4}, "UPDATE `db`.`tb2` SET `id` = ?, `name` = ? WHERE `id` = ? LIMIT 1", - []interface{}{3, 4, 1}, + []any{3, 4, 1}, }, { "CREATE TABLE tb1 (id INT UNIQUE, name INT)", "CREATE TABLE tb2 (id INT UNIQUE, name INT)", - []interface{}{nil, 2}, - []interface{}{3, 4}, + []any{nil, 2}, + []any{3, 4}, "UPDATE `db`.`tb2` SET `id` = ?, `name` = ? WHERE `id` IS ? AND `name` = ? LIMIT 1", - []interface{}{3, 4, nil, 2}, + []any{3, 4, nil, 2}, }, { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT)", "CREATE TABLE tb2 (c INT, c2 INT)", - []interface{}{1, 2}, - []interface{}{3, 4}, + []any{1, 2}, + []any{3, 4}, "UPDATE `db`.`tb2` SET `c` = ?, `c2` = ? WHERE `c` = ? AND `c2` = ? LIMIT 1", - []interface{}{3, 4, 1, 2}, + []any{3, 4, 1, 2}, }, // next 2 cases test generated column { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT AS (c+1))", "CREATE TABLE tb2 (c INT PRIMARY KEY, c2 INT AS (c+1))", - []interface{}{1, 2}, - []interface{}{3, 4}, + []any{1, 2}, + []any{3, 4}, "UPDATE `db`.`tb2` SET `c` = ? WHERE `c` = ? LIMIT 1", - []interface{}{3, 1}, + []any{3, 1}, }, { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT AS (c+1))", "CREATE TABLE tb2 (c INT PRIMARY KEY, c2 INT)", - []interface{}{1, 2}, - []interface{}{3, 4}, + []any{1, 2}, + []any{3, 4}, "UPDATE `db`.`tb2` SET `c` = ?, `c2` = ? WHERE `c` = ? LIMIT 1", - []interface{}{3, 4, 1}, + []any{3, 4, 1}, }, } @@ -267,7 +267,7 @@ func (s *dpanicSuite) TestGenUpdate() { } sourceTI := mockTableInfo(s.T(), "CREATE TABLE tb1 (id INT PRIMARY KEY, name INT)") - change := NewRowChange(source, nil, nil, []interface{}{3, 4}, sourceTI, nil, nil) + change := NewRowChange(source, nil, nil, []any{3, 4}, sourceTI, nil, nil) s.Panics(func() { change.GenSQL(DMLUpdate) }) @@ -281,24 +281,24 @@ func (s *dpanicSuite) TestExpressionIndex() { UNIQUE KEY j_index ((cast(json_extract(j,'$[*]') as signed array)), id) )` ti := mockTableInfo(s.T(), sql) - change := NewRowChange(source, nil, nil, []interface{}{1, `[1,2,3]`}, ti, nil, nil) + change := NewRowChange(source, nil, nil, []any{1, `[1,2,3]`}, ti, nil, nil) sql, args := change.GenSQL(DMLInsert) s.Equal("INSERT INTO `db`.`tb1` (`id`,`j`) VALUES (?,?)", sql) - s.Equal([]interface{}{1, `[1,2,3]`}, args) + s.Equal([]any{1, `[1,2,3]`}, args) require.Equal(s.T(), 2, change.ColumnCount()) keys := change.CausalityKeys() // TODO: need change it after future fix require.Equal(s.T(), []string{"1.id.db.tb1"}, keys) - change2 := NewRowChange(source, nil, []interface{}{1, `[1,2,3]`}, []interface{}{1, `[1,2,3,4]`}, ti, nil, nil) + change2 := NewRowChange(source, nil, []any{1, `[1,2,3]`}, []any{1, `[1,2,3,4]`}, ti, nil, nil) sql, args = change2.GenSQL(DMLUpdate) s.Equal("UPDATE `db`.`tb1` SET `id` = ?, `j` = ? WHERE `id` = ? LIMIT 1", sql) - s.Equal([]interface{}{1, `[1,2,3,4]`, 1}, args) + s.Equal([]any{1, `[1,2,3,4]`, 1}, args) change2.Reduce(change) sql, args = change2.GenSQL(DMLInsert) s.Equal("INSERT INTO `db`.`tb1` (`id`,`j`) VALUES (?,?)", sql) - s.Equal([]interface{}{1, `[1,2,3,4]`}, args) + s.Equal([]any{1, `[1,2,3,4]`}, args) } func TestGenInsert(t *testing.T) { @@ -310,43 +310,43 @@ func TestGenInsert(t *testing.T) { cases := []struct { sourceCreateSQL string targetCreateSQL string - postValues []interface{} + postValues []any expectedInsertSQL string expectedReplaceSQL string expectedInsertOnDupSQL string - expectedArgs []interface{} + expectedArgs []any }{ { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT)", "CREATE TABLE tb2 (c INT PRIMARY KEY, c2 INT, extra VARCHAR(20))", - []interface{}{1, 2}, + []any{1, 2}, "INSERT INTO `db`.`tb2` (`c`,`c2`) VALUES (?,?)", "REPLACE INTO `db`.`tb2` (`c`,`c2`) VALUES (?,?)", "INSERT INTO `db`.`tb2` (`c`,`c2`) VALUES (?,?) ON DUPLICATE KEY UPDATE `c`=VALUES(`c`),`c2`=VALUES(`c2`)", - []interface{}{1, 2}, + []any{1, 2}, }, // next 2 cases test generated column { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT AS (c+1))", "CREATE TABLE tb2 (c INT PRIMARY KEY, c2 INT AS (c+1))", - []interface{}{1, 2}, + []any{1, 2}, "INSERT INTO `db`.`tb2` (`c`) VALUES (?)", "REPLACE INTO `db`.`tb2` (`c`) VALUES (?)", "INSERT INTO `db`.`tb2` (`c`) VALUES (?) ON DUPLICATE KEY UPDATE `c`=VALUES(`c`)", - []interface{}{1}, + []any{1}, }, { "CREATE TABLE tb1 (c INT PRIMARY KEY, c2 INT AS (c+1))", "CREATE TABLE tb2 (c INT PRIMARY KEY, c2 INT)", - []interface{}{1, 2}, + []any{1, 2}, "INSERT INTO `db`.`tb2` (`c`,`c2`) VALUES (?,?)", "REPLACE INTO `db`.`tb2` (`c`,`c2`) VALUES (?,?)", "INSERT INTO `db`.`tb2` (`c`,`c2`) VALUES (?,?) ON DUPLICATE KEY UPDATE `c`=VALUES(`c`),`c2`=VALUES(`c2`)", - []interface{}{1, 2}, + []any{1, 2}, }, } diff --git a/pkg/sqlmodel/utils.go b/pkg/sqlmodel/utils.go index 75a69cdc9f..eb04d45082 100644 --- a/pkg/sqlmodel/utils.go +++ b/pkg/sqlmodel/utils.go @@ -23,10 +23,10 @@ import ( func getColsAndValuesOfIdx( columns []*timodel.ColumnInfo, indexColumns *timodel.IndexInfo, - data []interface{}, -) ([]*timodel.ColumnInfo, []interface{}) { + data []any, +) ([]*timodel.ColumnInfo, []any) { cols := make([]*timodel.ColumnInfo, 0, len(indexColumns.Columns)) - values := make([]interface{}, 0, len(indexColumns.Columns)) + values := make([]any, 0, len(indexColumns.Columns)) for _, col := range indexColumns.Columns { cols = append(cols, columns[col.Offset]) values = append(values, data[col.Offset]) @@ -40,7 +40,7 @@ func valuesHolder(n int) string { var builder strings.Builder builder.Grow((n-1)*2 + 3) builder.WriteByte('(') - for i := 0; i < n; i++ { + for i := range n { if i > 0 { builder.WriteString(",") } @@ -62,7 +62,7 @@ func generatedColumnsNameSet(columns []*timodel.ColumnInfo) map[string]struct{} } // ColValAsStr convert column value as string -func ColValAsStr(v interface{}) string { +func ColValAsStr(v any) string { switch dv := v.(type) { case []byte: return string(dv) diff --git a/pkg/sqlmodel/where_handle.go b/pkg/sqlmodel/where_handle.go index 740524f52a..be0e2a44d3 100644 --- a/pkg/sqlmodel/where_handle.go +++ b/pkg/sqlmodel/where_handle.go @@ -130,7 +130,7 @@ func allColsNotNull(idx *model.IndexInfo, cols []*model.ColumnInfo) bool { // - an UNIQUE index whose columns are all NOT NULL, or // - an UNIQUE index and the data are all NOT NULL. // For the last case, last used index is swapped to front. -func (h *WhereHandle) getWhereIdxByData(data []interface{}) *model.IndexInfo { +func (h *WhereHandle) getWhereIdxByData(data []any) *model.IndexInfo { if h == nil { log.L().DPanic("WhereHandle is nil") return nil diff --git a/pkg/sqlmodel/where_handle_test.go b/pkg/sqlmodel/where_handle_test.go index bf1f57d409..4972a0ea75 100644 --- a/pkg/sqlmodel/where_handle_test.go +++ b/pkg/sqlmodel/where_handle_test.go @@ -202,16 +202,16 @@ CREATE TABLE t ( require.NoError(t, err) handle := GetWhereHandle(ti, ti) - idx := handle.getWhereIdxByData([]interface{}{nil, 2, 3, 4}) + idx := handle.getWhereIdxByData([]any{nil, 2, 3, 4}) require.Equal(t, "idx2", idx.Name.L) require.Equal(t, idx, handle.UniqueIdxs[0]) // last used index is moved to front - idx = handle.getWhereIdxByData([]interface{}{1, 2, 3, nil}) + idx = handle.getWhereIdxByData([]any{1, 2, 3, nil}) require.Equal(t, "idx1", idx.Name.L) require.Equal(t, idx, handle.UniqueIdxs[0]) // no index available - idx = handle.getWhereIdxByData([]interface{}{1, nil, 3, nil}) + idx = handle.getWhereIdxByData([]any{1, nil, 3, nil}) require.Nil(t, idx) } diff --git a/pkg/tcpserver/tcp_server_test.go b/pkg/tcpserver/tcp_server_test.go index 5d53a13591..220238e7f5 100644 --- a/pkg/tcpserver/tcp_server_test.go +++ b/pkg/tcpserver/tcp_server_test.go @@ -51,20 +51,16 @@ func TestTCPServerInsecureHTTP1(t *testing.T) { var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx) require.Error(t, err) require.Regexp(t, ".*ErrTCPServerClosed.*", err.Error()) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { testWithHTTPWorkload(ctx, t, server, addr, &security.Credential{}) cancel() - }() + }) wg.Wait() } @@ -88,20 +84,16 @@ func TestTCPServerTLSHTTP1(t *testing.T) { var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx) require.Error(t, err) require.Regexp(t, ".*ErrTCPServerClosed.*", err.Error()) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer cancel() testWithHTTPWorkload(ctx, t, server, addr, makeCredential4Testing(t)) - }() + }) wg.Wait() } @@ -124,20 +116,16 @@ func TestTCPServerInsecureGrpc(t *testing.T) { var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx) require.Error(t, err) require.Regexp(t, ".*ErrTCPServerClosed.*", err.Error()) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { testWithGrpcWorkload(ctx, t, server, addr, &security.Credential{}) cancel() - }() + }) wg.Wait() } @@ -161,20 +149,16 @@ func TestTCPServerTLSGrpc(t *testing.T) { var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx) require.Error(t, err) require.Regexp(t, ".*ErrTCPServerClosed.*", err.Error()) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { testWithGrpcWorkload(ctx, t, server, addr, makeCredential4Testing(t)) cancel() - }() + }) wg.Wait() } @@ -236,9 +220,7 @@ func testWithHTTPWorkload(_ context.Context, t *testing.T, server TCPServer, add var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := httpServer.Serve(server.HTTP1Listener()) if err != nil && err != http.ErrServerClosed { require.FailNow(t, @@ -246,7 +228,7 @@ func testWithHTTPWorkload(_ context.Context, t *testing.T, server TCPServer, add "%d", err.Error()) } - }() + }) scheme := "http" if credentials.IsTLSEnabled() { @@ -281,12 +263,10 @@ func testWithGrpcWorkload(ctx context.Context, t *testing.T, server TCPServer, a var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := grpcServer.Serve(server.GrpcListener()) require.NoError(t, err) - }() + }) var conn *grpc.ClientConn if credentials.IsTLSEnabled() { @@ -305,7 +285,7 @@ func testWithGrpcWorkload(ctx context.Context, t *testing.T, server TCPServer, a client := grpcTestingProto.NewTestServiceClient(conn) - for i := 0; i < 5; i++ { + for i := range 5 { result, err := client.Ping(ctx, &grpcTestingProto.PingRequest{ Value: fmt.Sprintf("%d", i), }) @@ -313,15 +293,13 @@ func testWithGrpcWorkload(ctx context.Context, t *testing.T, server TCPServer, a require.Equal(t, fmt.Sprintf("%d", i), result.Value) } - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer grpcServer.GracefulStop() stream, err := client.PingStream(ctx) require.NoError(t, err) - for i := 0; i < 10; i++ { + for i := range 10 { err := stream.Send(&grpcTestingProto.PingRequest{ Value: fmt.Sprintf("%d", i), }) @@ -331,7 +309,7 @@ func testWithGrpcWorkload(ctx context.Context, t *testing.T, server TCPServer, a require.NoError(t, err) require.Equal(t, fmt.Sprintf("%d", i), received.Value) } - }() + }) wg.Wait() } @@ -348,13 +326,11 @@ func TestTcpServerClose(t *testing.T) { require.NoError(t, err) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.Run(ctx) require.Error(t, err) require.Regexp(t, ".*ErrTCPServerClosed.*", err.Error()) - }() + }) httpServer := &http.Server{} http.HandleFunc("/", func(writer http.ResponseWriter, _ *http.Request) { @@ -366,13 +342,11 @@ func TestTcpServerClose(t *testing.T) { http.DefaultServeMux = http.NewServeMux() }() - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := httpServer.Serve(server.HTTP1Listener()) require.Error(t, err) require.Regexp(t, ".*mux: server closed.*", err.Error()) - }() + }) cli, err := httputil.NewClient(&security.Credential{}) require.NoError(t, err) @@ -386,7 +360,7 @@ func TestTcpServerClose(t *testing.T) { require.Equal(t, 200, resp.StatusCode) // Close should be idempotent. - for i := 0; i < 3; i++ { + for range 3 { err := server.Close() require.NoError(t, err) } diff --git a/pkg/upstream/manager.go b/pkg/upstream/manager.go index 93c9bf7f57..459377c380 100644 --- a/pkg/upstream/manager.go +++ b/pkg/upstream/manager.go @@ -187,7 +187,7 @@ func (m *Manager) Get(upstreamID uint64) (*Upstream, bool) { // Please make sure it will only be called once when capture exits. func (m *Manager) Close() { m.cancel() - m.ups.Range(func(k, v interface{}) bool { + m.ups.Range(func(k, v any) bool { v.(*Upstream).Close() m.ups.Delete(k) return true @@ -197,7 +197,7 @@ func (m *Manager) Close() { // Visit on each upstream, return error on the first func (m *Manager) Visit(visitor func(up *Upstream) error) error { var err error - m.ups.Range(func(k, v interface{}) bool { + m.ups.Range(func(k, v any) bool { err = visitor(v.(*Upstream)) return err == nil }) @@ -224,7 +224,7 @@ func (m *Manager) Tick(ctx context.Context, defer m.mu.Unlock() var err error - m.ups.Range(func(k, v interface{}) bool { + m.ups.Range(func(k, v any) bool { select { case <-ctx.Done(): err = ctx.Err() diff --git a/pkg/upstream/upstream.go b/pkg/upstream/upstream.go index d169c78126..74817c21d9 100644 --- a/pkg/upstream/upstream.go +++ b/pkg/upstream/upstream.go @@ -222,11 +222,9 @@ func initUpstream(ctx context.Context, up *Upstream, cfg CaptureTopologyCfg) err return errors.Trace(err) } - up.wg.Add(1) - go func() { - defer up.wg.Done() + up.wg.Go(func() { up.PDClock.Run(ctx) - }() + }) log.Info("upstream initialize successfully", zap.Uint64("upstreamID", up.ID)) atomic.StoreInt32(&up.status, normal) diff --git a/pkg/upstream/upstream_test.go b/pkg/upstream/upstream_test.go index ebcf9728fc..1004a38dd1 100644 --- a/pkg/upstream/upstream_test.go +++ b/pkg/upstream/upstream_test.go @@ -14,7 +14,6 @@ package upstream import ( - "context" "fmt" "strconv" "sync" @@ -90,8 +89,7 @@ func TestTrySetIdleTime(t *testing.T) { func TestRegisterTopo(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() clientURL, etcdServer, err := etcd.SetupEmbedEtcd(t.TempDir()) defer etcdServer.Close() @@ -144,8 +142,7 @@ func TestRegisterTopo(t *testing.T) { func TestVerify(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() clientURL, etcdServer, err := etcd.SetupEmbedEtcd(t.TempDir()) defer etcdServer.Close() diff --git a/pkg/util/atomic_test.go b/pkg/util/atomic_test.go index 900720ebb5..777ec5adf0 100644 --- a/pkg/util/atomic_test.go +++ b/pkg/util/atomic_test.go @@ -57,10 +57,8 @@ func TestMustCompareAndIncrease(t *testing.T) { doIncrease() }() - wg.Add(1) // Test target never decrease. - go func() { - defer wg.Done() + wg.Go(func() { for { select { case <-ctx.Done(): @@ -71,7 +69,7 @@ func TestMustCompareAndIncrease(t *testing.T) { require.Greater(t, target.Load(), v) } } - }() + }) cancel() wg.Wait() diff --git a/pkg/util/json_writer.go b/pkg/util/json_writer.go index c30f997753..d3678bc917 100644 --- a/pkg/util/json_writer.go +++ b/pkg/util/json_writer.go @@ -27,7 +27,7 @@ var jsonAPI = jsoniter.Config{ }.Froze() var jWriterPool = sync.Pool{ - New: func() interface{} { + New: func() any { return &JSONWriter{} }, } diff --git a/pkg/util/seahash/seahash_test.go b/pkg/util/seahash/seahash_test.go index f4c6a78dfd..47acd460d2 100644 --- a/pkg/util/seahash/seahash_test.go +++ b/pkg/util/seahash/seahash_test.go @@ -33,7 +33,7 @@ func ExampleSum64() { func TestRandom(t *testing.T) { expected := "d30e85ff891306b8" str := []byte("abcdegfhijklmnabcdegfhijklmnabcdegfhijklmn") - for i := 0; i < 1000; i++ { + for i := range 1000 { r := rand.NewSource(int64(i)) s := str h := New() diff --git a/pkg/util/test_helper_test.go b/pkg/util/test_helper_test.go index 75169afe32..20bd6250fd 100644 --- a/pkg/util/test_helper_test.go +++ b/pkg/util/test_helper_test.go @@ -55,7 +55,7 @@ func TestHandleErr(t *testing.T) { count int32 ) errg := HandleErrWithErrGroup(ctx, errCh, func(e error) { atomic.AddInt32(&count, 1) }) - for i := 0; i < 5; i++ { + for range 5 { errCh <- errors.New("test error") } require.True(t, WaitSomething(5, time.Millisecond*10, func() bool { return atomic.LoadInt32(&count) == int32(5) })) diff --git a/pkg/uuid/uuid_test.go b/pkg/uuid/uuid_test.go index 2cb4672b2d..dd1e5057f3 100644 --- a/pkg/uuid/uuid_test.go +++ b/pkg/uuid/uuid_test.go @@ -47,7 +47,7 @@ func TestConstGenerator(t *testing.T) { uid := "const-uuid" gen := NewConstGenerator(uid) - for i := 0; i < 3; i++ { + for range 3 { require.Equal(t, uid, gen.NewString()) } } diff --git a/pkg/version/check_test.go b/pkg/version/check_test.go index 66fbdf4a33..2d0ed95771 100644 --- a/pkg/version/check_test.go +++ b/pkg/version/check_test.go @@ -54,7 +54,7 @@ func (m *mockPDClient) ServeHTTP(resp http.ResponseWriter, _ *http.Request) { } if m.getPDVersion != nil { - _, _ = resp.Write([]byte(fmt.Sprintf(`{"version":"%s"}`, m.getPDVersion()))) + _, _ = resp.Write(fmt.Appendf(nil, `{"version":"%s"}`, m.getPDVersion())) } } @@ -74,7 +74,7 @@ func TestCheckClusterVersion(t *testing.T) { defer srv.Close() cli, err := httputil.NewClient(nil) require.Nil(t, err) - for i := 0; i < 20; i++ { + for i := range 20 { time.Sleep(100 * time.Millisecond) resp, err := cli.Get(context.Background(), pdAddr) if err == nil { diff --git a/pkg/workerpool/async_pool_test.go b/pkg/workerpool/async_pool_test.go index 68ca2c015d..c4c2ce6dd3 100644 --- a/pkg/workerpool/async_pool_test.go +++ b/pkg/workerpool/async_pool_test.go @@ -40,7 +40,7 @@ func TestBasic(t *testing.T) { var sum int32 var wg sync.WaitGroup - for i := 0; i < 100; i++ { + for i := range 100 { wg.Add(1) finalI := i err := pool.Go(ctx, func() { @@ -70,7 +70,7 @@ func TestEventuallyRun(t *testing.T) { pool := newDefaultAsyncPoolImpl(4) errg.Go(func() error { defer cancelLoop() - for i := 0; i < 10; i++ { + for range 10 { log.Info("running pool") err := runForDuration(ctx, time.Millisecond*500, func(ctx context.Context) error { return pool.Run(ctx) diff --git a/pkg/workerpool/pool.go b/pkg/workerpool/pool.go index 8558c2c70a..3ba8c63d7e 100644 --- a/pkg/workerpool/pool.go +++ b/pkg/workerpool/pool.go @@ -24,7 +24,7 @@ type WorkerPool interface { // RegisterEvent returns a handle that can be used to trigger the execution of `f`. // `f` will be called with a context that is a child of the context with which Run is called. // TODO more reasonable usage of contexts, potentially involving context merging. - RegisterEvent(f func(ctx context.Context, event interface{}) error) EventHandle + RegisterEvent(f func(ctx context.Context, event any) error) EventHandle // Run runs the WorkerPool. // Internally several Goroutines are spawned. @@ -39,10 +39,10 @@ type EventHandle interface { // Note: events are always processed in the order they are added. // Unregistering the EventHandle MAY CAUSE EVENT LOSSES. But for an event lost, any event after it is guaranteed to be lost too. // Cancelling `ctx` here will cancel the on-going or next execution of the event. - AddEvent(ctx context.Context, event interface{}) error + AddEvent(ctx context.Context, event any) error // AddEvents is like AddEvent but retrieves a slice instead of an object. - AddEvents(ctx context.Context, events []interface{}) error + AddEvents(ctx context.Context, events []any) error // SetTimer is used to provide a function that is periodic called, as long as the EventHandle has not been unregistered. // The current implementation uses as the base clock source a ticker whose interval is the const workerPoolDefaultClockSourceInterval. diff --git a/pkg/workerpool/pool_impl.go b/pkg/workerpool/pool_impl.go index 0a10addebb..7a75644159 100644 --- a/pkg/workerpool/pool_impl.go +++ b/pkg/workerpool/pool_impl.go @@ -49,7 +49,7 @@ func NewDefaultWorkerPool(numWorkers int) WorkerPool { func newDefaultPoolImpl(hasher Hasher, numWorkers int) *defaultPoolImpl { workers := make([]*worker, numWorkers) - for i := 0; i < numWorkers; i++ { + for i := range numWorkers { workers[i] = newWorker() } return &defaultPoolImpl{ @@ -75,7 +75,7 @@ func (p *defaultPoolImpl) Run(ctx context.Context) error { return errg.Wait() } -func (p *defaultPoolImpl) RegisterEvent(f func(ctx context.Context, event interface{}) error) EventHandle { +func (p *defaultPoolImpl) RegisterEvent(f func(ctx context.Context, event any) error) EventHandle { handler := &defaultEventHandle{ f: f, errCh: make(chan error, 1), @@ -99,7 +99,7 @@ const ( type defaultEventHandle struct { // the function to be run each time the event is triggered - f func(ctx context.Context, event interface{}) error + f func(ctx context.Context, event any) error // must be accessed atomically status handleStatus // channel for the error returned by f @@ -126,7 +126,7 @@ type defaultEventHandle struct { errorHandler func(err error) } -func (h *defaultEventHandle) AddEvent(ctx context.Context, event interface{}) error { +func (h *defaultEventHandle) AddEvent(ctx context.Context, event any) error { status := atomic.LoadInt32(&h.status) if status != handleRunning { return cerrors.ErrWorkerPoolHandleCancelled.GenWithStackByArgs() @@ -149,7 +149,7 @@ func (h *defaultEventHandle) AddEvent(ctx context.Context, event interface{}) er return nil } -func (h *defaultEventHandle) AddEvents(ctx context.Context, events []interface{}) error { +func (h *defaultEventHandle) AddEvents(ctx context.Context, events []any) error { status := atomic.LoadInt32(&h.status) if status != handleRunning { return cerrors.ErrWorkerPoolHandleCancelled.GenWithStackByArgs() diff --git a/pkg/workerpool/pool_test.go b/pkg/workerpool/pool_test.go index 5a0480dd15..2537921889 100644 --- a/pkg/workerpool/pool_test.go +++ b/pkg/workerpool/pool_test.go @@ -39,7 +39,7 @@ func TestTaskError(t *testing.T) { return pool.Run(ctx) }) - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { if event.(int) == 3 { return errors.New("test error") } @@ -49,16 +49,14 @@ func TestTaskError(t *testing.T) { }) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < 10; i++ { + wg.Go(func() { + for i := range 10 { err := handle.AddEvent(ctx, i) if err != nil { require.Regexp(t, ".*ErrWorkerPoolHandleCancelled.*", err) } } - }() + }) select { case <-ctx.Done(): @@ -86,7 +84,7 @@ func TestTimerError(t *testing.T) { }) counter := 0 - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { return nil }).SetTimer(ctx, time.Millisecond*200, func(ctx context.Context) error { if counter == 3 { @@ -117,7 +115,7 @@ func TestMultiError(t *testing.T) { return pool.Run(ctx) }) - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { if event.(int) >= 3 { return errors.New("test error") } @@ -125,16 +123,14 @@ func TestMultiError(t *testing.T) { }) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < 10; i++ { + wg.Go(func() { + for i := range 10 { err := handle.AddEvent(ctx, i) if err != nil { require.Regexp(t, ".*ErrWorkerPoolHandleCancelled.*", err) } } - }() + }) select { case <-ctx.Done(): @@ -162,7 +158,7 @@ func TestCancelHandle(t *testing.T) { }) var num int32 - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { atomic.StoreInt32(&num, int32(event.(int))) return nil }) @@ -234,7 +230,7 @@ func TestCancelTimer(t *testing.T) { _ = failpoint.Disable("github.com/pingcap/tiflow/pkg/workerpool/unregisterDelayPoint") }() - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { return nil }).SetTimer(ctx, 200*time.Millisecond, func(ctx context.Context) error { return nil @@ -270,7 +266,7 @@ func TestErrorAndCancelRace(t *testing.T) { }) var racedVar int - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { return errors.New("fake") }).OnExit(func(err error) { time.Sleep(100 * time.Millisecond) @@ -301,7 +297,7 @@ func TestTimer(t *testing.T) { time.Sleep(200 * time.Millisecond) - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { if event.(int) == 3 { return errors.New("test error") } @@ -343,10 +339,10 @@ func TestBasics(t *testing.T) { var wg sync.WaitGroup wg.Add(16) - for i := 0; i < 16; i++ { + for i := range 16 { finalI := i resultCh := make(chan int, 128) - handler := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handler := pool.RegisterEvent(func(ctx context.Context, event any) error { select { case <-ctx.Done(): return ctx.Err() @@ -357,7 +353,7 @@ func TestBasics(t *testing.T) { }) errg.Go(func() error { - for j := 0; j < 256; j++ { + for j := range 256 { err := handler.AddEvent(ctx, j) if err != nil { return errors.Trace(err) @@ -396,8 +392,7 @@ func TestBasics(t *testing.T) { // TestCancelByAddEventContext makes sure that the event handle can be cancelled by the context used // to call `AddEvent`. func TestCancelByAddEventContext(t *testing.T) { - poolCtx, poolCancel := context.WithCancel(context.Background()) - defer poolCancel() + poolCtx := t.Context() pool := newDefaultPoolImpl(&defaultHasher{}, 4) go func() { err := pool.Run(poolCtx) @@ -408,14 +403,14 @@ func TestCancelByAddEventContext(t *testing.T) { defer cancel() errg, ctx := errgroup.WithContext(ctx) - for i := 0; i < 8; i++ { - handler := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + for range 8 { + handler := pool.RegisterEvent(func(ctx context.Context, event any) error { <-ctx.Done() return ctx.Err() }) errg.Go(func() error { - for j := 0; j < 64; j++ { + for j := range 64 { err := handler.AddEvent(ctx, j) if err != nil { return nil @@ -441,8 +436,7 @@ func TestCancelByAddEventContext(t *testing.T) { } func TestGracefulUnregister(t *testing.T) { - poolCtx, poolCancel := context.WithCancel(context.Background()) - defer poolCancel() + poolCtx := t.Context() pool := newDefaultPoolImpl(&defaultHasher{}, 4) go func() { err := pool.Run(poolCtx) @@ -455,7 +449,7 @@ func TestGracefulUnregister(t *testing.T) { waitCh := make(chan struct{}) var lastEventIdx int64 - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { select { case <-ctx.Done(): return errors.Trace(ctx.Err()) @@ -469,9 +463,7 @@ func TestGracefulUnregister(t *testing.T) { }) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { var maxEventIdx int64 for i := int64(0); ; i++ { err := handle.AddEvent(ctx, i+1) @@ -486,7 +478,7 @@ func TestGracefulUnregister(t *testing.T) { require.Eventually(t, func() (success bool) { return atomic.LoadInt64(&lastEventIdx) == maxEventIdx }, time.Millisecond*500, time.Millisecond*10) - }() + }) time.Sleep(time.Millisecond * 200) go func() { @@ -504,8 +496,7 @@ func TestGracefulUnregister(t *testing.T) { } func TestGracefulUnregisterTimeout(t *testing.T) { - poolCtx, poolCancel := context.WithCancel(context.Background()) - defer poolCancel() + poolCtx := t.Context() pool := newDefaultPoolImpl(&defaultHasher{}, 4) go func() { err := pool.Run(poolCtx) @@ -517,7 +508,7 @@ func TestGracefulUnregisterTimeout(t *testing.T) { waitCh := make(chan struct{}) - handle := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handle := pool.RegisterEvent(func(ctx context.Context, event any) error { select { case <-waitCh: return nil @@ -573,14 +564,13 @@ func TestSynchronizeLog(t *testing.T) { // Benchmark workerpool with ping-pong workflow. // go test -benchmem -run='^$' -bench '^(BenchmarkWorkerpool)$' github.com/pingcap/tiflow/pkg/workerpool func BenchmarkWorkerpool(b *testing.B) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := b.Context() pool := newDefaultPoolImpl(&defaultHasher{}, 4) go func() { _ = pool.Run(ctx) }() ch := make(chan int) - handler := pool.RegisterEvent(func(ctx context.Context, event interface{}) error { + handler := pool.RegisterEvent(func(ctx context.Context, event any) error { ch <- event.(int) return nil }) From 0db8b57111ecb396a28763a417d1ce989306ad22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Tue, 16 Jun 2026 11:15:49 +0200 Subject: [PATCH 2/2] make fmt --- pkg/chdelay/channel_delayer_test.go | 1 - pkg/p2p/server_client_integration_test.go | 1 - 2 files changed, 2 deletions(-) diff --git a/pkg/chdelay/channel_delayer_test.go b/pkg/chdelay/channel_delayer_test.go index 9d657d5ba8..25fddba5fa 100644 --- a/pkg/chdelay/channel_delayer_test.go +++ b/pkg/chdelay/channel_delayer_test.go @@ -47,7 +47,6 @@ func testChannelDelayer(t *testing.T, delayBy time.Duration, count int) { }) wg.Go(func() { - counter := 0 for ts := range delayer.Out() { require.Greater(t, time.Since(ts), delayBy) diff --git a/pkg/p2p/server_client_integration_test.go b/pkg/p2p/server_client_integration_test.go index 3560b94ba1..8e9a51c8b0 100644 --- a/pkg/p2p/server_client_integration_test.go +++ b/pkg/p2p/server_client_integration_test.go @@ -404,7 +404,6 @@ func TestTopicCongested(t *testing.T) { var lastSeq Seq wg.Go(func() { - for range 100 { seq, err := client.SendMessage(ctx, "test-topic-1", &testTopicContent{}) require.NoError(t, err)