go.temporal.io/server@v1.23.0/common/persistence/visibility/visibility_manager_impl.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 visibility 26 27 import ( 28 "context" 29 "fmt" 30 "time" 31 32 commonpb "go.temporal.io/api/common/v1" 33 enumspb "go.temporal.io/api/enums/v1" 34 "go.temporal.io/api/serviceerror" 35 workflowpb "go.temporal.io/api/workflow/v1" 36 "google.golang.org/protobuf/proto" 37 "google.golang.org/protobuf/types/known/timestamppb" 38 39 "go.temporal.io/server/common/log" 40 "go.temporal.io/server/common/namespace" 41 "go.temporal.io/server/common/persistence/visibility/manager" 42 "go.temporal.io/server/common/persistence/visibility/store" 43 "go.temporal.io/server/common/searchattribute" 44 ) 45 46 type ( 47 // visibilityManagerImpl is responsible for: 48 // - convert request (serialized some fields), 49 // - call underlying store (standard or advanced), 50 // - convert response. 51 visibilityManagerImpl struct { 52 store store.VisibilityStore 53 logger log.Logger 54 } 55 ) 56 57 const ( 58 // MemoEncoding is default encoding for visibility memo. 59 MemoEncoding = enumspb.ENCODING_TYPE_PROTO3 60 ) 61 62 var _ manager.VisibilityManager = (*visibilityManagerImpl)(nil) 63 64 func newVisibilityManagerImpl( 65 store store.VisibilityStore, 66 logger log.Logger, 67 ) *visibilityManagerImpl { 68 return &visibilityManagerImpl{ 69 store: store, 70 logger: logger, 71 } 72 } 73 74 func (p *visibilityManagerImpl) Close() { 75 p.store.Close() 76 } 77 78 func (p *visibilityManagerImpl) GetReadStoreName(_ namespace.Name) string { 79 return p.store.GetName() 80 } 81 82 func (p *visibilityManagerImpl) GetStoreNames() []string { 83 return []string{p.store.GetName()} 84 } 85 86 func (p *visibilityManagerImpl) HasStoreName(stName string) bool { 87 return p.store.GetName() == stName 88 } 89 90 func (p *visibilityManagerImpl) GetIndexName() string { 91 return p.store.GetIndexName() 92 } 93 94 func (p *visibilityManagerImpl) ValidateCustomSearchAttributes( 95 searchAttributes map[string]any, 96 ) (map[string]any, error) { 97 return p.store.ValidateCustomSearchAttributes(searchAttributes) 98 } 99 100 func (p *visibilityManagerImpl) RecordWorkflowExecutionStarted( 101 ctx context.Context, 102 request *manager.RecordWorkflowExecutionStartedRequest, 103 ) error { 104 requestBase, err := p.newInternalVisibilityRequestBase(request.VisibilityRequestBase) 105 if err != nil { 106 return err 107 } 108 req := &store.InternalRecordWorkflowExecutionStartedRequest{ 109 InternalVisibilityRequestBase: requestBase, 110 } 111 return p.store.RecordWorkflowExecutionStarted(ctx, req) 112 } 113 114 func (p *visibilityManagerImpl) RecordWorkflowExecutionClosed( 115 ctx context.Context, 116 request *manager.RecordWorkflowExecutionClosedRequest, 117 ) error { 118 requestBase, err := p.newInternalVisibilityRequestBase(request.VisibilityRequestBase) 119 if err != nil { 120 return err 121 } 122 req := &store.InternalRecordWorkflowExecutionClosedRequest{ 123 InternalVisibilityRequestBase: requestBase, 124 CloseTime: request.CloseTime, 125 HistoryLength: request.HistoryLength, 126 HistorySizeBytes: request.HistorySizeBytes, 127 ExecutionDuration: request.CloseTime.Sub(request.ExecutionTime), 128 StateTransitionCount: request.StateTransitionCount, 129 } 130 return p.store.RecordWorkflowExecutionClosed(ctx, req) 131 } 132 133 func (p *visibilityManagerImpl) UpsertWorkflowExecution( 134 ctx context.Context, 135 request *manager.UpsertWorkflowExecutionRequest, 136 ) error { 137 requestBase, err := p.newInternalVisibilityRequestBase(request.VisibilityRequestBase) 138 if err != nil { 139 return err 140 } 141 req := &store.InternalUpsertWorkflowExecutionRequest{ 142 InternalVisibilityRequestBase: requestBase, 143 } 144 return p.store.UpsertWorkflowExecution(ctx, req) 145 } 146 147 func (p *visibilityManagerImpl) DeleteWorkflowExecution( 148 ctx context.Context, 149 request *manager.VisibilityDeleteWorkflowExecutionRequest, 150 ) error { 151 return p.store.DeleteWorkflowExecution(ctx, request) 152 } 153 154 func (p *visibilityManagerImpl) ListOpenWorkflowExecutions( 155 ctx context.Context, 156 request *manager.ListWorkflowExecutionsRequest, 157 ) (*manager.ListWorkflowExecutionsResponse, error) { 158 response, err := p.store.ListOpenWorkflowExecutions(ctx, request) 159 if err != nil { 160 return nil, err 161 } 162 return p.convertInternalListResponse(response) 163 } 164 165 func (p *visibilityManagerImpl) ListClosedWorkflowExecutions( 166 ctx context.Context, 167 request *manager.ListWorkflowExecutionsRequest, 168 ) (*manager.ListWorkflowExecutionsResponse, error) { 169 response, err := p.store.ListClosedWorkflowExecutions(ctx, request) 170 if err != nil { 171 return nil, err 172 } 173 174 return p.convertInternalListResponse(response) 175 } 176 177 func (p *visibilityManagerImpl) ListOpenWorkflowExecutionsByType( 178 ctx context.Context, 179 request *manager.ListWorkflowExecutionsByTypeRequest, 180 ) (*manager.ListWorkflowExecutionsResponse, error) { 181 response, err := p.store.ListOpenWorkflowExecutionsByType(ctx, request) 182 if err != nil { 183 return nil, err 184 } 185 186 return p.convertInternalListResponse(response) 187 } 188 189 func (p *visibilityManagerImpl) ListClosedWorkflowExecutionsByType( 190 ctx context.Context, 191 request *manager.ListWorkflowExecutionsByTypeRequest, 192 ) (*manager.ListWorkflowExecutionsResponse, error) { 193 response, err := p.store.ListClosedWorkflowExecutionsByType(ctx, request) 194 if err != nil { 195 return nil, err 196 } 197 198 return p.convertInternalListResponse(response) 199 } 200 201 func (p *visibilityManagerImpl) ListOpenWorkflowExecutionsByWorkflowID( 202 ctx context.Context, 203 request *manager.ListWorkflowExecutionsByWorkflowIDRequest, 204 ) (*manager.ListWorkflowExecutionsResponse, error) { 205 response, err := p.store.ListOpenWorkflowExecutionsByWorkflowID(ctx, request) 206 if err != nil { 207 return nil, err 208 } 209 210 return p.convertInternalListResponse(response) 211 } 212 213 func (p *visibilityManagerImpl) ListClosedWorkflowExecutionsByWorkflowID( 214 ctx context.Context, 215 request *manager.ListWorkflowExecutionsByWorkflowIDRequest, 216 ) (*manager.ListWorkflowExecutionsResponse, error) { 217 response, err := p.store.ListClosedWorkflowExecutionsByWorkflowID(ctx, request) 218 if err != nil { 219 return nil, err 220 } 221 222 return p.convertInternalListResponse(response) 223 } 224 225 func (p *visibilityManagerImpl) ListClosedWorkflowExecutionsByStatus( 226 ctx context.Context, 227 request *manager.ListClosedWorkflowExecutionsByStatusRequest, 228 ) (*manager.ListWorkflowExecutionsResponse, error) { 229 response, err := p.store.ListClosedWorkflowExecutionsByStatus(ctx, request) 230 if err != nil { 231 return nil, err 232 } 233 234 return p.convertInternalListResponse(response) 235 } 236 237 func (p *visibilityManagerImpl) ListWorkflowExecutions( 238 ctx context.Context, 239 request *manager.ListWorkflowExecutionsRequestV2, 240 ) (*manager.ListWorkflowExecutionsResponse, error) { 241 response, err := p.store.ListWorkflowExecutions(ctx, request) 242 if err != nil { 243 return nil, err 244 } 245 246 return p.convertInternalListResponse(response) 247 } 248 249 func (p *visibilityManagerImpl) ScanWorkflowExecutions( 250 ctx context.Context, 251 request *manager.ListWorkflowExecutionsRequestV2, 252 ) (*manager.ListWorkflowExecutionsResponse, error) { 253 response, err := p.store.ScanWorkflowExecutions(ctx, request) 254 if err != nil { 255 return nil, err 256 } 257 258 return p.convertInternalListResponse(response) 259 } 260 261 func (p *visibilityManagerImpl) CountWorkflowExecutions( 262 ctx context.Context, 263 request *manager.CountWorkflowExecutionsRequest, 264 ) (*manager.CountWorkflowExecutionsResponse, error) { 265 response, err := p.store.CountWorkflowExecutions(ctx, request) 266 if err != nil { 267 return nil, err 268 } 269 270 return response, err 271 } 272 273 func (p *visibilityManagerImpl) GetWorkflowExecution( 274 ctx context.Context, 275 request *manager.GetWorkflowExecutionRequest, 276 ) (*manager.GetWorkflowExecutionResponse, error) { 277 response, err := p.store.GetWorkflowExecution(ctx, request) 278 if err != nil { 279 return nil, err 280 } 281 execution, err := p.convertInternalWorkflowExecutionInfo(response.Execution) 282 if err != nil { 283 return nil, err 284 } 285 return &manager.GetWorkflowExecutionResponse{Execution: execution}, err 286 } 287 288 func (p *visibilityManagerImpl) newInternalVisibilityRequestBase( 289 request *manager.VisibilityRequestBase, 290 ) (*store.InternalVisibilityRequestBase, error) { 291 if request == nil { 292 return nil, nil 293 } 294 memoBlob, err := p.serializeMemo(request.Memo) 295 if err != nil { 296 return nil, err 297 } 298 299 var searchAttrs *commonpb.SearchAttributes 300 if len(request.SearchAttributes.GetIndexedFields()) > 0 { 301 // Remove any system search attribute from the map. 302 // This is necessary because the validation can supress errors when trying 303 // to set a value on a system search attribute. 304 searchAttrs = &commonpb.SearchAttributes{ 305 IndexedFields: make(map[string]*commonpb.Payload), 306 } 307 for key, value := range request.SearchAttributes.IndexedFields { 308 if !searchattribute.IsSystem(key) { 309 searchAttrs.IndexedFields[key] = value 310 } 311 } 312 } 313 314 var ( 315 parentWorkflowID *string 316 parentRunID *string 317 ) 318 if request.ParentExecution != nil { 319 parentWorkflowID = &request.ParentExecution.WorkflowId 320 parentRunID = &request.ParentExecution.RunId 321 } 322 323 return &store.InternalVisibilityRequestBase{ 324 NamespaceID: request.NamespaceID.String(), 325 WorkflowID: request.Execution.GetWorkflowId(), 326 RunID: request.Execution.GetRunId(), 327 WorkflowTypeName: request.WorkflowTypeName, 328 StartTime: request.StartTime, 329 Status: request.Status, 330 ExecutionTime: request.ExecutionTime, 331 TaskID: request.TaskID, 332 ShardID: request.ShardID, 333 TaskQueue: request.TaskQueue, 334 Memo: memoBlob, 335 SearchAttributes: searchAttrs, 336 ParentWorkflowID: parentWorkflowID, 337 ParentRunID: parentRunID, 338 }, nil 339 } 340 341 func (p *visibilityManagerImpl) convertInternalListResponse( 342 internalResponse *store.InternalListWorkflowExecutionsResponse, 343 ) (*manager.ListWorkflowExecutionsResponse, error) { 344 if internalResponse == nil { 345 return nil, nil 346 } 347 348 resp := &manager.ListWorkflowExecutionsResponse{} 349 resp.Executions = make([]*workflowpb.WorkflowExecutionInfo, len(internalResponse.Executions)) 350 for i, execution := range internalResponse.Executions { 351 var err error 352 resp.Executions[i], err = p.convertInternalWorkflowExecutionInfo(execution) 353 if err != nil { 354 return nil, err 355 } 356 } 357 358 resp.NextPageToken = internalResponse.NextPageToken 359 return resp, nil 360 } 361 362 func (p *visibilityManagerImpl) convertInternalWorkflowExecutionInfo( 363 internalExecution *store.InternalWorkflowExecutionInfo, 364 ) (*workflowpb.WorkflowExecutionInfo, error) { 365 if internalExecution == nil { 366 return nil, nil 367 } 368 memo, err := p.deserializeMemo(internalExecution.Memo) 369 if err != nil { 370 return nil, err 371 } 372 373 executionInfo := &workflowpb.WorkflowExecutionInfo{ 374 Execution: &commonpb.WorkflowExecution{ 375 WorkflowId: internalExecution.WorkflowID, 376 RunId: internalExecution.RunID, 377 }, 378 Type: &commonpb.WorkflowType{ 379 Name: internalExecution.TypeName, 380 }, 381 StartTime: timestamppb.New(internalExecution.StartTime), 382 ExecutionTime: timestamppb.New(internalExecution.ExecutionTime), 383 Memo: memo, 384 SearchAttributes: internalExecution.SearchAttributes, 385 TaskQueue: internalExecution.TaskQueue, 386 Status: internalExecution.Status, 387 } 388 389 if internalExecution.ParentWorkflowID != "" { 390 executionInfo.ParentExecution = &commonpb.WorkflowExecution{ 391 WorkflowId: internalExecution.ParentWorkflowID, 392 RunId: internalExecution.ParentRunID, 393 } 394 } 395 396 // for close records 397 if internalExecution.Status != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING { 398 executionInfo.CloseTime = timestamppb.New(internalExecution.CloseTime) 399 executionInfo.HistoryLength = internalExecution.HistoryLength 400 executionInfo.HistorySizeBytes = internalExecution.HistorySizeBytes 401 executionInfo.StateTransitionCount = internalExecution.StateTransitionCount 402 } 403 404 // Workflows created before 1.11 have ExecutionTime set to Unix epoch zero time (1/1/1970) for non-cron/non-retry case. 405 // Use StartTime as ExecutionTime for this case (if there was a backoff it must be set). 406 // Remove this "if" block when ExecutionTime field has actual correct value (added 6/9/21). 407 // Affects only non-advanced visibility. 408 if !executionInfo.ExecutionTime.AsTime().After(time.Unix(0, 0)) { 409 executionInfo.ExecutionTime = executionInfo.StartTime 410 } 411 412 return executionInfo, nil 413 } 414 func (p *visibilityManagerImpl) deserializeMemo(data *commonpb.DataBlob) (*commonpb.Memo, error) { 415 if data == nil || len(data.Data) == 0 { 416 return &commonpb.Memo{}, nil 417 } 418 419 var () 420 switch data.EncodingType { 421 case enumspb.ENCODING_TYPE_PROTO3: 422 memo := &commonpb.Memo{} 423 err := proto.Unmarshal(data.Data, memo) 424 if err != nil { 425 return nil, serviceerror.NewInternal(fmt.Sprintf("Unable to deserialize memo from data blob: %v", err)) 426 } 427 return memo, nil 428 default: 429 return nil, serviceerror.NewInternal(fmt.Sprintf("Invalid memo encoding in database: %s", data.GetEncodingType().String())) 430 } 431 } 432 433 func (p *visibilityManagerImpl) serializeMemo(memo *commonpb.Memo) (*commonpb.DataBlob, error) { 434 if memo == nil { 435 memo = &commonpb.Memo{} 436 } 437 438 data, err := proto.Marshal(memo) 439 if err != nil { 440 return nil, serviceerror.NewInternal(fmt.Sprintf("Unable to serialize memo to data blob: %v", err)) 441 } 442 443 return &commonpb.DataBlob{ 444 Data: data, 445 EncodingType: MemoEncoding, 446 }, nil 447 }