Class: ZeroClick::Sellers::Middleware::Meter
- Defined in:
- lib/zeroclick/sellers/middleware.rb
Overview
Guards a billable endpoint: verifies the signature, confirms the buyer can pay, and — if the app responds 2xx — reports the usage.
use ZeroClick::Sellers::Middleware::Meter,
seller: SELLER, service_slug: "extractor",
usage: [ZeroClick::Sellers::UsageItem.new(meter_slug: "requests", quantity: 1)]
Inside the app, the request body still reads normally: verification consumes rack.input and this replaces it with a fresh stream over the same bytes.
Every usage item must carry an explicit quantity, and it refuses the others at wire-up. Meter settles usage automatically from what it declared, so an item with only a max_quantity ceiling — or with neither quantity nor max_quantity — has no settled amount, and inventing one would silently mis-bill a delivered 200. That is the exact failure this SDK exists to prevent, so it fails when you build the middleware rather than in production: declare a fixed quantity here and report the variable part with Client#report_usage.
Instance Method Summary collapse
-
#initialize(app, service_slug:, usage:, seller: nil, plan_slug: nil, max_body_bytes: DEFAULT_MAX_BODY_BYTES) ⇒ Meter
constructor
A new instance of Meter.
Methods inherited from Base
Constructor Details
#initialize(app, service_slug:, usage:, seller: nil, plan_slug: nil, max_body_bytes: DEFAULT_MAX_BODY_BYTES) ⇒ Meter
Returns a new instance of Meter.
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/zeroclick/sellers/middleware.rb', line 186 def initialize(app, service_slug:, usage:, seller: nil, plan_slug: nil, max_body_bytes: DEFAULT_MAX_BODY_BYTES) super(app, seller: seller, service_slug: service_slug, max_body_bytes: max_body_bytes) @usage = Sellers.normalize_usage(usage, operation: "Middleware::Meter", allow_empty: false) @plan_slug = plan_slug # Meter settles usage from what it declared, so every item must carry # a definite quantity. An item that does not — a max_quantity ceiling, # or one that defers to the meter's configured per-request default — # has no settled amount here, and inventing one would silently # mis-bill a delivered 200. That is the exact failure this SDK exists # to prevent, so it fails at wire-up rather than in production. indefinite = @usage.find { |item| item.quantity.nil? } return unless indefinite raise Error.new("malformed_input", operation: "Middleware::Meter", meter_slug: indefinite.meter_slug, message: "Middleware::Meter needs an explicit quantity on every usage item, and " \ "#{indefinite.meter_slug} has none. It settles usage from what it " \ "declares, so an item carrying a max_quantity ceiling — or neither " \ "quantity nor max_quantity — has no settled amount to report. Declare a " \ "fixed quantity here and report the variable part with Client#report_usage.") end |