Releases / TinyStore 0.7.1
TinyStore 0.7.1
TinyStore 0.7.1 came out on 6 November 2026. An aggregate given limit now
pages past the 1,000 series one query may find, a group at a time, so a
timer's p95 by function over a hundred functions reads in pages instead of
failing. A page's limit counts only buckets that hold samples, so a range
that is mostly empty no longer gives empty pages. Nothing that a program
calls changes.
- Metrics
- Aggregates past 1,000 series: pages hold whole groups, 1,000 series at most.
- No empty pages:
limitcounts buckets with samples.
Aggregates past 1,000 series
A timer with 12 bounds writes a series for each bound, so its p95 by
function over 92 functions finds 1,104 series. Without limit that is still
a limit error. With limit, each page holds whole groups whose series are
1,000 at most, and the next page goes on with the next group
(#59):
const page = await store.metrics.aggregate({ name: 'rpc_ms', since: '24h', op: 'p95', by: ['fn'], limit: 10_000 })
for await (const group of page) chart.appendBuckets(group.labels, group.buckets) // this page, then every page after itpage = await store.metrics.aggregate(name="rpc_ms", since="24h", op="p95", by=["fn"], limit=10_000)
async for group in page: # this page, then every page after it
chart.append_buckets(group.labels, group.buckets)q := metrics.Query{Name: "rpc_ms", Since: 24 * time.Hour, Op: metrics.Percentile(95), By: []string{"fn"}, Limit: 10_000}
page, err := metrics.Aggregate(ctx, store, q)
for group, err := range page.All(ctx) { // this page, then every page after it
chart.AppendBuckets(group.Labels, group.Buckets)
}let day = stats.query().name("rpc_ms").since(Duration::from_hours(24)).by(&["fn"]).limit(10_000);
for group in day.aggregate(Op::Percentile(95.0))?.all() {
chart.append_buckets(&group?); // this page, then every page after it
}-
Each group's buckets are the ones a call for that group alone gives: 92 functions come as pages of 83 functions, 996 series, and then 9.
-
A group with more than 1,000 series alone is still a
limiterror, since a bucket counts every series of its group. The error says to groupbymore labels or find fewer series, and no longer offerslimit:metrics: rpc_ms: a group past 1000 series, which no page splits, since a bucket counts every series of its group: group `by` more labels, or find fewer series: limit -
A bucket that alone passes a bound on a paged call says to make the buckets smaller, and no longer offers
limiteither.
Aggregate in pages has the details.
No empty pages
limit counts only buckets that hold samples. Before, it counted every
bucket of the range: with since: '2h' over an hour of data, a page spent
its limit on the empty hour as on the full one, and many pages came back
with no buckets at all. Now the same walk takes 552 pages of 10 buckets:
every: '1m', limit: 10, 92 functions, an hour of data in two | 0.7.0 | 0.7.1 |
|---|---|---|
| pages to walk | 1,114 | 552, which is 92 × 60 ÷ 10 |
| time | 1.34 s | 0.67 s |
Measured on Windows 11 Pro 26300, a release build, Bun 1.4.2, five runs'
median, with the script of
#59. A page still holds
fewer than limit buckets when it is the last, when a bound stops it, when a
short gap lies inside samples dense enough to have one in every bucket, or
when a timer measured nothing in a bucket: avg, max and percentiles leave
that bucket out, though its counters have samples there.
Fixes
tinystore sql --helpprints its text without the runs of spaces a lost line break left in it.
Install
bun add @tinyshed/tinystore@0.7.1
npm install @tinyshed/tinystore@0.7.1pip install tinyshed-tinystore==0.7.1go get tinyshed.org/tinystore@v0.7.1cargo add tinystore@0.7.1
cargo install tinystore-cli@0.7.1Nothing in a store's files changes, so 0.7.0 and 0.7.1 open each other's
stores. Pages go past 1,000 series where the core runs: a program that
reaches a server gets them once the server is 0.7.1. The server image is
ghcr.io/tinyshed/tinystore:0.7.1.
Every commit since 0.7.0 is in the GitHub release.