func (pq *PQueue) loadAllMessages() { nowTs := common.Uts() log.Debug("Initializing queue: %s", pq.desc.Name) iter := pq.database.IterServiceItems(pq.serviceId) defer iter.Close() msgs := MessageSlice{} delIds := []string{} cfg := pq.config for iter.Valid() { pqmsg := UnmarshalPQMessage(string(iter.Key), iter.Value) // Store list if message IDs that should be removed. if pqmsg.CreatedTs+cfg.MsgTtl < nowTs || (pqmsg.PopCount >= cfg.PopCountLimit && cfg.PopCountLimit > 0) { delIds = append(delIds, pqmsg.Id) } else { msgs = append(msgs, pqmsg) } iter.Next() } log.Debug("Loaded %d messages for %s queue", len(msgs), pq.desc.Name) if len(delIds) > 0 { log.Debug("Deleting %d expired messages", len(delIds)) for _, msgId := range delIds { pq.database.DeleteItem(pq.serviceId, msgId) } } // Sorting data guarantees that messages will be available in the same order as they arrived. sort.Sort(msgs) // Update serial number to match the latest message. if len(msgs) > 0 { pq.msgSerialNumber = msgs[len(msgs)-1].SerialNumber } for _, msg := range msgs { pq.msgMap[msg.Id] = msg if msg.UnlockTs > nowTs { pq.inFlightHeap.PushItem(msg.Id, msg.UnlockTs) } else { pq.expireHeap.PushItem(msg.Id, msg.CreatedTs+cfg.MsgTtl) pq.availMsgs.Push(msg.Id, msg.Priority) } } log.Debug("Messages available: %d", pq.expireHeap.Len()) log.Debug("Messages are in flight: %d", pq.inFlightHeap.Len()) }
// Remove all items which are completely expired. func (pq *PQueue) cleanExpiredItems(ts int64) int64 { var counter int64 = 0 eh := pq.expireHeap bs := conf.CFG.PQueueConfig.ExpirationBatchSize for !(eh.Empty()) && eh.MinElement() < ts && counter < bs { counter++ pq.deleteMessage(eh.PopItem().Id) } if counter > 0 { log.Debug("%d item(s) expired.", counter) } return counter }
// Unlocks all items which exceeded their lock time. func (pq *PQueue) releaseInFlight(ts int64) int64 { ifHeap := pq.inFlightHeap bs := conf.CFG.PQueueConfig.UnlockBatchSize var counter int64 = 0 for !(ifHeap.Empty()) && ifHeap.MinElement() < ts && counter < bs { counter++ unlockedItem := ifHeap.PopItem() pqmsg := pq.msgMap[unlockedItem.Id] pq.returnToFront(pqmsg) } if counter > 0 { log.Debug("'%d' item(s) returned to the front of the queue.", counter) } return counter }
// Connection dispatcher. Entry point to start connection handling. func (s *SessionHandler) DispatchConn() { go s.quitListenter() addr := s.conn.RemoteAddr().String() log.Info("Client connected: %s", addr) s.writeResponse(common.NewStrResponse("HELLO FIREMPQ-0.1")) for s.active { cmdTokens, err := s.tokenizer.ReadTokens(s.conn) if err == nil { err = s.processCmdTokens(cmdTokens) } if err != nil { errTxt := err.Error() if err != io.EOF && !(strings.Index(errTxt, "use of closed") > 0) { log.Error(errTxt) } break } } log.Debug("Client disconnected: %s", addr) }
// Delete all messages in the queue. It includes all type of messages func (pq *PQueue) Clear() { total := 0 for { ids := []string{} pq.lock.Lock() if len(pq.msgMap) == 0 { pq.lock.Unlock() break } for k, _ := range pq.msgMap { ids = append(ids, k) if len(ids) > 100 { break } } total += len(ids) for _, id := range ids { pq.deleteMessage(id) } pq.lock.Unlock() } log.Debug("Removed %d messages.", total) }
func (pq *PQueue) IsClosed() bool { log.Debug("Closing PQueue service: %s", pq.desc.Name) return pq.closedState.IsTrue() }