Conditions (ee version) (#1858)

* feat(backend): moved conditions to ee folder

* feat(backend): fixed typo
This commit is contained in:
Alexander 2024-01-26 14:03:29 +01:00 committed by GitHub
parent 4711bf28f0
commit 354f071fb0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 180 additions and 148 deletions

View file

@ -0,0 +1,11 @@
package router
import (
"errors"
"net/http"
"time"
)
func (e *Router) getConditions(w http.ResponseWriter, r *http.Request) {
ResponseWithError(w, http.StatusNotImplemented, errors.New("no support"), time.Now(), r.URL.Path, 0)
}

View file

@ -645,32 +645,3 @@ func (e *Router) getTags(w http.ResponseWriter, r *http.Request) {
}
ResponseWithJSON(w, &UrlResponse{Tags: tags}, startTime, r.URL.Path, bodySize)
}
func (e *Router) getConditions(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
bodySize := 0
// Check authorization
_, err := e.services.Tokenizer.ParseFromHTTPRequest(r)
if err != nil {
ResponseWithError(w, http.StatusUnauthorized, err, startTime, r.URL.Path, bodySize)
return
}
// Get taskID
vars := mux.Vars(r)
projID := vars["project"]
projectID, err := strconv.Atoi(projID)
if err != nil {
ResponseWithError(w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
return
}
// Get task info
info, err := e.services.Conditions.Get(uint32(projectID))
if err != nil {
ResponseWithError(w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
return
}
ResponseWithJSON(w, info, startTime, r.URL.Path, bodySize)
}

View file

@ -1,129 +1,13 @@
package conditions
import (
"fmt"
"log"
"openreplay/backend/pkg/db/postgres/pool"
)
type Conditions interface {
Get(projectID uint32) (*Response, error)
GetRate(projectID uint32, condition string) (int, error)
}
type Conditions interface{}
type conditionsImpl struct {
db pool.Pool
cache map[uint32]map[string]int // projectID -> condition -> rate
}
type conditionsImpl struct{}
func New(db pool.Pool) Conditions {
return &conditionsImpl{
db: db,
cache: make(map[uint32]map[string]int),
}
}
type ConditionType string
const (
VisitedURL ConditionType = "visited_url"
RequestURL ConditionType = "request_url"
ClickLabel ConditionType = "click_label"
ClickSelector ConditionType = "click_selector"
CustomEvent ConditionType = "custom_event"
Exception ConditionType = "exception"
FeatureFlag ConditionType = "feature_flag"
SessionDuration ConditionType = "session_duration"
)
type ConditionOperator string
const (
Is ConditionOperator = "is"
IsNot ConditionOperator = "isNot"
Contains ConditionOperator = "contains"
NotContains ConditionOperator = "notContains"
StartsWith ConditionOperator = "startsWith"
EndsWith ConditionOperator = "endsWith"
)
type Condition struct {
Type ConditionType `json:"type"`
Operator ConditionOperator `json:"operator"`
Values []string `json:"value"`
}
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) (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
return &conditionsImpl{}
}

View file

@ -0,0 +1,37 @@
package router
import (
"github.com/gorilla/mux"
"net/http"
"strconv"
"time"
)
func (e *Router) getConditions(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
bodySize := 0
// Check authorization
_, err := e.services.Tokenizer.ParseFromHTTPRequest(r)
if err != nil {
ResponseWithError(w, http.StatusUnauthorized, err, startTime, r.URL.Path, bodySize)
return
}
// Get taskID
vars := mux.Vars(r)
projID := vars["project"]
projectID, err := strconv.Atoi(projID)
if err != nil {
ResponseWithError(w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
return
}
// Get task info
info, err := e.services.Conditions.Get(uint32(projectID))
if err != nil {
ResponseWithError(w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
return
}
ResponseWithJSON(w, info, startTime, r.URL.Path, bodySize)
}

View file

@ -0,0 +1,129 @@
package conditions
import (
"fmt"
"log"
"openreplay/backend/pkg/db/postgres/pool"
)
type Conditions interface {
Get(projectID uint32) (*Response, error)
GetRate(projectID uint32, condition string) (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 ConditionType string
const (
VisitedURL ConditionType = "visited_url"
RequestURL ConditionType = "request_url"
ClickLabel ConditionType = "click_label"
ClickSelector ConditionType = "click_selector"
CustomEvent ConditionType = "custom_event"
Exception ConditionType = "exception"
FeatureFlag ConditionType = "feature_flag"
SessionDuration ConditionType = "session_duration"
)
type ConditionOperator string
const (
Is ConditionOperator = "is"
IsNot ConditionOperator = "isNot"
Contains ConditionOperator = "contains"
NotContains ConditionOperator = "notContains"
StartsWith ConditionOperator = "startsWith"
EndsWith ConditionOperator = "endsWith"
)
type Condition struct {
Type ConditionType `json:"type"`
Operator ConditionOperator `json:"operator"`
Values []string `json:"value"`
}
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) (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
}