feat(metering): meter request and response bytes - #1073
Conversation
P4 already hands the pricing device the inbound request in `estimate' and the result in `price'; both were discarded. Sizing them there puts bandwidth alongside `beam-reductions' in the same session, so a node can be priced on what it carried as well as what it computed, and a device that relays on another node's behalf needs no pricing logic of its own. Bodies are forced through `hb_cache:ensure_all_loaded/2' before sizing. A relayed payload arrives as unforced links and measures a few kilobytes whatever it refers to, so an unforced size is not a size. Sizes are of the ETF encoding rather than the wire form: stable and monotone in payload size, but not reproducible by a payer from the bytes it sent, and the ratio to wire size varies by request shape. Both resources are inert until an operator sets a rate. Tested via `rebar3 device test -m dev_metering': a 1 MB body prices above 100x a 1 KB one, and with no rates set both price to zero. Note that `rebar3 eunit --module=dev_metering' cannot see preloaded devices and reports the module missing.
| body_size(Req, Opts) when is_map(Req) -> | ||
| case hb_maps:get(<<"body">>, Req, not_found, Opts) of | ||
| not_found -> 0; | ||
| Body -> term_size(hb_cache:ensure_all_loaded(Body, Opts)) |
There was a problem hiding this comment.
I was thinking about this and concluded we definitely didn't want to do this, but only because it has a very bad pathological case. Imagine the node is about to return a giant linked message. It has (implicitly or not) accept-bundle: false. Subsequently, without this call it would happily just drop the value as +link in the result and it would be tiny. With this call we [tl;dr] get completely rekt.
The behavior we actually want is dependent, I think, on whether the body message has a commitment with bundle: true in it. There is still a situation where that goes wrong I think (codec devices that support the brainfucking 'unbundled encoding of a bundle: true commitment case) but we shouldn't encounter that with any frequency, I think. Famous last words...
To easily pick out whether the body message has a bundle: true commitment hb_message:commitment[s] is your friend.
There was a problem hiding this comment.
Right -- fixed by only loading linked body content when a bundle commitment includes it, with a test covering bundled / unbundled responses
Only load linked body content when a bundle commitment includes it. This preserves link-sized metering for unbundled messages while charging for committed bundled content.
Extend metering@1.0 with request-bytes and response-bytes resources while retaining beam-reductions. Payloads are forced before sizing; rates remain operator-configured and default to zero.