67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
package builder
|
|
|
|
import (
|
|
"time"
|
|
|
|
"openreplay/backend/internal/handlers"
|
|
. "openreplay/backend/pkg/messages"
|
|
)
|
|
|
|
type builder struct {
|
|
readyMsgs []Message
|
|
timestamp uint64
|
|
lastMessageID uint64
|
|
lastSystemTime time.Time
|
|
processors []handlers.MessageProcessor
|
|
ended bool
|
|
}
|
|
|
|
func NewBuilder(handlers ...handlers.MessageProcessor) *builder {
|
|
return &builder{
|
|
processors: handlers,
|
|
}
|
|
}
|
|
|
|
func (b *builder) iterateReadyMessages(iter func(msg Message)) {
|
|
for _, readyMsg := range b.readyMsgs {
|
|
iter(readyMsg)
|
|
}
|
|
b.readyMsgs = nil
|
|
}
|
|
|
|
func (b *builder) checkSessionEnd(message Message) {
|
|
if _, isEnd := message.(*IOSSessionEnd); isEnd {
|
|
b.ended = true
|
|
}
|
|
if _, isEnd := message.(*SessionEnd); isEnd {
|
|
b.ended = true
|
|
}
|
|
}
|
|
|
|
func (b *builder) handleMessage(message Message, messageID uint64) {
|
|
if messageID < b.lastMessageID {
|
|
// May happen in case of duplicated messages in kafka (if `idempotence: false`)
|
|
return
|
|
}
|
|
timestamp := GetTimestamp(message)
|
|
if timestamp == 0 {
|
|
// May happen in case of messages that are single-in-batch,
|
|
// e.g. SessionStart or RawErrorEvent (emitted by `integrations`).
|
|
|
|
// TODO: make timestamp system transparent;
|
|
return
|
|
}
|
|
if timestamp < b.timestamp {
|
|
// Shouldn't happen after messageID check which is done above. TODO: log this case.
|
|
return
|
|
}
|
|
|
|
b.timestamp = timestamp
|
|
b.lastSystemTime = time.Now()
|
|
for _, p := range b.processors {
|
|
if rm := p.Handle(message, messageID, b.timestamp); rm != nil {
|
|
b.readyMsgs = append(b.readyMsgs, rm)
|
|
}
|
|
}
|
|
b.checkSessionEnd(message)
|
|
}
|