Search code examples
open-policy-agentrego

Are Rego function calls memoized?


I have defined a function that is not idempotent; it can return different results for the same inputs. Does Rego memoize the result of the function on each query? In other words, given the following policy:

val := myFunc(...) # Returns an object with "a" and "b" fields.

foo {
    val.a
}

bar {
    val.b
}

Rules foo and bar would operate on the same val which resulted from a single call to myFunc. Does Rego guarantee this?


Solution

  • Except for http.send, I don't think there are any builtins that would allow you to return different data provided the same input. I'd be curious to find out though! :)

    To answer your question, a rule/function is cached in the scope of a single query, so multiple calls to the same rule/function won't be re-evaluated. The http.send builtin additionally allows you to cache results across queries, which can be very useful when requesting data which is rarely updated.

    Speaking of http.send, it's a pretty useful builtin to test things like this. Just fire up a local webserver, e.g. python3 -m http.server and then have a policy that queries that:

    package policy
    
    my_func(x) {
        http.send({
            "method": "GET",
            "url": "http://localhost:8000",
        })
    }
    
    boo := my_func("x")
    foo := my_func("x")
    

    Then evaluate the policy:

    opa eval -f pretty -d policy.rego data.policy
    {
      "boo": true,
      "foo": true
    }
    

    Checking the logs of the web server, you'll see that only one request was sent despite two rules calling the my_func function:

    ::1 - - [29/Jun/2022 19:27:01] "GET / HTTP/1.1" 200 -