首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OPA PrepareForEval时间呈指数增长

OPA PrepareForEval时间呈指数增长
EN

Stack Overflow用户
提问于 2020-06-22 17:33:35
回答 1查看 96关注 0票数 0

我需要我的应用程序能够加载策略(rego),然后根据定义的策略评估输入JSON。

我错误地在我的评估API中使用了PrepareForEval,而不是load policy API。这个结果让我很惊讶,因为每次评估后响应时间都会呈指数级增长,而策略保持不变。不过,在此之后,我意识到并更改了我的逻辑,在加载策略时调用PrepareForEval方法,然后将准备好的查询实例存储在我的结构实例中。但我仍然担心,如果在加载策略时多次执行prepare方法,那么它仍然会成为一个昂贵的操作。

因此,如果能正确地使用prepare方法,那就太好了。

示例代码:

代码语言:javascript
复制
// 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)
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-23 00:07:58

TLDR;这可能不是这个问题的正确位置。如果你看到你认为是错误的行为,就在GitHub上提交一个问题。

为了回答你关于如何正确地准备查询的问题,你的main函数应该(至少)看起来像这样:

代码语言:javascript
复制
func main() {
  pq1 := loadPolicies(policySet1)
  
  for _, inp := range inputSet1 {
    eval(pq1, inp)
  }

  pq2 := loadPolicies(policySet2)
 
  for _, inp := range inputSet2 {
    eval(pq2, inp)
  }
}

为上述示例实现loadPolicies的最简单方法如下所示:

代码语言:javascript
复制
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函数变成:

代码语言:javascript
复制
func eval(pq, inp) {
   rs, err := pq.Eval(rego.EvalInput(inp))
   // handle err
   // interpret rs
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62511382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档