Время OPA PrepareForEval увеличивается экспоненциально
Мне нужно, чтобы мое приложение могло загружать политики (rego), а затем оценивать входной JSON на основе определенных политик.
Я по ошибке использовал PrepareForEval
в моем оценочном API вместо API политики загрузки. Результат меня удивил, поскольку время отклика продолжало экспоненциально увеличиваться после каждой оценки, в то время как правила оставались неизменными. Хотя после этого я понял и изменил свою логику на вызовPrepareForEval
во время загрузки политики, а затем сохраните подготовленный экземпляр запроса в моем экземпляре структуры. Но меня все еще беспокоит, если метод подготовки выполняется несколько раз при загрузке политик, тогда это все равно станет дорогостоящей операцией.
Итак, было бы здорово указать на правильный способ использования метода подготовки.
Образец кода:
// My provider
func init() {
cachedRego := rego.New(rego.Query("data.report"))
}
// My load policy method
func loadPolicy(ctx context.Context, filename, regoPolicy string) {
mod, err := ast.ParseModule(filename, regoPolicy)
rego.ParsedModule(mod)(cachedRego)
}
// My evaluate method
func eval(ctx context.Context, input interface{}) {
// after loading my policies, the following call took 1s, 2s, 5s, 10s,... respectively on eval calls
preparedQuery, _ := cachedRego.PrepareForEval(ctx) // <- I've moved this to my load policy method and cached preparedQuery
// this doesn’t take much time
rs, _ := preparedQuery.Eval(ctx, rego.EvalInput(input))
}
// My use case
func main() {
// load policies and evaluate inputs
for _, p := range policySet1 {
loadPolicy(context.Background(), p.filename, p.regoPolicy)
}
for _, inp := range inputSet1 {
eval(context.Background(), inp)
}
// load more policies to the earlier set and evaluate another input set
for _, p := range policySet2 {
loadPolicy(context.Background(), p.filename, p.regoPolicy)
}
for _, inp := range inputSet2 {
eval(context.Background(), inp)
}
}
1 ответ
TL; DR; это, вероятно, не подходящее место для этого вопроса. Сообщите о проблеме на GitHub, если вы заметили неправильное поведение.
Чтобы ответить на ваш вопрос о том, как правильно подготовить запросы, ваша основная функция должна (как минимум) выглядеть так:
func main() {
pq1 := loadPolicies(policySet1)
for _, inp := range inputSet1 {
eval(pq1, inp)
}
pq2 := loadPolicies(policySet2)
for _, inp := range inputSet2 {
eval(pq2, inp)
}
}
Самый простой способ реализовать loadPolicies
для приведенного выше примера будет примерно так:
func loadPolicies(policySet) {
opts := []func(*rego.Rego){}
// setup prepared query. load all modules.
for _, p := range policySet {
opts = append(opts, rego.Module(p.filename, p.regoPolicy))
}
// create new prepared query
return rego.New(rego.Query("data.report"), opts...).PrepareForEval()
}
Тогда ваша функция eval станет:
func eval(pq, inp) {
rs, err := pq.Eval(rego.EvalInput(inp))
// handle err
// interpret rs
}