lightninglabs / lightninglabs/aperture

meterd: bound stranded reservations with a TTL

Open
#253 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement metering
Dominant language
Go
Stars
268
Forks
78
Avg merge
22h 25m
Merged PRs (30d)
1

Description

Follow-up from the review of #247, which fixed the reservation leaks that were reachable through normal request flow (the rate limiter running after the reservation, a backend that never answered skipping ModifyResponse, and protocol upgrades returning early). What remains is the ops-event tail, and it wants a backstop rather than another targeted fix.

What is still open

AuthorizeRequest reserves an estimate and only a usage report gives it back. After #247 the report is sent on every path the proxy controls, but not when the process loses the ability to send one at all:

  • the pricer is down through all four reportUsageWithRetry attempts
  • aperture crashes or is restarted between authorize and report
  • a handler panics somewhere between the two

Bundle.Reserved is deliberately not persisted (store.go, the json:"-" tag), so a meterd restart clears it. That is the only thing clearing it today. Until then available = RemainingTokens - Reserved stays depressed, and enough stranded reservations make a bundle with real balance read as exhausted, at which point the buyer is told to purchase another one.

What to do

Give a reservation a TTL and sweep expired ones, on the order of ten times reportTimeout so a slow-but-succeeding report is never swept out from under itself. The existing ExpireStale janitor is the natural place to hang it.

Two details worth getting right:

  • A swept reservation must not double-release if the late report eventually lands. Recording reservations individually rather than as a single counter per bundle would make that natural, at the cost of more state.
  • The sweep needs the same eviction age floor that #247 added for un-paid bundles, so a young reservation on an in-flight long request is never reaped.

Acceptance

  • A reservation whose report never arrives is released within a bounded window.
  • A late report after a sweep does not release twice.
  • An in-flight request longer than the report timeout is not swept.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Bundle.Reserved and the json:"-" handling in store.go, then trace AuthorizeRequest, reportUsageWithRetry, and the existing ExpireStale janitor. Determine how reservations can be tracked individually and how the #247 eviction age floor applies. Done means abandoned reservations are released within a bounded window, late reports do not release twice, and long in-flight requests are not swept.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.