producer/pack_id.go (51 lines of code) (raw):
package producer
import (
"fmt"
"strings"
"sync"
"sync/atomic"
"time"
)
type PackIdGenerator struct {
mutex sync.RWMutex
logstorePackIdGenerator map[string]*LogStorePackIdGenerator
count atomic.Int32
}
func newPackIdGenerator() *PackIdGenerator {
return &PackIdGenerator{
logstorePackIdGenerator: make(map[string]*LogStorePackIdGenerator),
}
}
func (g *PackIdGenerator) GeneratePackId(project, logstore string) string {
key := project + "|" + logstore
// fast path, logstore already has a generator
g.mutex.RLock()
if l, ok := g.logstorePackIdGenerator[key]; ok {
packNumber := l.packNumber.Add(1)
g.mutex.RUnlock()
return fmt.Sprintf("%s%X", l.prefix, packNumber-1)
}
g.mutex.RUnlock()
// slow path
g.mutex.Lock()
if _, ok := g.logstorePackIdGenerator[key]; !ok {
g.logstorePackIdGenerator[key] = newLogStorePackIdGenerator(g.count.Add(1))
}
l := g.logstorePackIdGenerator[key]
packNumber := l.packNumber.Add(1)
g.mutex.Unlock()
return fmt.Sprintf("%s%X", l.prefix, packNumber-1)
}
type LogStorePackIdGenerator struct {
packNumber atomic.Int64
prefix string // with "-"
}
func newLogStorePackIdGenerator(id int32) *LogStorePackIdGenerator {
hash := fmt.Sprintf("%d-%d", time.Now().UnixNano(), id)
return &LogStorePackIdGenerator{
packNumber: atomic.Int64{},
prefix: strings.ToUpper(generatePackId(hash)) + "-",
}
}
func generatePackId(source string) string {
srcData := source + time.Now().String()
return ToMd5(srcData)[0:16]
}