go.temporal.io/server@v1.23.0/common/namespace/dlq_message_handler.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 //go:generate mockgen -copyright_file ../../LICENSE -package $GOPACKAGE -source $GOFILE -destination dlq_message_handler_mock.go 26 27 package namespace 28 29 import ( 30 "context" 31 32 "go.temporal.io/api/serviceerror" 33 34 replicationspb "go.temporal.io/server/api/replication/v1" 35 "go.temporal.io/server/common/log" 36 "go.temporal.io/server/common/log/tag" 37 "go.temporal.io/server/common/persistence" 38 ) 39 40 type ( 41 // DLQMessageHandler is the interface handles namespace DLQ messages 42 DLQMessageHandler interface { 43 Read(ctx context.Context, lastMessageID int64, pageSize int, pageToken []byte) ([]*replicationspb.ReplicationTask, []byte, error) 44 Purge(ctx context.Context, lastMessageID int64) error 45 Merge(ctx context.Context, lastMessageID int64, pageSize int, pageToken []byte) ([]byte, error) 46 } 47 48 dlqMessageHandlerImpl struct { 49 replicationHandler ReplicationTaskExecutor 50 namespaceReplicationQueue persistence.NamespaceReplicationQueue 51 logger log.Logger 52 } 53 ) 54 55 // NewDLQMessageHandler returns a DLQTaskHandler instance 56 func NewDLQMessageHandler( 57 replicationHandler ReplicationTaskExecutor, 58 namespaceReplicationQueue persistence.NamespaceReplicationQueue, 59 logger log.Logger, 60 ) DLQMessageHandler { 61 return &dlqMessageHandlerImpl{ 62 replicationHandler: replicationHandler, 63 namespaceReplicationQueue: namespaceReplicationQueue, 64 logger: logger, 65 } 66 } 67 68 // ReadMessages reads namespace replication DLQ messages 69 func (d *dlqMessageHandlerImpl) Read( 70 ctx context.Context, 71 lastMessageID int64, 72 pageSize int, 73 pageToken []byte, 74 ) ([]*replicationspb.ReplicationTask, []byte, error) { 75 76 ackLevel, err := d.namespaceReplicationQueue.GetDLQAckLevel(ctx) 77 if err != nil { 78 return nil, nil, err 79 } 80 81 return d.namespaceReplicationQueue.GetMessagesFromDLQ( 82 ctx, 83 ackLevel, 84 lastMessageID, 85 pageSize, 86 pageToken, 87 ) 88 } 89 90 // PurgeMessages purges namespace replication DLQ messages 91 func (d *dlqMessageHandlerImpl) Purge( 92 ctx context.Context, 93 lastMessageID int64, 94 ) error { 95 96 ackLevel, err := d.namespaceReplicationQueue.GetDLQAckLevel(ctx) 97 if err != nil { 98 return err 99 } 100 101 if err := d.namespaceReplicationQueue.RangeDeleteMessagesFromDLQ( 102 ctx, 103 ackLevel, 104 lastMessageID, 105 ); err != nil { 106 return err 107 } 108 109 if err := d.namespaceReplicationQueue.UpdateDLQAckLevel( 110 ctx, 111 lastMessageID, 112 ); err != nil { 113 d.logger.Error("Failed to update DLQ ack level after purging messages", tag.Error(err)) 114 } 115 116 return nil 117 } 118 119 // MergeMessages merges namespace replication DLQ messages 120 func (d *dlqMessageHandlerImpl) Merge( 121 ctx context.Context, 122 lastMessageID int64, 123 pageSize int, 124 pageToken []byte, 125 ) ([]byte, error) { 126 127 ackLevel, err := d.namespaceReplicationQueue.GetDLQAckLevel(ctx) 128 if err != nil { 129 return nil, err 130 } 131 132 messages, token, err := d.namespaceReplicationQueue.GetMessagesFromDLQ( 133 ctx, 134 ackLevel, 135 lastMessageID, 136 pageSize, 137 pageToken, 138 ) 139 if err != nil { 140 return nil, err 141 } 142 143 var ackedMessageID int64 144 for _, message := range messages { 145 namespaceTask := message.GetNamespaceTaskAttributes() 146 if namespaceTask == nil { 147 return nil, serviceerror.NewInternal("Encounter non namespace replication task in namespace replication queue.") 148 } 149 150 if err := d.replicationHandler.Execute( 151 ctx, 152 namespaceTask, 153 ); err != nil { 154 return nil, err 155 } 156 ackedMessageID = message.SourceTaskId 157 } 158 159 if err := d.namespaceReplicationQueue.RangeDeleteMessagesFromDLQ( 160 ctx, 161 ackLevel, 162 ackedMessageID, 163 ); err != nil { 164 d.logger.Error("failed to delete merged tasks on merging namespace DLQ message", tag.Error(err)) 165 return nil, err 166 } 167 if err := d.namespaceReplicationQueue.UpdateDLQAckLevel(ctx, ackedMessageID); err != nil { 168 d.logger.Error("failed to update ack level on merging namespace DLQ message", tag.Error(err)) 169 } 170 171 return token, nil 172 }