Я использую PubSub в двух разных потоках, где мы получаем сообщения из одного потока, запускаем некоторую логику, и если она соответствует определенным критериям, мы публикуем ее во втором потоке. Второй поток также принимается из горутина.
Теперь у меня есть две основные функции HandleMessage
и HandleRetry
, где первая из первого потока, а вторая для второго потока.
Соответствующий код для HandleMessage
выглядит следующим образом:
if c.handler.ShouldProcess(tx) {
err := c.handler.Process(tx)
if err != nil {
c.log.
WithError(err).
WithField("tx_hash", tx.TxHash.String()).
Error("failed to process")
retryMsg := RetryMessage{
Transaction: tx,
RemainingProcessingAttempts: c.config.MaxProcessingAttempts,
LastAttempt: time.Now(),
}
data, err := pubsub.EncodeMessage(retryMsg)
if err != nil {
c.log.WithError(err).Error("failed to convert retry msg to byte slice")
}
id, err := c.retryQueue.Publish(context.Background(), &pubsub.Message{Data: data})
if err != nil {
c.log.WithError(err).
WithField("id", id).
Error("failed to publish message to retry queue")
}
}
}
и в HandleRetry
функция открывается с
retryTx := new(RetryMessage)
err := pubsub.DecodeMessage(msg.Data, retryTx)
if err != nil {
c.log.WithError(err).
Error("failed to decode message: not a retry tx")
msg.Ack()
return
}
Для RetryQueue
, который обрабатывается HandleRetry
- нет другого ввода, кроме сообщений, публикуемых с HandleMessage
Но я продолжаю получать ошибку декодирования gob, говоря:
level=error msg="failed to decode message: not a retry tx" env=LOCAL error="gob: type mismatch: no fields matched compiling decoder for RetryMessage"
RetryMessage
выглядит так
type RetryMessage struct {
Transaction *firehose.Transaction
RemainingProcessingAttempts int
LastAttempt time.Time
}
Функции кодирования и декодирования следующие
// EncodeMessage convert an arbitrary interface into a byte slice.
func EncodeMessage(data interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(data)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// DecodeMessage decodes message data into the provided interface.
func DecodeMessage(data []byte, dest interface{}) error {
buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf)
return dec.Decode(dest)
}