feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
Этот коммит содержится в:
86
app/models/contact.go
Обычный файл
86
app/models/contact.go
Обычный файл
@@ -0,0 +1,86 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/datatypes"
|
||||
|
||||
"rsgit.ru/rsmon/rsmon/app/models/concerns"
|
||||
)
|
||||
|
||||
// Contact represents a notification contact.
|
||||
//
|
||||
// Ownership / tenancy:
|
||||
//
|
||||
// - A Contact belongs to exactly one Account (tenant). AccountID may be
|
||||
// nil for system-level admin contacts (see SystemContacts).
|
||||
// - A Contact may belong to at most one User. UserID is set when the
|
||||
// contact was created on behalf of a specific user (the typical
|
||||
// case for self-service "My email" / "My Telegram" contacts) and is
|
||||
// nil for account-wide contacts.
|
||||
//
|
||||
// `User` is omitempty because most list payloads don't preload it; the
|
||||
// `/settings/users` page loads it server-side via the AccountUserRow
|
||||
// payload.
|
||||
type Contact struct {
|
||||
concerns.Model
|
||||
|
||||
AccountID *int64 `json:"account_id" gorm:"type:bigint REFERENCES accounts(id)"`
|
||||
Account *Account `json:"-"`
|
||||
UserID *int64 `gorm:"type:bigint REFERENCES users(id)" json:"user_id"`
|
||||
User *User `json:"user,omitempty"`
|
||||
Name string `json:"name" gorm:"not null"`
|
||||
Kind string `json:"kind" gorm:"not null;index:contact_value"`
|
||||
Value string `json:"value" gorm:"index:contact_value"`
|
||||
Enabled bool `json:"enabled" gorm:"not null;default:true"`
|
||||
Data datatypes.JSON `json:"data"`
|
||||
IsSystem *bool `json:"is_system" gorm:"default:false"`
|
||||
Notifications []Notification `json:"-" gorm:"many2many:notification_contacts;"`
|
||||
NotificationsCount int `gorm:"-:all" json:"notifications_count"`
|
||||
MonitorsCount int `gorm:"-:all" json:"monitors_count"`
|
||||
Messages []Message `json:"-"`
|
||||
|
||||
concerns.Timestamped
|
||||
concerns.HasToken
|
||||
Audited
|
||||
}
|
||||
|
||||
// SystemContacts returns all contacts marked as system/admin (is_system=true).
|
||||
// These are the contacts distributed workers notify directly when the main
|
||||
// API is unreachable (see docs/worker-protocol.md "System Selfcheck").
|
||||
func SystemContacts() ([]Contact, error) {
|
||||
var contacts []Contact
|
||||
err := DB().Where("is_system = ? AND enabled = ?", true, true).Find(&contacts).Error
|
||||
return contacts, err
|
||||
}
|
||||
|
||||
// ContactsCounts fills NotificationsCount and MonitorsCount for each contact.
|
||||
func ContactsCounts(contacts *[]Contact) {
|
||||
groupIDs := make(map[int64]bool, 0)
|
||||
groupCount := make(map[int64]int, 0)
|
||||
|
||||
for i, c := range *contacts { //nolint:gocritic // range copy is acceptable here
|
||||
(*contacts)[i].NotificationsCount = len(c.Notifications)
|
||||
for _, n := range c.Notifications { //nolint:gocritic // range copy is acceptable here
|
||||
for _, g := range n.Groups { //nolint:gocritic // range copy is acceptable here
|
||||
groupIDs[g.ID] = true
|
||||
groupCount[g.ID] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gids := make([]int64, 0, len(groupIDs))
|
||||
for g := range groupIDs {
|
||||
gids = append(gids, g)
|
||||
}
|
||||
|
||||
CountGroups(gids, &groupCount)
|
||||
|
||||
for i, c := range *contacts { //nolint:gocritic // range copy is acceptable here
|
||||
cnt := 0
|
||||
for _, n := range c.Notifications { //nolint:gocritic // range copy is acceptable here
|
||||
for _, g := range n.Groups { //nolint:gocritic // range copy is acceptable here
|
||||
cnt += groupCount[g.ID]
|
||||
}
|
||||
}
|
||||
(*contacts)[i].MonitorsCount = cnt
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user