feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
Этот коммит содержится в:
108
app/models/plan.go
Обычный файл
108
app/models/plan.go
Обычный файл
@@ -0,0 +1,108 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"rsgit.ru/rsmon/rsmon/app/models/concerns"
|
||||
)
|
||||
|
||||
var canonicalPlanCodes = []string{"free", "solo", "team", "enterprise"}
|
||||
|
||||
// CanonicalPlanCodes returns the supported public catalog codes.
|
||||
func CanonicalPlanCodes() []string {
|
||||
return append([]string(nil), canonicalPlanCodes...)
|
||||
}
|
||||
|
||||
// Plan is a versioned-by-code catalog entry. A zero cap means unlimited.
|
||||
type Plan struct {
|
||||
concerns.Model
|
||||
|
||||
Code string `gorm:"size:32;not null" json:"code"`
|
||||
NameRU string `gorm:"size:64;not null" json:"name_ru"`
|
||||
NameEN string `gorm:"size:64;not null" json:"name_en"`
|
||||
PriceMonthlyMinor int64 `gorm:"not null;default:0" json:"price_monthly_minor"`
|
||||
PriceAnnualMinor int64 `gorm:"not null;default:0" json:"price_annual_minor"`
|
||||
Currency string `gorm:"size:3;not null;default:'RUB'" json:"currency"`
|
||||
MonitorCap int64 `gorm:"not null;default:0" json:"monitor_cap"`
|
||||
IntervalMinSeconds int `gorm:"not null;default:30" json:"interval_min_seconds"`
|
||||
StatusPagesCap int64 `gorm:"not null;default:0" json:"status_pages_cap"`
|
||||
MaintenanceCap int64 `gorm:"not null;default:0" json:"maintenance_cap"`
|
||||
LoginSeatsIncluded int64 `gorm:"not null;default:0" json:"login_seats_included"`
|
||||
NotifySeatsIncluded int64 `gorm:"not null;default:0" json:"notify_seats_included"`
|
||||
UnlimitedSeats bool `gorm:"not null;default:false" json:"unlimited_seats"`
|
||||
Integrations pq.StringArray `gorm:"type:text[];not null;default:'{}'" json:"integrations"`
|
||||
CheckKinds pq.StringArray `gorm:"type:text[];not null;default:'{}'" json:"check_kinds"`
|
||||
DataRetentionMonths int `gorm:"not null;default:3" json:"data_retention_months"`
|
||||
DistributedWorkers bool `gorm:"not null;default:false" json:"distributed_workers"`
|
||||
Confirmations bool `gorm:"not null;default:false" json:"confirmations"`
|
||||
AllowHardAlerts bool `gorm:"not null;default:false" json:"allow_hard_alerts"`
|
||||
ConfirmTimeoutSec int `gorm:"not null;default:90" json:"confirm_timeout_sec"`
|
||||
HealthWindowSec int `gorm:"not null;default:300" json:"health_window_sec"`
|
||||
HealthRateThreshold float64 `gorm:"not null;default:0.5" json:"health_rate_threshold"`
|
||||
HealthMinAttempts int `gorm:"not null;default:10" json:"health_min_attempts"`
|
||||
SOC2 bool `gorm:"not null;default:false" json:"soc2"`
|
||||
GDPRDPA bool `gorm:"not null;default:false" json:"gdpr_dpa"`
|
||||
IsDefault bool `gorm:"not null;default:false" json:"is_default"`
|
||||
Archived bool `gorm:"not null;default:false" json:"archived"`
|
||||
|
||||
// Deprecated source-compatibility fields. The legacy plans table is retained
|
||||
// as plans_legacy; these values are never written to the canonical catalog.
|
||||
Default bool `gorm:"-" json:"Default,omitempty"`
|
||||
Name string `gorm:"-" json:"Name,omitempty"`
|
||||
HTTPMonitors *int64 `gorm:"-" json:"HTTPMonitors,omitempty"`
|
||||
DNSMonitors *int64 `gorm:"-" json:"DNSMonitors,omitempty"`
|
||||
WHOISMonitors *int64 `gorm:"-" json:"WHOISMonitors,omitempty"`
|
||||
TotalMonitors *int64 `gorm:"-" json:"TotalMonitors,omitempty"`
|
||||
Price int `gorm:"-" json:"Price,omitempty"`
|
||||
TrialPeriod int `gorm:"-" json:"TrialPeriod,omitempty"`
|
||||
|
||||
concerns.Timestamped
|
||||
Audited
|
||||
}
|
||||
|
||||
func (p *Plan) BeforeCreate(_ *gorm.DB) error {
|
||||
if p.Code == "" {
|
||||
p.Code = "legacy-" + uuid.NewString()[:24]
|
||||
}
|
||||
if p.NameRU == "" {
|
||||
p.NameRU = p.Name
|
||||
}
|
||||
if p.NameEN == "" {
|
||||
p.NameEN = p.NameRU
|
||||
}
|
||||
if p.Currency == "" {
|
||||
p.Currency = "RUB"
|
||||
}
|
||||
if p.IntervalMinSeconds == 0 {
|
||||
p.IntervalMinSeconds = 30
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plan) AfterFind(_ *gorm.DB) error {
|
||||
p.Name = p.NameRU
|
||||
p.Price = int(p.PriceMonthlyMinor / 100)
|
||||
p.Default = p.IsDefault
|
||||
p.TotalMonitors = &p.MonitorCap
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultPlan returns the canonical free plan.
|
||||
func DefaultPlan() Plan {
|
||||
pl := Plan{}
|
||||
if err := DB().Where("code = ? AND archived = FALSE", "free").First(&pl).Error; err != nil {
|
||||
log.Println("unable to find default plan")
|
||||
panic(err)
|
||||
}
|
||||
return pl
|
||||
}
|
||||
|
||||
// AllowsDistributed keeps legacy callers working while using the canonical
|
||||
// entitlement flag for catalog plans.
|
||||
func (p *Plan) AllowsDistributed() bool {
|
||||
return p != nil && (p.DistributedWorkers || p.Price > 0)
|
||||
}
|
||||
Ссылка в новой задаче
Block a user