OpenGFW/ruleset/loader.go
Aionw 65cb64168d feat: rule set loader
Add rule set loader, move original config loader routine into
ruleset/loader.go
2024-03-02 15:20:55 +08:00

73 lines
1.6 KiB
Go

package ruleset
import (
"os"
"os/signal"
"sync"
"syscall"
"github.com/apernet/OpenGFW/analyzer"
"github.com/apernet/OpenGFW/modifier"
"go.uber.org/zap"
)
type RuleSetHandler func(Ruleset) error
type RuleSetLoader interface {
Start() error
}
type SignalRuleSetLoader struct {
o sync.Once
filePath string
handler RuleSetHandler
reloadChan chan os.Signal
analyzers []analyzer.Analyzer
modifiers []modifier.Modifier
config *BuiltinConfig
logger *zap.Logger
}
func NewSignalRuleSetLoader(path string, handler RuleSetHandler, ans []analyzer.Analyzer, mods []modifier.Modifier, cfg *BuiltinConfig) RuleSetLoader {
return &SignalRuleSetLoader{
o: sync.Once{},
filePath: path,
handler: handler,
reloadChan: make(chan os.Signal),
analyzers: ans,
modifiers: mods,
config: cfg,
}
}
func (l *SignalRuleSetLoader) Start() error {
l.o.Do(
func() {
signal.Notify(l.reloadChan, syscall.SIGHUP)
go func() {
for {
<-l.reloadChan
l.logger.Info("reloading rules")
rawRs, err := ExprRulesFromYAML(l.filePath)
if err != nil {
l.logger.Error("failed to load rules, using old rules", zap.Error(err))
continue
}
rs, err := CompileExprRules(rawRs, l.analyzers, l.modifiers, l.config)
if err != nil {
l.logger.Error("failed to compile rules, using old rules", zap.Error(err))
continue
}
err = l.handler(rs)
if err != nil {
l.logger.Error("failed to update ruleset", zap.Error(err))
} else {
l.logger.Info("rules reloaded")
}
}
}()
},
)
return nil
}