@@ -193,7 +193,7 @@ func (s *sqlMessageStore) FetchByOffset(ctx context.Context, topic string, parti
193193
194194 // Fetch visible messages (invisible_until <= now)
195195 rows , err := tx .QueryContext (ctx , fmt .Sprintf (`
196- SELECT offset, id, payload, metadata, partition_key, retry_count, published_at
196+ SELECT offset, id, payload, metadata, partition_key, retry_count, published_at, failed_at, failure_count, last_error, original_topic
197197 FROM %s
198198 WHERE topic = ? AND partition_key = ? AND offset > ? AND invisible_until <= ?
199199 ORDER BY offset
@@ -222,9 +222,13 @@ func (s *sqlMessageStore) FetchByOffset(ctx context.Context, topic string, parti
222222 partKey string
223223 retryCount int
224224 publishedAtMilli int64
225+ failedAt sql.NullInt64
226+ failureCount sql.NullInt32
227+ lastError sql.NullString
228+ originalTopic sql.NullString
225229 )
226230
227- if err := rows .Scan (& offset , & id , & payload , & metadataJSON , & partKey , & retryCount , & publishedAtMilli ); err != nil {
231+ if err := rows .Scan (& offset , & id , & payload , & metadataJSON , & partKey , & retryCount , & publishedAtMilli , & failedAt , & failureCount , & lastError , & originalTopic ); err != nil {
228232 s .logger .Errorw ("failed to scan message row" ,
229233 logTopic , topic ,
230234 logPartitionKey , partitionKey ,
@@ -251,14 +255,40 @@ func (s *sqlMessageStore) FetchByOffset(ctx context.Context, topic string, parti
251255 metadata = make (map [string ]string )
252256 }
253257
258+ // Convert sql.Null types to pointers
259+ var failedAtPtr * int64
260+ if failedAt .Valid {
261+ failedAtPtr = & failedAt .Int64
262+ }
263+
264+ var failureCountPtr * int
265+ if failureCount .Valid {
266+ val := int (failureCount .Int32 )
267+ failureCountPtr = & val
268+ }
269+
270+ var lastErrorPtr * string
271+ if lastError .Valid {
272+ lastErrorPtr = & lastError .String
273+ }
274+
275+ var originalTopicPtr * string
276+ if originalTopic .Valid {
277+ originalTopicPtr = & originalTopic .String
278+ }
279+
254280 results = append (results , MessageRow {
255- Offset : offset ,
256- ID : id ,
257- Payload : payload ,
258- Metadata : metadata ,
259- PartitionKey : partKey ,
260- RetryCount : retryCount ,
261- PublishedAt : publishedAtMilli ,
281+ Offset : offset ,
282+ ID : id ,
283+ Payload : payload ,
284+ Metadata : metadata ,
285+ PartitionKey : partKey ,
286+ RetryCount : retryCount ,
287+ PublishedAt : publishedAtMilli ,
288+ FailedAt : failedAtPtr ,
289+ FailureCount : failureCountPtr ,
290+ LastError : lastErrorPtr ,
291+ OriginalTopic : originalTopicPtr ,
262292 })
263293
264294 messageIDs = append (messageIDs , id )
@@ -331,13 +361,18 @@ func (s *sqlMessageStore) FetchByOffset(ctx context.Context, topic string, parti
331361 return results , nil
332362}
333363
334- // MoveToDLQ atomically moves a message from the main table to the DLQ table
364+ // MoveToDLQ atomically moves a message to the DLQ by reinserting it with the DLQ topic name
365+ // The message is inserted back into queue_messages table with the DLQ topic (original + suffix)
366+ // This allows DLQ messages to be consumed using the normal subscriber
335367func (s * sqlMessageStore ) MoveToDLQ (ctx context.Context , topic string , messageID string , failureCount int , lastError string ) error {
336368 start := time .Now ()
337369 defer func () {
338370 s .metrics .Timer ("move_to_dlq.latency" ).Record (time .Since (start ))
339371 }()
340372
373+ // Construct DLQ topic name
374+ dlqTopic := topic + s .config .DLQ .TopicSuffix
375+
341376 tx , err := s .db .BeginTx (ctx , nil )
342377 if err != nil {
343378 s .logger .Errorw ("failed to begin transaction for DLQ move" ,
@@ -357,13 +392,14 @@ func (s *sqlMessageStore) MoveToDLQ(ctx context.Context, topic string, messageID
357392 partitionKey string
358393 createdAtMilli int64
359394 publishedAtMilli int64
395+ retryCount int
360396 )
361397
362398 err = tx .QueryRowContext (ctx , fmt .Sprintf (`
363- SELECT payload, metadata, partition_key, created_at, published_at
399+ SELECT payload, metadata, partition_key, created_at, published_at, retry_count
364400 FROM %s
365401 WHERE topic = ? AND id = ?
366- ` , MessagesTableName ), topic , messageID ).Scan (& payload , & metadataJSON , & partitionKey , & createdAtMilli , & publishedAtMilli )
402+ ` , MessagesTableName ), topic , messageID ).Scan (& payload , & metadataJSON , & partitionKey , & createdAtMilli , & publishedAtMilli , & retryCount )
367403
368404 if err != nil {
369405 if err == sql .ErrNoRows {
@@ -383,16 +419,19 @@ func (s *sqlMessageStore) MoveToDLQ(ctx context.Context, topic string, messageID
383419 return fmt .Errorf ("failed to fetch message: %w" , err )
384420 }
385421
386- // Insert into DLQ table
422+ // Insert into queue_messages table with DLQ topic name and DLQ-specific fields
423+ // Reset retry_count to 0 since this is a new topic (DLQ processing starts fresh)
424+ // Store the original failure count for tracking purposes
387425 now := time .Now ().UnixMilli ()
388426 _ , err = tx .ExecContext (ctx , fmt .Sprintf (`
389- INSERT INTO %s (topic, id, payload, metadata, partition_key, created_at, published_at, failed_at, failure_count, last_error)
390- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
391- ` , DLQTableName ), topic , messageID , payload , metadataJSON , partitionKey , createdAtMilli , publishedAtMilli , now , failureCount , lastError )
427+ INSERT INTO %s (topic, id, payload, metadata, partition_key, created_at, published_at, invisible_until, retry_count, failed_at, failure_count, last_error, original_topic )
428+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
429+ ` , MessagesTableName ), dlqTopic , messageID , payload , metadataJSON , partitionKey , createdAtMilli , publishedAtMilli , int64 ( 0 ), 0 , now , failureCount , lastError , topic )
392430
393431 if err != nil {
394- s .logger .Errorw ("failed to insert into DLQ" ,
432+ s .logger .Errorw ("failed to insert into DLQ topic " ,
395433 logTopic , topic ,
434+ "dlq_topic" , dlqTopic ,
396435 logMessageID , messageID ,
397436 logPartitionKey , partitionKey ,
398437 "failure_count" , failureCount ,
@@ -402,7 +441,7 @@ func (s *sqlMessageStore) MoveToDLQ(ctx context.Context, topic string, messageID
402441 return fmt .Errorf ("failed to insert into DLQ: %w" , err )
403442 }
404443
405- // Delete from main table
444+ // Delete from original topic
406445 _ , err = tx .ExecContext (ctx , fmt .Sprintf (`
407446 DELETE FROM %s WHERE topic = ? AND id = ?
408447 ` , MessagesTableName ), topic , messageID )
@@ -431,6 +470,7 @@ func (s *sqlMessageStore) MoveToDLQ(ctx context.Context, topic string, messageID
431470 s .metrics .Counter ("messages.moved_to_dlq" ).Inc (1 )
432471 s .logger .Infow ("moved message to DLQ" ,
433472 logTopic , topic ,
473+ "dlq_topic" , dlqTopic ,
434474 logMessageID , messageID ,
435475 logPartitionKey , partitionKey ,
436476 "failure_count" , failureCount ,
0 commit comments