go.temporal.io/server@v1.23.0/common/namespace/dlq_message_handler_test.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package namespace
    26  
    27  import (
    28  	"context"
    29  	"fmt"
    30  	"testing"
    31  
    32  	"github.com/golang/mock/gomock"
    33  	"github.com/pborman/uuid"
    34  	"github.com/stretchr/testify/require"
    35  	"github.com/stretchr/testify/suite"
    36  
    37  	enumsspb "go.temporal.io/server/api/enums/v1"
    38  	replicationspb "go.temporal.io/server/api/replication/v1"
    39  	"go.temporal.io/server/common/log"
    40  	"go.temporal.io/server/common/persistence"
    41  )
    42  
    43  type (
    44  	dlqMessageHandlerSuite struct {
    45  		suite.Suite
    46  
    47  		*require.Assertions
    48  		controller *gomock.Controller
    49  
    50  		mockReplicationTaskExecutor *MockReplicationTaskExecutor
    51  		mockReplicationQueue        *persistence.MockNamespaceReplicationQueue
    52  		dlqMessageHandler           *dlqMessageHandlerImpl
    53  	}
    54  )
    55  
    56  func TestDLQMessageHandlerSuite(t *testing.T) {
    57  	s := new(dlqMessageHandlerSuite)
    58  	suite.Run(t, s)
    59  }
    60  
    61  func (s *dlqMessageHandlerSuite) SetupSuite() {
    62  }
    63  
    64  func (s *dlqMessageHandlerSuite) TearDownSuite() {
    65  
    66  }
    67  
    68  func (s *dlqMessageHandlerSuite) SetupTest() {
    69  	s.Assertions = require.New(s.T())
    70  	s.controller = gomock.NewController(s.T())
    71  
    72  	logger := log.NewTestLogger()
    73  	s.mockReplicationTaskExecutor = NewMockReplicationTaskExecutor(s.controller)
    74  	s.mockReplicationQueue = persistence.NewMockNamespaceReplicationQueue(s.controller)
    75  
    76  	s.dlqMessageHandler = NewDLQMessageHandler(
    77  		s.mockReplicationTaskExecutor,
    78  		s.mockReplicationQueue,
    79  		logger,
    80  	).(*dlqMessageHandlerImpl)
    81  }
    82  
    83  func (s *dlqMessageHandlerSuite) TearDownTest() {
    84  }
    85  
    86  func (s *dlqMessageHandlerSuite) TestReadMessages() {
    87  	ackLevel := int64(10)
    88  	lastMessageID := int64(20)
    89  	pageSize := 100
    90  	pageToken := []byte{}
    91  
    92  	tasks := []*replicationspb.ReplicationTask{
    93  		{
    94  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
    95  			SourceTaskId: 1,
    96  		},
    97  	}
    98  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
    99  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   100  		Return(tasks, nil, nil)
   101  
   102  	resp, token, err := s.dlqMessageHandler.Read(context.Background(), lastMessageID, pageSize, pageToken)
   103  
   104  	s.NoError(err)
   105  	s.Equal(tasks, resp)
   106  	s.Nil(token)
   107  }
   108  
   109  func (s *dlqMessageHandlerSuite) TestReadMessages_ThrowErrorOnGetDLQAckLevel() {
   110  	lastMessageID := int64(20)
   111  	pageSize := 100
   112  	pageToken := []byte{}
   113  
   114  	tasks := []*replicationspb.ReplicationTask{
   115  		{
   116  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   117  			SourceTaskId: 1,
   118  		},
   119  	}
   120  	testError := fmt.Errorf("test")
   121  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(int64(-1), testError)
   122  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   123  		Return(tasks, nil, nil).Times(0)
   124  
   125  	_, _, err := s.dlqMessageHandler.Read(context.Background(), lastMessageID, pageSize, pageToken)
   126  
   127  	s.Equal(testError, err)
   128  }
   129  
   130  func (s *dlqMessageHandlerSuite) TestReadMessages_ThrowErrorOnReadMessages() {
   131  	ackLevel := int64(10)
   132  	lastMessageID := int64(20)
   133  	pageSize := 100
   134  	pageToken := []byte{}
   135  
   136  	testError := fmt.Errorf("test")
   137  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   138  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   139  		Return(nil, nil, testError)
   140  
   141  	_, _, err := s.dlqMessageHandler.Read(context.Background(), lastMessageID, pageSize, pageToken)
   142  
   143  	s.Equal(testError, err)
   144  }
   145  
   146  func (s *dlqMessageHandlerSuite) TestPurgeMessages() {
   147  	ackLevel := int64(10)
   148  	lastMessageID := int64(20)
   149  
   150  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   151  	s.mockReplicationQueue.EXPECT().RangeDeleteMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID).Return(nil)
   152  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), lastMessageID).Return(nil)
   153  	err := s.dlqMessageHandler.Purge(context.Background(), lastMessageID)
   154  
   155  	s.NoError(err)
   156  }
   157  
   158  func (s *dlqMessageHandlerSuite) TestPurgeMessages_ThrowErrorOnGetDLQAckLevel() {
   159  	lastMessageID := int64(20)
   160  	testError := fmt.Errorf("test")
   161  
   162  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(int64(-1), testError)
   163  	s.mockReplicationQueue.EXPECT().RangeDeleteMessagesFromDLQ(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(0)
   164  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), gomock.Any()).Times(0)
   165  	err := s.dlqMessageHandler.Purge(context.Background(), lastMessageID)
   166  
   167  	s.Equal(testError, err)
   168  }
   169  
   170  func (s *dlqMessageHandlerSuite) TestPurgeMessages_ThrowErrorOnPurgeMessages() {
   171  	ackLevel := int64(10)
   172  	lastMessageID := int64(20)
   173  	testError := fmt.Errorf("test")
   174  
   175  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   176  	s.mockReplicationQueue.EXPECT().RangeDeleteMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID).Return(testError)
   177  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), gomock.Any()).Times(0)
   178  	err := s.dlqMessageHandler.Purge(context.Background(), lastMessageID)
   179  
   180  	s.Equal(testError, err)
   181  }
   182  
   183  func (s *dlqMessageHandlerSuite) TestMergeMessages() {
   184  	ackLevel := int64(10)
   185  	lastMessageID := int64(20)
   186  	pageSize := 100
   187  	pageToken := []byte{}
   188  	messageID := int64(11)
   189  
   190  	namespaceAttribute := &replicationspb.NamespaceTaskAttributes{
   191  		Id: uuid.New(),
   192  	}
   193  
   194  	tasks := []*replicationspb.ReplicationTask{
   195  		{
   196  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   197  			SourceTaskId: messageID,
   198  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   199  				NamespaceTaskAttributes: namespaceAttribute,
   200  			},
   201  		},
   202  	}
   203  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   204  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   205  		Return(tasks, nil, nil)
   206  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), namespaceAttribute).Return(nil)
   207  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), messageID).Return(nil)
   208  	s.mockReplicationQueue.EXPECT().RangeDeleteMessagesFromDLQ(gomock.Any(), ackLevel, messageID).Return(nil)
   209  
   210  	token, err := s.dlqMessageHandler.Merge(context.Background(), lastMessageID, pageSize, pageToken)
   211  	s.NoError(err)
   212  	s.Nil(token)
   213  }
   214  
   215  func (s *dlqMessageHandlerSuite) TestMergeMessages_ThrowErrorOnGetDLQAckLevel() {
   216  	lastMessageID := int64(20)
   217  	pageSize := 100
   218  	pageToken := []byte{}
   219  	messageID := int64(11)
   220  	testError := fmt.Errorf("test")
   221  	namespaceAttribute := &replicationspb.NamespaceTaskAttributes{
   222  		Id: uuid.New(),
   223  	}
   224  
   225  	tasks := []*replicationspb.ReplicationTask{
   226  		{
   227  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   228  			SourceTaskId: int64(messageID),
   229  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   230  				NamespaceTaskAttributes: namespaceAttribute,
   231  			},
   232  		},
   233  	}
   234  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(int64(-1), testError)
   235  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   236  		Return(tasks, nil, nil).Times(0)
   237  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), gomock.Any()).Times(0)
   238  	s.mockReplicationQueue.EXPECT().DeleteMessageFromDLQ(gomock.Any(), gomock.Any()).Times(0)
   239  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), gomock.Any()).Times(0)
   240  
   241  	token, err := s.dlqMessageHandler.Merge(context.Background(), lastMessageID, pageSize, pageToken)
   242  	s.Equal(testError, err)
   243  	s.Nil(token)
   244  }
   245  
   246  func (s *dlqMessageHandlerSuite) TestMergeMessages_ThrowErrorOnGetDLQMessages() {
   247  	ackLevel := int64(10)
   248  	lastMessageID := int64(20)
   249  	pageSize := 100
   250  	pageToken := []byte{}
   251  	testError := fmt.Errorf("test")
   252  
   253  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   254  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   255  		Return(nil, nil, testError)
   256  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), gomock.Any()).Times(0)
   257  	s.mockReplicationQueue.EXPECT().DeleteMessageFromDLQ(gomock.Any(), gomock.Any()).Times(0)
   258  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), gomock.Any()).Times(0)
   259  
   260  	token, err := s.dlqMessageHandler.Merge(context.Background(), lastMessageID, pageSize, pageToken)
   261  	s.Equal(testError, err)
   262  	s.Nil(token)
   263  }
   264  
   265  func (s *dlqMessageHandlerSuite) TestMergeMessages_ThrowErrorOnHandleReceivingTask() {
   266  	ackLevel := int64(10)
   267  	lastMessageID := int64(20)
   268  	pageSize := 100
   269  	pageToken := []byte{}
   270  	messageID1 := int64(11)
   271  	messageID2 := int64(12)
   272  	testError := fmt.Errorf("test")
   273  	namespaceAttribute1 := &replicationspb.NamespaceTaskAttributes{
   274  		Id: uuid.New(),
   275  	}
   276  	namespaceAttribute2 := &replicationspb.NamespaceTaskAttributes{
   277  		Id: uuid.New(),
   278  	}
   279  	tasks := []*replicationspb.ReplicationTask{
   280  		{
   281  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   282  			SourceTaskId: messageID1,
   283  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   284  				NamespaceTaskAttributes: namespaceAttribute1,
   285  			},
   286  		},
   287  		{
   288  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   289  			SourceTaskId: messageID2,
   290  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   291  				NamespaceTaskAttributes: namespaceAttribute2,
   292  			},
   293  		},
   294  	}
   295  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   296  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   297  		Return(tasks, nil, nil)
   298  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), namespaceAttribute1).Return(nil)
   299  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), namespaceAttribute2).Return(testError)
   300  
   301  	token, err := s.dlqMessageHandler.Merge(context.Background(), lastMessageID, pageSize, pageToken)
   302  	s.Equal(testError, err)
   303  	s.Nil(token)
   304  }
   305  
   306  func (s *dlqMessageHandlerSuite) TestMergeMessages_ThrowErrorOnDeleteMessages() {
   307  	ackLevel := int64(10)
   308  	lastMessageID := int64(20)
   309  	pageSize := 100
   310  	pageToken := []byte{}
   311  	messageID1 := int64(11)
   312  	messageID2 := int64(12)
   313  	testError := fmt.Errorf("test")
   314  	namespaceAttribute1 := &replicationspb.NamespaceTaskAttributes{
   315  		Id: uuid.New(),
   316  	}
   317  	namespaceAttribute2 := &replicationspb.NamespaceTaskAttributes{
   318  		Id: uuid.New(),
   319  	}
   320  	tasks := []*replicationspb.ReplicationTask{
   321  		{
   322  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   323  			SourceTaskId: messageID1,
   324  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   325  				NamespaceTaskAttributes: namespaceAttribute1,
   326  			},
   327  		},
   328  		{
   329  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   330  			SourceTaskId: messageID2,
   331  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   332  				NamespaceTaskAttributes: namespaceAttribute2,
   333  			},
   334  		},
   335  	}
   336  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   337  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   338  		Return(tasks, nil, nil)
   339  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), namespaceAttribute1).Return(nil)
   340  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), namespaceAttribute2).Return(nil)
   341  	s.mockReplicationQueue.EXPECT().RangeDeleteMessagesFromDLQ(gomock.Any(), ackLevel, messageID2).Return(testError)
   342  
   343  	token, err := s.dlqMessageHandler.Merge(context.Background(), lastMessageID, pageSize, pageToken)
   344  	s.Error(err)
   345  	s.Nil(token)
   346  }
   347  
   348  func (s *dlqMessageHandlerSuite) TestMergeMessages_IgnoreErrorOnUpdateDLQAckLevel() {
   349  	ackLevel := int64(10)
   350  	lastMessageID := int64(20)
   351  	pageSize := 100
   352  	pageToken := []byte{}
   353  	messageID := int64(11)
   354  	testError := fmt.Errorf("test")
   355  	namespaceAttribute := &replicationspb.NamespaceTaskAttributes{
   356  		Id: uuid.New(),
   357  	}
   358  
   359  	tasks := []*replicationspb.ReplicationTask{
   360  		{
   361  			TaskType:     enumsspb.REPLICATION_TASK_TYPE_NAMESPACE_TASK,
   362  			SourceTaskId: messageID,
   363  			Attributes: &replicationspb.ReplicationTask_NamespaceTaskAttributes{
   364  				NamespaceTaskAttributes: namespaceAttribute,
   365  			},
   366  		},
   367  	}
   368  	s.mockReplicationQueue.EXPECT().GetDLQAckLevel(gomock.Any()).Return(ackLevel, nil)
   369  	s.mockReplicationQueue.EXPECT().GetMessagesFromDLQ(gomock.Any(), ackLevel, lastMessageID, pageSize, pageToken).
   370  		Return(tasks, nil, nil)
   371  	s.mockReplicationTaskExecutor.EXPECT().Execute(gomock.Any(), namespaceAttribute).Return(nil)
   372  	s.mockReplicationQueue.EXPECT().RangeDeleteMessagesFromDLQ(gomock.Any(), ackLevel, messageID).Return(nil)
   373  	s.mockReplicationQueue.EXPECT().UpdateDLQAckLevel(gomock.Any(), messageID).Return(testError)
   374  
   375  	token, err := s.dlqMessageHandler.Merge(context.Background(), lastMessageID, pageSize, pageToken)
   376  	s.NoError(err)
   377  	s.Nil(token)
   378  }