first commit
This commit is contained in:
99
framework/configstore/tables/routing_rules.go
Normal file
99
framework/configstore/tables/routing_rules.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package tables
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
bifrost "github.com/maximhq/bifrost/core"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// TableRoutingRule represents a routing rule in the database
|
||||
type TableRoutingRule struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(255)" json:"id"`
|
||||
ConfigHash string `gorm:"type:varchar(255)" json:"config_hash"` // Hash of config.json version, used for change detection
|
||||
Name string `gorm:"type:varchar(255);not null;uniqueIndex:idx_routing_rule_scope_name" json:"name"`
|
||||
Description string `gorm:"type:text" json:"description"`
|
||||
Enabled bool `gorm:"not null;default:true" json:"enabled"`
|
||||
CelExpression string `gorm:"type:text;not null" json:"cel_expression"`
|
||||
|
||||
// Routing Targets (output) — 1:many relationship; weights must sum to 1
|
||||
Targets []TableRoutingTarget `gorm:"foreignKey:RuleID;constraint:OnDelete:CASCADE" json:"targets"`
|
||||
|
||||
Fallbacks *string `gorm:"type:text" json:"-"` // JSON array of fallback chains
|
||||
ParsedFallbacks []string `gorm:"-" json:"fallbacks,omitempty"` // Parsed fallbacks from JSON
|
||||
|
||||
Query *string `gorm:"type:text" json:"-"`
|
||||
ParsedQuery map[string]any `gorm:"-" json:"query,omitempty"`
|
||||
|
||||
// Scope: where this rule applies
|
||||
Scope string `gorm:"type:varchar(50);not null;uniqueIndex:idx_routing_rule_scope_name" json:"scope"` // "global" | "team" | "customer" | "virtual_key"
|
||||
ScopeID *string `gorm:"type:varchar(255);uniqueIndex:idx_routing_rule_scope_name" json:"scope_id"` // nil for global, otherwise entity ID
|
||||
|
||||
// Chaining
|
||||
ChainRule bool `gorm:"not null;default:false" json:"chain_rule"` // If true, re-evaluates routing chain after this rule matches
|
||||
|
||||
// Execution
|
||||
Priority int `gorm:"type:int;not null;default:0;index" json:"priority"` // Lower = evaluated first within scope
|
||||
|
||||
// Timestamps
|
||||
CreatedAt time.Time `gorm:"index;not null" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"index;not null" json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName for TableRoutingRule
|
||||
func (TableRoutingRule) TableName() string { return "routing_rules" }
|
||||
|
||||
// BeforeSave hook for TableRoutingRule to serialize JSON fields
|
||||
func (r *TableRoutingRule) BeforeSave(tx *gorm.DB) error {
|
||||
if len(r.ParsedFallbacks) > 0 {
|
||||
data, err := sonic.Marshal(r.ParsedFallbacks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Fallbacks = bifrost.Ptr(string(data))
|
||||
} else {
|
||||
r.Fallbacks = nil
|
||||
}
|
||||
if r.ParsedQuery != nil {
|
||||
data, err := sonic.Marshal(r.ParsedQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Query = bifrost.Ptr(string(data))
|
||||
} else {
|
||||
r.Query = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AfterFind hook for TableRoutingRule to deserialize JSON fields
|
||||
func (r *TableRoutingRule) AfterFind(tx *gorm.DB) error {
|
||||
if r.Fallbacks != nil && strings.TrimSpace(*r.Fallbacks) != "" {
|
||||
if err := sonic.Unmarshal([]byte(*r.Fallbacks), &r.ParsedFallbacks); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if r.Query != nil && strings.TrimSpace(*r.Query) != "" {
|
||||
if err := sonic.Unmarshal([]byte(*r.Query), &r.ParsedQuery); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TableRoutingTarget represents a weighted routing target for probabilistic routing.
|
||||
// Multiple targets can be associated with a single routing rule; weights determine
|
||||
// the probability of each target being selected and must sum to 1 across all targets in a rule.
|
||||
// The composite (RuleID, Provider, Model, KeyID) is unique to prevent duplicate target configs.
|
||||
type TableRoutingTarget struct {
|
||||
RuleID string `gorm:"type:varchar(255);not null;index;uniqueIndex:idx_routing_target_config" json:"-"`
|
||||
Provider *string `gorm:"type:varchar(255);uniqueIndex:idx_routing_target_config" json:"provider,omitempty"` // nil = use incoming provider
|
||||
Model *string `gorm:"type:varchar(255);uniqueIndex:idx_routing_target_config" json:"model,omitempty"` // nil = use incoming model
|
||||
KeyID *string `gorm:"type:varchar(255);uniqueIndex:idx_routing_target_config" json:"key_id,omitempty"` // nil = no key pin
|
||||
Weight float64 `gorm:"not null;default:1" json:"weight"` // must sum to 1 across all targets in a rule
|
||||
}
|
||||
|
||||
// TableName for TableRoutingTarget
|
||||
func (TableRoutingTarget) TableName() string { return "routing_targets" }
|
||||
Reference in New Issue
Block a user