Refactor Kafka publishing without DB outbox

This commit is contained in:
richjohnrambo
2026-09-01 23:00:14 +08:00
parent 18237cf3ec
commit 929f847003
25 changed files with 416 additions and 478 deletions
+60 -1
View File
@@ -2984,11 +2984,20 @@ func (t *Topic) replyGetData(sess *Session, asUid types.Uid, asChan bool, req *M
count := 0
if userData := t.perUser[asUid]; (userData.modeGiven & userData.modeWant).IsReader() {
// Read messages from DB
messages, err := store.Messages.GetAll(t.tenantID, t.name, asUid, msgOpts2storeOpts(req))
opts := msgOpts2storeOpts(req)
messages, err := store.Messages.GetAll(t.tenantID, t.name, asUid, opts)
if err != nil {
sess.queueOut(ErrUnknownReply(msg, now))
return err
}
if len(messages) == 0 && shouldTryHotMessageFallback(t.cat, t.lastID, opts) {
hotMessages, ok, cacheErr := store.GetHotMessages(t.tenantID, t.name, opts, hotMessageFallbackLimit(opts))
if cacheErr != nil {
logs.Warn.Printf("get.data hot message fallback failed topic=%s user=%s: %v", t.name, asUid.UserId(), cacheErr)
} else if ok {
messages = filterHotMessagesForUser(hotMessages, asUid)
}
}
// Push the list of messages to the client as {data}.
if messages != nil {
@@ -3032,6 +3041,56 @@ func (t *Topic) replyGetData(sess *Session, asUid types.Uid, asChan bool, req *M
return nil
}
func shouldTryHotMessageFallback(cat types.TopicCat, lastID int64, opts *types.QueryOpt) bool {
if cat != types.TopicCatGrp || opts == nil || opts.IfModifiedSince != nil ||
!opts.User.IsZero() || opts.Topic != "" || opts.Since <= 0 || opts.Before > 0 || len(opts.IdRanges) > 0 {
return false
}
limit := hotMessageFallbackLimit(opts)
if limit <= 0 || limit > 10 {
return false
}
floor := lastID - 10
if floor < 1 {
floor = 1
}
return lastID <= 0 || opts.Since >= floor
}
func hotMessageFallbackLimit(opts *types.QueryOpt) int {
if opts != nil && opts.Limit > 0 {
return opts.Limit
}
return 1
}
func filterHotMessagesForUser(messages []types.Message, asUid types.Uid) []types.Message {
if len(messages) == 0 {
return messages
}
filtered := messages[:0]
for i := range messages {
if hotMessageVisibleToUser(&messages[i], asUid) {
filtered = append(filtered, messages[i])
}
}
return filtered
}
func hotMessageVisibleToUser(msg *types.Message, asUid types.Uid) bool {
if msg == nil || msg.DeletedAt != nil || msg.DelId > 0 || asUid.IsZero() {
return msg != nil && msg.DeletedAt == nil && msg.DelId == 0
}
uid := asUid.String()
userID := asUid.UserId()
for _, deleted := range msg.DeletedFor {
if deleted.User == uid || deleted.User == userID {
return false
}
}
return true
}
// replyGetTags returns topics' tags - tokens used for discovery.
func (t *Topic) replyGetTags(sess *Session, asUid types.Uid, msg *ClientComMessage) error {
now := types.TimeNow()