1
0
Fork 0
hswro-alarm-bot/filters_sync.go

118 lines
2.6 KiB
Go
Raw Normal View History

2025-01-06 13:55:08 +00:00
package main
2025-01-06 23:09:41 +00:00
import (
"log"
"sync"
2025-01-08 19:24:45 +00:00
"git.sr.ht/~michalr/go-satel"
2025-01-06 23:09:41 +00:00
)
2025-01-06 13:55:08 +00:00
2025-01-06 22:29:54 +00:00
type SyncFilter[MsgType any] interface {
Then(what SyncFilter[MsgType]) SyncFilter[MsgType]
Call(msg MsgType)
2025-01-06 13:55:08 +00:00
}
2025-01-06 22:29:54 +00:00
type SyncFilterImpl[MsgType any] struct {
next SyncFilter[MsgType]
2025-01-06 13:55:08 +00:00
}
2025-01-06 22:29:54 +00:00
func (impl *SyncFilterImpl[MsgType]) Then(what SyncFilter[MsgType]) SyncFilter[MsgType] {
2025-01-06 19:53:08 +00:00
impl.next = what
2025-01-06 13:55:08 +00:00
return what
}
2025-01-06 22:29:54 +00:00
func (impl *SyncFilterImpl[MsgType]) CallNext(msg MsgType) {
2025-01-06 19:53:08 +00:00
if impl.next != nil {
impl.next.Call(msg)
2025-01-06 13:55:08 +00:00
}
}
2025-01-06 23:10:21 +00:00
type CollectFromChannel[MsgType any] struct{ SyncFilterImpl[MsgType] }
2025-01-06 19:53:08 +00:00
2025-01-06 23:10:21 +00:00
func (collect *CollectFromChannel[MsgType]) Call(msg MsgType) {
2025-01-06 19:53:08 +00:00
collect.CallNext(msg)
}
2025-01-06 23:10:21 +00:00
func (collect CollectFromChannel[MsgType]) Collect(events <-chan MsgType, wg *sync.WaitGroup, onClose func()) {
2025-01-06 13:55:08 +00:00
wg.Add(1)
go func() {
defer wg.Done()
2025-01-06 23:10:21 +00:00
defer onClose()
2025-01-06 13:55:08 +00:00
for e := range events {
2025-01-06 19:53:08 +00:00
collect.Call(e)
2025-01-06 13:55:08 +00:00
}
}()
}
2025-01-06 23:09:41 +00:00
type ThrottleSync struct {
SyncFilterImpl[GenericMessage]
events chan GenericMessage
}
2025-01-08 19:24:45 +00:00
func appendToGenericMessage(msg *GenericMessage, new *GenericMessage) *GenericMessage {
if msg == nil {
msg = &GenericMessage{make([]satel.BasicEventElement, 0)}
}
throughNewMessages:
for _, newEv := range new.Messages {
for i, oldEv := range msg.Messages {
if oldEv.Index == newEv.Index && oldEv.Type == newEv.Type {
// this message was seen - update its value
msg.Messages[i].Value = newEv.Value
continue throughNewMessages
}
}
// apparently this type of message was not yet seen, save it
msg.Messages = append(msg.Messages, newEv)
}
return msg
}
2025-01-06 23:09:41 +00:00
func MakeThrottleSync(sleeper Sleeper, logger *log.Logger, wg *sync.WaitGroup) *ThrottleSync {
events := make(chan GenericMessage)
throttle := ThrottleSync{SyncFilterImpl[GenericMessage]{}, events}
wg.Add(1)
go func() {
timeoutEvents := make(chan interface{})
var currentEvent *GenericMessage = nil
loop:
for {
select {
case ev, ok := <-events:
if !ok {
break loop
}
if currentEvent == nil {
logger.Print("Waiting for more messages to arrive before sending...")
sleeper.Sleep(timeoutEvents)
}
currentEvent = appendToGenericMessage(currentEvent, &ev)
case <-timeoutEvents:
logger.Print("Time's up, sending all messages we've got for now.")
throttle.CallNext(*currentEvent)
currentEvent = nil
}
}
// If anything is left to be sent, send it now
if currentEvent != nil {
throttle.CallNext(*currentEvent)
}
wg.Done()
logger.Print("Throttling goroutine finishing")
}()
return &throttle
}
func (throttle *ThrottleSync) Close() { close(throttle.events) }
func (throttle *ThrottleSync) Call(msg GenericMessage) {
throttle.events <- msg
}