Packages
one_flight
0.1.0
Collapse concurrent duplicate Elixir calls into one supervised execution per key.
Current section
Files
Jump to
Current section
Files
one_flight
ROADMAP.md
ROADMAP.md
# Roadmap
`one_flight` should stay small: the core package is a request-coalescing primitive,
not a cache, HTTP client, retry library, or JSON library. Integrations should be
added only when they make the primitive easier to apply without weakening that
boundary.
## v0.1: Single-node core
Status: implemented.
- Single-node `OneFlight.run/3` and `OneFlight.run!/3`.
- `OneFlight.async/3` and `OneFlight.await/2`.
- `OneFlight.forget/2`.
- `OneFlight.stats/2`.
- Supervised Task execution.
- Per-waiter timeouts.
- Demand-driven cancellation.
- Execution error capture for raise, exit, and throw.
- Telemetry events for collapsed work.
## v0.2: Cluster scope
Goal: keep the same call-site API while coalescing duplicate calls across a
connected Elixir cluster.
- Add `scope: :cluster`.
- Use the two-level design:
- level 1: local singleflight per node
- level 2: only local leaders enter cluster coordination
- Use `:global` name registration for level-2 coordination.
- Keep closures local; user functions never cross the wire.
- Add `:peer` tests for simultaneous candidates, leader-node death, and netsplit behavior.
- Document the honest guarantee: at most one execution per connected partition in steady state, with duplicate windows during membership changes.
## v0.3: Req integration
Goal: make outbound HTTP request coalescing ergonomic for projects that already use
Req.
Likely shape:
```elixir
Req.new()
|> OneFlight.Req.attach(name: MyApp.Flights, key: :url)
|> Req.get!(url: url)
```
Use cases:
- duplicate GET requests to the same upstream resource
- rate-limited APIs
- remote configuration fetches
- token introspection
- service discovery endpoints
The integration should let callers choose the key strategy, such as URL only,
method plus URL, or method plus URL plus request body hash.
## v0.4: Finch examples or helper
Goal: support lower-level HTTP users without forcing a Req dependency.
Start with README examples:
```elixir
OneFlight.run({:http, :get, url, headers_hash}, fn ->
Finch.build(:get, url, headers)
|> Finch.request(MyFinch)
end, name: MyApp.Flights)
```
Only add a dedicated helper if real users ask for it. A `OneFlight.Finch` module
is less obviously valuable than a Req step because Finch intentionally has a small
low-level API.
## Poison and JSON workloads
Poison is a use case, not an integration target.
Good uses:
- coalesce loading and decoding the same large remote JSON config
- avoid duplicate parse work after a cache miss
- dedupe expensive schema/source transformations keyed by content hash
Avoid a `OneFlight.Poison` module unless a concrete repeated pattern appears.
JSON libraries are easy to wrap with `OneFlight.run/3` directly.
## Possible later work
- `strategy: :ring` for large clusters where `:global` coordination becomes a measured bottleneck.
- `OneFlight.Req` request-key presets for common safe cases.
- Markdown report or telemetry example snippets for observability docs.
- Benchmarks comparing duplicate uncoalesced work vs `one_flight` under hot keys.
## Explicit non-plans
- No result TTL.
- No persistent storage.
- No retry, backoff, or circuit breaking.
- No cache API.
- No distributed consensus dependency.