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?
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 -