func (m *diskMailbox) Nack(id vega.MessageId) error { m.Lock() defer m.Unlock() idxStr := id.LocalIndex() if idxStr == "" { return vega.EUnknownMessage } idx, err := strconv.Atoi(idxStr) if err != nil { return err } db := m.disk.db return db.Update(func(tx *bolt.Tx) error { var header mailboxHeader buk := tx.Bucket(m.prefix) data := buk.Get(cMInfo) if data == nil { return vega.EUnknownMessage } diskDataUnmarshal(data, &header) if idx < header.AckIndex || idx >= header.ReadIndex { return vega.EUnknownMessage } header.InFlight-- // optimization, nack'ing the last read message if idx == header.ReadIndex-1 { header.ReadIndex-- header.Size++ } else { header.DCMessages = append(header.DCMessages, idx) } headerData, err := diskDataMarshal(&header) if err != nil { return err } return buk.Put(cMInfo, headerData) }) }
func (m *diskMailbox) Ack(id vega.MessageId) error { m.Lock() defer m.Unlock() db := m.disk.db return db.Update(func(tx *bolt.Tx) error { buk := tx.Bucket(m.prefix) data := buk.Get(cMInfo) if len(data) == 0 { return vega.EUnknownMessage } var header mailboxHeader err := diskDataUnmarshal(data, &header) if err != nil { return ECorruptMailbox } idxStr := id.LocalIndex() if idxStr == "" { return vega.EUnknownMessage } idx, err := strconv.Atoi(idxStr) if err != nil { return err } // debugf("acking message %d (AckIndex: %d)\n", idx, header.AckIndex) if header.ReadIndex-header.AckIndex == 0 { return vega.EUnknownMessage } if idx < header.AckIndex || idx >= header.ReadIndex { return vega.EUnknownMessage } // Messages may be ack'd incontigiously. That's fine, we'll // just track AckIndex as the oldest un-acked message. if header.AckIndex == idx { header.AckIndex++ } key := append(cMessagePrefix, []byte(idxStr)...) err = buk.Delete(key) if err != nil { return err } header.InFlight-- headerData, err := diskDataMarshal(&header) if err != nil { return err } return buk.Put(cMInfo, headerData) }) }