openreplay/ee/backend/pkg/conditions/conditions.go

99 lines
2.2 KiB
Go

package conditions
import (
"fmt"
"log"
"openreplay/backend/pkg/db/postgres/pool"
)
type Conditions interface {
Get(projectID uint32) (*Response, error)
GetRate(projectID uint32, condition string, def int) (int, error)
}
type conditionsImpl struct {
db pool.Pool
cache map[uint32]map[string]int // projectID -> condition -> rate
}
func New(db pool.Pool) Conditions {
return &conditionsImpl{
db: db,
cache: make(map[uint32]map[string]int),
}
}
type ConditionSet struct {
Name string `json:"name"`
Filters interface{} `json:"filters"`
Rate int `json:"capture_rate"`
}
type Response struct {
Conditions interface{} `json:"conditions"`
}
func (c *conditionsImpl) getConditions(projectID uint32) ([]ConditionSet, error) {
var conditions []ConditionSet
rows, err := c.db.Query(`
SELECT name, capture_rate, filters
FROM projects_conditions
WHERE project_id = $1
`, projectID)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var name string
var rate int
var filters interface{}
if err := rows.Scan(&name, &rate, &filters); err != nil {
log.Printf("can't scan row: %s", err)
continue
}
conditions = append(conditions, ConditionSet{
Name: name,
Filters: filters,
Rate: rate,
})
}
// Save project's conditions to cache
conditionSet := make(map[string]int)
for _, condition := range conditions {
conditionSet[condition.Name] = condition.Rate
}
c.cache[projectID] = conditionSet
if conditions == nil {
return []ConditionSet{}, nil
}
return conditions, nil
}
func (c *conditionsImpl) Get(projectID uint32) (*Response, error) {
conditions, err := c.getConditions(projectID)
return &Response{Conditions: conditions}, err
}
func (c *conditionsImpl) GetRate(projectID uint32, condition string, def int) (int, error) {
proj, ok := c.cache[projectID]
if ok {
rate, ok := proj[condition]
if ok {
return rate, nil
}
}
// Don't have project's conditions in cache or particular condition
_, err := c.getConditions(projectID)
if err != nil {
return 0, err
}
rate, ok := c.cache[projectID][condition]
if !ok {
return 0, fmt.Errorf("condition %s not found", condition)
}
return rate, nil
}