From edf14b9828ac60438cec8a72dfb88cad654719e7 Mon Sep 17 00:00:00 2001 From: Messede Degod Date: Wed, 23 Sep 2026 16:51:56 +0000 Subject: [PATCH 1/4] update: optimize broadcaster by lazily computing cert entry bytes --- internal/broadcast/dispatcher.go | 54 +++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/internal/broadcast/dispatcher.go b/internal/broadcast/dispatcher.go index 56a3ad8..9b9b124 100644 --- a/internal/broadcast/dispatcher.go +++ b/internal/broadcast/dispatcher.go @@ -1,6 +1,7 @@ package broadcast import ( + "fmt" "log" "sync" @@ -116,30 +117,53 @@ func (bm *Dispatcher) GetSkippedCerts() map[string]uint64 { return skippedCerts } +func entryBytesComputer(entry *models.Entry) func(subType SubscriptionType) ([]byte, error) { + var dataLite, dataFull, dataDomain []byte + var isDataLiteComputed, isDataFullComputed, isDataDomainComputed bool + + return func(subType SubscriptionType) ([]byte, error) { + switch subType { + case SubTypeLite: + if !isDataLiteComputed { + dataLite = entry.JSONLite() + isDataLiteComputed = true + } + return dataLite, nil + + case SubTypeFull: + if !isDataFullComputed { + dataFull = entry.JSON() + isDataFullComputed = true + } + return dataFull, nil + + case SubTypeDomain: + if !isDataDomainComputed { + dataDomain = entry.JSONDomains() + isDataDomainComputed = true + } + return dataDomain, nil + + default: + return []byte{}, fmt.Errorf("Unknown subscription type '%d'", subType) + } + } +} + // broadcaster is run in a goroutine and handles the dispatching of certs to clients. func (bm *Dispatcher) broadcaster() { for { - var data []byte - // Take entry out of broadcast channel and generate JSON representations for the entry. entry := <-bm.MessageQueue - dataLite := entry.JSONLite() - dataFull := entry.JSON() - dataDomain := entry.JSONDomains() + computeBytes := entryBytesComputer(&entry) bm.clientLock.RLock() for _, c := range bm.clients { - switch c.SubType() { - case SubTypeLite: - data = dataLite - case SubTypeFull: - data = dataFull - case SubTypeDomain: - data = dataDomain - default: - // This should never happen, but if it does, we log it and skip the client. - log.Printf("Unknown subscription type '%d' for client '%s'. Skipping this client!\n", c.SubType(), c.Name()) + data, err := computeBytes(c.SubType()) + // This should never happen, but if it does, we log it and skip the client. + if err != nil { + log.Printf("%s on client '%s'. Skipping this client!\n", err.Error(), c.Name()) continue } From 8c0344cfb46bdcf0db4167feab6dea8db7f710ef Mon Sep 17 00:00:00 2001 From: Messede Degod Date: Sat, 26 Sep 2026 06:49:37 +0000 Subject: [PATCH 2/4] update: use internal cache of models.Entry JSON methods in entryBytesComputer --- internal/broadcast/dispatcher.go | 24 +++--------------------- internal/models/certstream.go | 15 +++++++++++---- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/internal/broadcast/dispatcher.go b/internal/broadcast/dispatcher.go index 9b9b124..c4b5730 100644 --- a/internal/broadcast/dispatcher.go +++ b/internal/broadcast/dispatcher.go @@ -118,32 +118,14 @@ func (bm *Dispatcher) GetSkippedCerts() map[string]uint64 { } func entryBytesComputer(entry *models.Entry) func(subType SubscriptionType) ([]byte, error) { - var dataLite, dataFull, dataDomain []byte - var isDataLiteComputed, isDataFullComputed, isDataDomainComputed bool - return func(subType SubscriptionType) ([]byte, error) { switch subType { case SubTypeLite: - if !isDataLiteComputed { - dataLite = entry.JSONLite() - isDataLiteComputed = true - } - return dataLite, nil - + return entry.JSONLite(), nil case SubTypeFull: - if !isDataFullComputed { - dataFull = entry.JSON() - isDataFullComputed = true - } - return dataFull, nil - + return entry.JSON(), nil case SubTypeDomain: - if !isDataDomainComputed { - dataDomain = entry.JSONDomains() - isDataDomainComputed = true - } - return dataDomain, nil - + return entry.JSONDomains(), nil default: return []byte{}, fmt.Errorf("Unknown subscription type '%d'", subType) } diff --git a/internal/models/certstream.go b/internal/models/certstream.go index 4d2e4f5..eceb930 100644 --- a/internal/models/certstream.go +++ b/internal/models/certstream.go @@ -7,10 +7,11 @@ import ( ) type Entry struct { - Data Data `json:"data"` - MessageType string `json:"message_type"` - cachedJSON []byte - cachedJSONLite []byte + Data Data `json:"data"` + MessageType string `json:"message_type"` + cachedJSON []byte + cachedJSONLite []byte + cachedJSONDomains []byte } // Clone returns a new copy of the Entry. @@ -61,6 +62,10 @@ func (e *Entry) JSONLiteNoCache() []byte { // JSONDomains returns the JSON encoded domains (DomainsEntry) as byte slice. func (e *Entry) JSONDomains() []byte { + if len(e.cachedJSONDomains) > 0 { + return e.cachedJSONDomains + } + domainsEntry := DomainsEntry{ Data: e.Data.LeafCert.AllDomains, MessageType: "dns_entries", @@ -71,6 +76,8 @@ func (e *Entry) JSONDomains() []byte { log.Println(err) } + e.cachedJSONDomains = domainsEntryBytes + return domainsEntryBytes } From cb5d977616e3bcc6885654735b90bba9f402ddba Mon Sep 17 00:00:00 2001 From: Messede Degod Date: Sun, 27 Sep 2026 06:08:19 +0000 Subject: [PATCH 3/4] update: simplify broadcaster loop while keeping the cache --- internal/broadcast/dispatcher.go | 33 +++++++++++--------------------- internal/models/certstream.go | 9 +++++---- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/internal/broadcast/dispatcher.go b/internal/broadcast/dispatcher.go index c4b5730..99c79d2 100644 --- a/internal/broadcast/dispatcher.go +++ b/internal/broadcast/dispatcher.go @@ -1,7 +1,6 @@ package broadcast import ( - "fmt" "log" "sync" @@ -117,38 +116,28 @@ func (bm *Dispatcher) GetSkippedCerts() map[string]uint64 { return skippedCerts } -func entryBytesComputer(entry *models.Entry) func(subType SubscriptionType) ([]byte, error) { - return func(subType SubscriptionType) ([]byte, error) { - switch subType { - case SubTypeLite: - return entry.JSONLite(), nil - case SubTypeFull: - return entry.JSON(), nil - case SubTypeDomain: - return entry.JSONDomains(), nil - default: - return []byte{}, fmt.Errorf("Unknown subscription type '%d'", subType) - } - } -} - // broadcaster is run in a goroutine and handles the dispatching of certs to clients. func (bm *Dispatcher) broadcaster() { for { // Take entry out of broadcast channel and generate JSON representations for the entry. entry := <-bm.MessageQueue - computeBytes := entryBytesComputer(&entry) bm.clientLock.RLock() + var data []byte for _, c := range bm.clients { - data, err := computeBytes(c.SubType()) - // This should never happen, but if it does, we log it and skip the client. - if err != nil { - log.Printf("%s on client '%s'. Skipping this client!\n", err.Error(), c.Name()) + subType := c.SubType() + switch subType { + case SubTypeLite: + data = entry.JSONLite() + case SubTypeFull: + data = entry.JSON() + case SubTypeDomain: + data = entry.JSONDomains() + default: + log.Printf("Unknown subscription type '%d' on client '%s'. Skipping this client!\n", subType, c.Name()) continue } - c.Write(data) } diff --git a/internal/models/certstream.go b/internal/models/certstream.go index eceb930..83f3312 100644 --- a/internal/models/certstream.go +++ b/internal/models/certstream.go @@ -17,10 +17,11 @@ type Entry struct { // Clone returns a new copy of the Entry. func (e *Entry) Clone() Entry { return Entry{ - Data: e.Data, - MessageType: e.MessageType, - cachedJSON: e.cachedJSON, - cachedJSONLite: e.cachedJSONLite, + Data: e.Data, + MessageType: e.MessageType, + cachedJSON: e.cachedJSON, + cachedJSONLite: e.cachedJSONLite, + cachedJSONDomains: e.cachedJSONDomains, } } From a6ab765c948cbd1ab6cbd7a550d819277067ad45 Mon Sep 17 00:00:00 2001 From: Messede Degod Date: Sun, 27 Sep 2026 06:10:35 +0000 Subject: [PATCH 4/4] update: refactor broadcaster loop --- internal/broadcast/dispatcher.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/broadcast/dispatcher.go b/internal/broadcast/dispatcher.go index 99c79d2..640cc3b 100644 --- a/internal/broadcast/dispatcher.go +++ b/internal/broadcast/dispatcher.go @@ -119,15 +119,15 @@ func (bm *Dispatcher) GetSkippedCerts() map[string]uint64 { // broadcaster is run in a goroutine and handles the dispatching of certs to clients. func (bm *Dispatcher) broadcaster() { for { + var data []byte + // Take entry out of broadcast channel and generate JSON representations for the entry. entry := <-bm.MessageQueue bm.clientLock.RLock() - var data []byte for _, c := range bm.clients { - subType := c.SubType() - switch subType { + switch c.SubType() { case SubTypeLite: data = entry.JSONLite() case SubTypeFull: @@ -135,7 +135,7 @@ func (bm *Dispatcher) broadcaster() { case SubTypeDomain: data = entry.JSONDomains() default: - log.Printf("Unknown subscription type '%d' on client '%s'. Skipping this client!\n", subType, c.Name()) + log.Printf("Unknown subscription type '%d' on client '%s'. Skipping this client!\n", c.SubType(), c.Name()) continue } c.Write(data)