feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
Этот коммит содержится в:
193
app/models/notification.go
Обычный файл
193
app/models/notification.go
Обычный файл
@@ -0,0 +1,193 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"rsgit.ru/rsmon/rsmon/app/models/concerns"
|
||||
"rsgit.ru/rsmon/rsmon/internal/workdays"
|
||||
)
|
||||
|
||||
// Notification provides functionality.
|
||||
type Notification struct {
|
||||
concerns.Model
|
||||
|
||||
Name string `json:"name" gorm:"not null"`
|
||||
AccountID int64 `gorm:"type:bigint REFERENCES accounts(id)" json:"account_id"`
|
||||
Account *Account `json:"-"`
|
||||
Enabled bool `gorm:"not null;default:true" json:"enabled"`
|
||||
ContactIDs []int64 `gorm:"-:all" json:"contact_ids"`
|
||||
Contacts []Contact `gorm:"many2many:notification_contacts;" json:"contacts,omitempty"`
|
||||
GroupIDs []int64 `gorm:"-:all" json:"group_ids"`
|
||||
Groups []Group `gorm:"many2many:notification_groups;" json:"-"`
|
||||
AlertDelay *int64 `json:"alert_delay,omitempty"`
|
||||
// RepeatAlert *int64 `json:"repeat_alert,omitempty"`
|
||||
BeforeExpiration *int64 `json:"before_expiration,omitempty"`
|
||||
|
||||
NotifyDown bool `gorm:"default:true" json:"notify_down"`
|
||||
NotifyRestore bool `gorm:"default:true" json:"notify_restore"`
|
||||
|
||||
NotifyWHOIS bool `gorm:"default:true" json:"notify_whois"`
|
||||
NotifySSL bool `gorm:"default:true" json:"notify_ssl"`
|
||||
|
||||
NotifyDays *int `json:"notify_days"`
|
||||
NotifyDayStart *int `json:"notify_day_start"`
|
||||
NotifyDayEnd *int `json:"notify_day_end"`
|
||||
NotifyHolidays bool `gorm:"default:true" json:"notify_holidays"`
|
||||
|
||||
Messages []Message `json:"-"`
|
||||
|
||||
concerns.Timestamped
|
||||
Audited
|
||||
}
|
||||
|
||||
const notificationDebug = false
|
||||
|
||||
// EnabledNow checks if the notification is enabled at the given time.
|
||||
func (n *Notification) EnabledNow(tn *time.Time) bool {
|
||||
weekday := int(tn.Weekday())
|
||||
// делаем из 0-воскр 1-пн 6-сб вариант 0-пн 6-воскр
|
||||
if weekday == 0 {
|
||||
weekday = 7
|
||||
}
|
||||
weekday--
|
||||
if notificationDebug {
|
||||
log.Println("notification", n.ID, "check enabled now at", tn, "for day", weekday)
|
||||
}
|
||||
|
||||
if !n.NotifyHolidays {
|
||||
c := workdays.GetCalendar()
|
||||
if !c.IsWorkday(*tn) {
|
||||
if notificationDebug {
|
||||
log.Println("notification", n.ID, "is not enabled on holiday", tn)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
minusOneDay := false
|
||||
notifyFromDay := true
|
||||
|
||||
if n.NotifyDayStart != nil && n.NotifyDayEnd != nil {
|
||||
bod := BeginningOfDay(*tn)
|
||||
secondsToday := int(tn.Sub(bod) / time.Second)
|
||||
|
||||
ds := *n.NotifyDayStart
|
||||
de := *n.NotifyDayEnd
|
||||
// вариант 9 утра - 2 часа ночи
|
||||
if ds == de { //nolint:gocritic // complex condition chain
|
||||
notifyFromDay = true
|
||||
} else if ds > de {
|
||||
// с 0 до DayEnd
|
||||
if secondsToday < de { //nolint:gocritic // complex condition chain
|
||||
minusOneDay = true
|
||||
notifyFromDay = true
|
||||
} else if secondsToday < ds {
|
||||
// с DayEnd до DayStart
|
||||
notifyFromDay = false
|
||||
} else {
|
||||
notifyFromDay = true
|
||||
}
|
||||
} else {
|
||||
if secondsToday < ds { //nolint:gocritic // complex condition chain
|
||||
// с 0 до DayStart
|
||||
notifyFromDay = false
|
||||
} else if secondsToday > de {
|
||||
notifyFromDay = false
|
||||
} else {
|
||||
notifyFromDay = true
|
||||
}
|
||||
}
|
||||
// log.Println(secondsToday)
|
||||
}
|
||||
|
||||
if !notifyFromDay {
|
||||
if notificationDebug {
|
||||
log.Println("notification", n.ID, *n.NotifyDays, "is NOT enabled as notifyFromDay", tn)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Если время 0-dayStart считаем что это прошлый день
|
||||
if minusOneDay {
|
||||
weekday--
|
||||
if weekday < 0 {
|
||||
weekday = 6
|
||||
}
|
||||
}
|
||||
|
||||
if n.NotifyDays != nil {
|
||||
if !HasBit(*n.NotifyDays, uint(weekday)) {
|
||||
if notificationDebug {
|
||||
log.Println("notification", n.ID, *n.NotifyDays, "is NOT enabled on weekday", tn.Weekday(), weekday, tn)
|
||||
}
|
||||
return false
|
||||
}
|
||||
if notificationDebug {
|
||||
log.Println("notification", n.ID, *n.NotifyDays, "is enabled on weekday", tn.Weekday(), weekday, tn)
|
||||
}
|
||||
}
|
||||
|
||||
if notificationDebug {
|
||||
log.Println("notification", n.ID, *n.NotifyDays, "is enabled", tn)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NotificationLoadIDs provides functionality.
|
||||
func NotificationLoadIDs(notifications *[]Notification) {
|
||||
for i, n := range *notifications { //nolint:gocritic // range copy is acceptable here
|
||||
cids := make([]int64, len(n.Contacts))
|
||||
for i, c := range n.Contacts { //nolint:gocritic // range copy is acceptable here
|
||||
cids[i] = c.ID
|
||||
}
|
||||
(*notifications)[i].ContactIDs = cids
|
||||
|
||||
gids := make([]int64, len(n.Groups))
|
||||
for j, g := range n.Groups { //nolint:gocritic // range copy is acceptable here
|
||||
gids[j] = g.ID
|
||||
}
|
||||
(*notifications)[i].GroupIDs = gids
|
||||
}
|
||||
}
|
||||
|
||||
// PersistRelations provides functionality.
|
||||
func (n *Notification) PersistRelations() error {
|
||||
cts := make([]Contact, len(n.ContactIDs))
|
||||
for i, c := range n.ContactIDs {
|
||||
ct := Contact{}
|
||||
ct.ID = c
|
||||
cts[i] = ct
|
||||
}
|
||||
err := DB().Model(&n).Association("Contacts").Replace(cts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
grp := make([]Group, len(n.GroupIDs))
|
||||
for i, g := range n.GroupIDs {
|
||||
gr := Group{}
|
||||
gr.ID = g
|
||||
grp[i] = gr
|
||||
}
|
||||
err = DB().Model(&n).Association("Groups").Replace(grp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetContacts returns the contacts associated with this notification.
|
||||
// Errors are logged and an empty slice is returned instead of panicking so
|
||||
// that a single misconfigured notification cannot kill the scheduler goroutine
|
||||
// that processes expiry alerts (see internal/notifier.RunExp).
|
||||
func (n *Notification) GetContacts() []Contact {
|
||||
contacts := make([]Contact, 0)
|
||||
err := DB().Model(*n).Where("enabled = ?", true).Association("Contacts").Find(&contacts)
|
||||
if err != nil {
|
||||
log.Printf("notification %d: GetContacts failed: %v", n.ID, err)
|
||||
return contacts
|
||||
}
|
||||
return contacts
|
||||
}
|
||||
Ссылка в новой задаче
Block a user