go.temporal.io/server@v1.23.0/common/persistence/visibility/store/elasticsearch/visibility_store_write_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 elasticsearch
    26  
    27  import (
    28  	"context"
    29  	"fmt"
    30  	"strings"
    31  	"time"
    32  
    33  	"github.com/golang/mock/gomock"
    34  	commonpb "go.temporal.io/api/common/v1"
    35  	enumspb "go.temporal.io/api/enums/v1"
    36  
    37  	"go.temporal.io/server/common/future"
    38  	"go.temporal.io/server/common/payload"
    39  	"go.temporal.io/server/common/persistence"
    40  	"go.temporal.io/server/common/persistence/visibility/manager"
    41  	"go.temporal.io/server/common/persistence/visibility/store"
    42  	"go.temporal.io/server/common/persistence/visibility/store/elasticsearch/client"
    43  	"go.temporal.io/server/common/searchattribute"
    44  )
    45  
    46  func (s *ESVisibilitySuite) TestRecordWorkflowExecutionStarted() {
    47  	// test non-empty request fields match
    48  	request := &store.InternalRecordWorkflowExecutionStartedRequest{
    49  		InternalVisibilityRequestBase: &store.InternalVisibilityRequestBase{
    50  			NamespaceID:      "namespaceID",
    51  			WorkflowID:       "wid",
    52  			RunID:            "rid",
    53  			WorkflowTypeName: "wfType",
    54  			StartTime:        time.Unix(0, 123).UTC(),
    55  			ExecutionTime:    time.Unix(0, 321).UTC(),
    56  			TaskID:           int64(111),
    57  			ShardID:          2208,
    58  			Memo:             persistence.NewDataBlob([]byte("test bytes"), enumspb.ENCODING_TYPE_PROTO3.String()),
    59  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
    60  			TaskQueue:        "task-queue-name",
    61  			SearchAttributes: &commonpb.SearchAttributes{
    62  				IndexedFields: map[string]*commonpb.Payload{
    63  					"CustomTextField": payload.EncodeString("alex"),
    64  				},
    65  			},
    66  		},
    67  	}
    68  
    69  	s.mockProcessor.EXPECT().Add(gomock.Any(), gomock.Any()).
    70  		DoAndReturn(func(bulkRequest *client.BulkableRequest, visibilityTaskKey string) future.Future[bool] {
    71  			s.Equal("2208~111", visibilityTaskKey)
    72  
    73  			body := bulkRequest.Doc
    74  
    75  			s.Equal(request.NamespaceID, body[searchattribute.NamespaceID])
    76  			s.Equal(request.WorkflowID, body[searchattribute.WorkflowID])
    77  			s.Equal(request.RunID, body[searchattribute.RunID])
    78  			s.Equal(request.WorkflowTypeName, body[searchattribute.WorkflowType])
    79  			s.EqualValues(request.StartTime, body[searchattribute.StartTime])
    80  			s.EqualValues(request.ExecutionTime, body[searchattribute.ExecutionTime])
    81  			s.Equal(request.TaskQueue, body[searchattribute.TaskQueue])
    82  			s.EqualValues(request.Status.String(), body[searchattribute.ExecutionStatus])
    83  
    84  			s.Equal(request.Memo.Data, body[searchattribute.Memo])
    85  			s.Equal(enumspb.ENCODING_TYPE_PROTO3.String(), body[searchattribute.MemoEncoding])
    86  
    87  			CustomTextField := body["CustomTextField"].(string)
    88  			// %q because request has JSON encoded string.
    89  			s.EqualValues(request.SearchAttributes.GetIndexedFields()["CustomTextField"].Data, fmt.Sprintf("%q", CustomTextField))
    90  
    91  			s.Equal(client.BulkableRequestTypeIndex, bulkRequest.RequestType)
    92  			s.EqualValues(request.TaskID, bulkRequest.Version)
    93  			s.Equal("wid~rid", bulkRequest.ID)
    94  			s.Equal("test-index", bulkRequest.Index)
    95  
    96  			f := future.NewFuture[bool]()
    97  			f.Set(true, nil)
    98  			return f
    99  		})
   100  
   101  	err := s.visibilityStore.RecordWorkflowExecutionStarted(context.Background(), request)
   102  	s.NoError(err)
   103  }
   104  
   105  func (s *ESVisibilitySuite) TestRecordWorkflowExecutionStarted_EmptyRequest() {
   106  	// test empty request
   107  	request := &store.InternalRecordWorkflowExecutionStartedRequest{
   108  		InternalVisibilityRequestBase: &store.InternalVisibilityRequestBase{
   109  			Memo: &commonpb.DataBlob{},
   110  		},
   111  	}
   112  
   113  	s.mockProcessor.EXPECT().Add(gomock.Any(), gomock.Any()).
   114  		DoAndReturn(func(bulkRequest *client.BulkableRequest, visibilityTaskKey string) future.Future[bool] {
   115  			s.Equal("0~0", visibilityTaskKey)
   116  
   117  			body := bulkRequest.Doc
   118  
   119  			_, ok := body[searchattribute.Memo]
   120  			s.False(ok)
   121  			_, ok = body[searchattribute.MemoEncoding]
   122  			s.False(ok)
   123  
   124  			s.Equal(client.BulkableRequestTypeIndex, bulkRequest.RequestType)
   125  			s.EqualValues(request.TaskID, bulkRequest.Version)
   126  			s.Equal("~", bulkRequest.ID)
   127  			s.Equal("test-index", bulkRequest.Index)
   128  
   129  			f := future.NewFuture[bool]()
   130  			f.Set(true, nil)
   131  			return f
   132  		})
   133  
   134  	err := s.visibilityStore.RecordWorkflowExecutionStarted(context.Background(), request)
   135  	s.NoError(err)
   136  }
   137  
   138  func (s *ESVisibilitySuite) TestRecordWorkflowExecutionClosed() {
   139  	// test non-empty request fields match
   140  	request := &store.InternalRecordWorkflowExecutionClosedRequest{
   141  		InternalVisibilityRequestBase: &store.InternalVisibilityRequestBase{
   142  			NamespaceID:      "namespaceID",
   143  			WorkflowID:       "wid",
   144  			RunID:            "rid",
   145  			WorkflowTypeName: "wfType",
   146  			StartTime:        time.Date(2020, 8, 2, 1, 2, 3, 4, time.UTC),
   147  			ExecutionTime:    time.Date(2020, 8, 2, 2, 2, 3, 4, time.UTC),
   148  			TaskID:           int64(111),
   149  			ShardID:          2208,
   150  			Memo:             persistence.NewDataBlob([]byte("test bytes"), enumspb.ENCODING_TYPE_PROTO3.String()),
   151  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_TERMINATED,
   152  			TaskQueue:        "task-queue-name",
   153  			SearchAttributes: &commonpb.SearchAttributes{
   154  				IndexedFields: map[string]*commonpb.Payload{
   155  					"CustomTextField": payload.EncodeString("alex"),
   156  				},
   157  			},
   158  		},
   159  		CloseTime:     time.Unix(0, 1978).UTC(),
   160  		HistoryLength: int64(20),
   161  	}
   162  
   163  	s.mockProcessor.EXPECT().Add(gomock.Any(), gomock.Any()).
   164  		DoAndReturn(func(bulkRequest *client.BulkableRequest, visibilityTaskKey string) future.Future[bool] {
   165  			s.Equal("2208~111", visibilityTaskKey)
   166  
   167  			body := bulkRequest.Doc
   168  
   169  			s.Equal(request.NamespaceID, body[searchattribute.NamespaceID])
   170  			s.Equal(request.WorkflowID, body[searchattribute.WorkflowID])
   171  			s.Equal(request.RunID, body[searchattribute.RunID])
   172  			s.Equal(request.WorkflowTypeName, body[searchattribute.WorkflowType])
   173  			s.EqualValues(request.StartTime, body[searchattribute.StartTime])
   174  			s.EqualValues(request.ExecutionTime, body[searchattribute.ExecutionTime])
   175  			s.Equal(request.Memo.Data, body[searchattribute.Memo])
   176  			s.Equal(enumspb.ENCODING_TYPE_PROTO3.String(), body[searchattribute.MemoEncoding])
   177  			s.EqualValues(request.CloseTime, body[searchattribute.CloseTime])
   178  			s.EqualValues(request.Status.String(), body[searchattribute.ExecutionStatus])
   179  			s.EqualValues(request.HistoryLength, body[searchattribute.HistoryLength])
   180  
   181  			s.Equal(client.BulkableRequestTypeIndex, bulkRequest.RequestType)
   182  			s.EqualValues(request.TaskID, bulkRequest.Version)
   183  			s.Equal("wid~rid", bulkRequest.ID)
   184  			s.Equal("test-index", bulkRequest.Index)
   185  
   186  			f := future.NewFuture[bool]()
   187  			f.Set(true, nil)
   188  			return f
   189  		})
   190  
   191  	err := s.visibilityStore.RecordWorkflowExecutionClosed(context.Background(), request)
   192  	s.NoError(err)
   193  }
   194  
   195  func (s *ESVisibilitySuite) TestRecordWorkflowExecutionClosed_EmptyRequest() {
   196  	// test empty request
   197  	request := &store.InternalRecordWorkflowExecutionClosedRequest{
   198  		InternalVisibilityRequestBase: &store.InternalVisibilityRequestBase{
   199  			Memo: &commonpb.DataBlob{},
   200  		},
   201  	}
   202  
   203  	s.mockProcessor.EXPECT().Add(gomock.Any(), gomock.Any()).
   204  		DoAndReturn(func(bulkRequest *client.BulkableRequest, visibilityTaskKey string) future.Future[bool] {
   205  			s.Equal("0~0", visibilityTaskKey)
   206  
   207  			body := bulkRequest.Doc
   208  
   209  			_, ok := body[searchattribute.Memo]
   210  			s.False(ok)
   211  			_, ok = body[searchattribute.MemoEncoding]
   212  			s.False(ok)
   213  
   214  			s.Equal(client.BulkableRequestTypeIndex, bulkRequest.RequestType)
   215  			s.EqualValues(request.TaskID, bulkRequest.Version)
   216  			s.Equal("~", bulkRequest.ID)
   217  			s.Equal("test-index", bulkRequest.Index)
   218  
   219  			f := future.NewFuture[bool]()
   220  			f.Set(true, nil)
   221  			return f
   222  		})
   223  
   224  	err := s.visibilityStore.RecordWorkflowExecutionClosed(context.Background(), request)
   225  	s.NoError(err)
   226  }
   227  
   228  func (s *ESVisibilitySuite) TestDeleteExecution() {
   229  	// test non-empty request fields match
   230  	request := &manager.VisibilityDeleteWorkflowExecutionRequest{
   231  		NamespaceID: "namespaceID",
   232  		RunID:       "rid",
   233  		WorkflowID:  "wid",
   234  		TaskID:      int64(111),
   235  	}
   236  
   237  	s.mockProcessor.EXPECT().Add(gomock.Any(), gomock.Any()).
   238  		DoAndReturn(func(bulkRequest *client.BulkableRequest, visibilityTaskKey string) future.Future[bool] {
   239  			s.Equal("wid~rid", visibilityTaskKey)
   240  
   241  			s.Equal(client.BulkableRequestTypeDelete, bulkRequest.RequestType)
   242  			s.EqualValues(request.TaskID, bulkRequest.Version)
   243  			s.Equal("wid~rid", bulkRequest.ID)
   244  			s.Equal("test-index", bulkRequest.Index)
   245  
   246  			f := future.NewFuture[bool]()
   247  			f.Set(true, nil)
   248  			return f
   249  		})
   250  
   251  	err := s.visibilityStore.DeleteWorkflowExecution(context.Background(), request)
   252  	s.NoError(err)
   253  }
   254  
   255  func (s *ESVisibilitySuite) TestDeleteExecution_EmptyRequest() {
   256  	// test empty request
   257  	request := &manager.VisibilityDeleteWorkflowExecutionRequest{}
   258  
   259  	s.mockProcessor.EXPECT().Add(gomock.Any(), gomock.Any()).
   260  		DoAndReturn(func(bulkRequest *client.BulkableRequest, visibilityTaskKey string) future.Future[bool] {
   261  			s.Equal("~", visibilityTaskKey)
   262  
   263  			s.Equal(client.BulkableRequestTypeDelete, bulkRequest.RequestType)
   264  			s.Equal("~", bulkRequest.ID)
   265  			s.Equal("test-index", bulkRequest.Index)
   266  
   267  			f := future.NewFuture[bool]()
   268  			f.Set(true, nil)
   269  			return f
   270  		})
   271  
   272  	err := s.visibilityStore.DeleteWorkflowExecution(context.Background(), request)
   273  	s.NoError(err)
   274  }
   275  
   276  func (s *ESVisibilitySuite) Test_getDocID() {
   277  	s.Equal("wid~rid", getDocID("wid", "rid"))
   278  
   279  	s.Equal(strings.Repeat("a", 512), getDocID("wid", strings.Repeat("a", 1000)))
   280  	s.Equal(strings.Repeat("a", 512), getDocID("wid", strings.Repeat("a", 513)))
   281  	s.Equal(strings.Repeat("a", 512), getDocID("wid", strings.Repeat("a", 512)))
   282  	s.Equal(strings.Repeat("a", 511), getDocID("wid", strings.Repeat("a", 511)))
   283  	s.Equal("w~"+strings.Repeat("a", 510), getDocID("wid", strings.Repeat("a", 510)))
   284  	s.Equal("wi~"+strings.Repeat("a", 509), getDocID("wid", strings.Repeat("a", 509)))
   285  	s.Equal("wid~"+strings.Repeat("a", 508), getDocID("wid", strings.Repeat("a", 508)))
   286  	s.Equal("wid~"+strings.Repeat("a", 507), getDocID("wid", strings.Repeat("a", 507)))
   287  
   288  	s.Equal(strings.Repeat("a", 512-1-36)+"~fd86a520-741e-4fd3-a788-165c445ea6f3", getDocID(strings.Repeat("a", 1000), "fd86a520-741e-4fd3-a788-165c445ea6f3"))
   289  	s.Equal(strings.Repeat("a", 512-1-36)+"~fd86a520-741e-4fd3-a788-165c445ea6f3", getDocID(strings.Repeat("a", 477), "fd86a520-741e-4fd3-a788-165c445ea6f3"))
   290  	s.Equal(strings.Repeat("a", 512-1-36)+"~fd86a520-741e-4fd3-a788-165c445ea6f3", getDocID(strings.Repeat("a", 476), "fd86a520-741e-4fd3-a788-165c445ea6f3"))
   291  	s.Equal(strings.Repeat("a", 475)+"~fd86a520-741e-4fd3-a788-165c445ea6f3", getDocID(strings.Repeat("a", 475), "fd86a520-741e-4fd3-a788-165c445ea6f3"))
   292  	s.Equal(strings.Repeat("a", 474)+"~fd86a520-741e-4fd3-a788-165c445ea6f3", getDocID(strings.Repeat("a", 474), "fd86a520-741e-4fd3-a788-165c445ea6f3"))
   293  	s.Equal(strings.Repeat("a", 400)+"~fd86a520-741e-4fd3-a788-165c445ea6f3", getDocID(strings.Repeat("a", 400), "fd86a520-741e-4fd3-a788-165c445ea6f3"))
   294  }
   295  
   296  func (s *ESVisibilitySuite) Test_getVisibilityTaskKey() {
   297  	s.Equal("22~8", getVisibilityTaskKey(22, 8))
   298  	s.Equal("228~1978", getVisibilityTaskKey(228, 1978))
   299  }