Commit Graph
6389 Commits
Author SHA1 Message Date
localhost 3de8610e2e fix(ci): compare release validation against the previous stable version (#9636)
Ancestry-based tag selection skips stable tags that live only on older release branches.

Signed-off-by: paomian <xpaomian@gmail.com>
2026-10-16 07:01:29 +00:00
discord9 778f4556a8 feat: unify query options across SQL, HTTP and gRPC (#9494)
Isolated rebase verification of PR #9494. Preserve the reviewed net change; original PR branch remains untouched.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-10-16 04:48:32 +00:00
Lei, HUANG f663569cf0 feat(auth): expose public authentication config (#9626)
Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-10-16 03:25:58 +00:00
YingNing ce428bb74d feat(servers): accept application/x-json-stream for log ingestion (#9581)
* feat(servers): accept application/x-json-stream for log ingestion

Support fluentbit's json_stream output format on the HTTP log ingestion
endpoints by accepting `application/x-json-stream` as a payload content
type.

The payload is parsed as concatenated JSON -- multiple JSON values placed
back-to-back without a separator, e.g. `{"a":1}{"b":2}` -- reusing the
streaming value iterator already used for `application/json`, so the
behavior for concatenated or mixed payloads is identical.

Aimed at #5404 (msgpack support is left as a possible follow-up).

Signed-off-by: dxqlovestudy <59612604+dxqlovestudy@users.noreply.github.com>

* chore(servers): remove redundant comments per review feedback

Signed-off-by: dxqlovestudy <59612604+dxqlovestudy@users.noreply.github.com>

---------

Signed-off-by: dxqlovestudy <59612604+dxqlovestudy@users.noreply.github.com>
2026-10-16 02:36:47 +00:00
Weny Xu 4859e57e0b feat(meta): apply affinity to failover and repartition (#9604)
* feat(meta): apply affinity to failover and repartition

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(meta): share repartition affinity until group allocation

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-15 14:29:10 +00:00
jeremyhi deae75ffee fix(log-store): refuse to open object store WAL regions whose history is missing (#9561)
* fix(log-store): refuse to open object store WAL regions whose history is missing

A region persists only its WAL prefix, not the object store that holds it.
After `[wal].storage_provider`, or the bucket or root of the provider it
names, changes, or after the objects under the prefix are deleted, every
region reopened against a prefix without its history, replayed nothing and
silently lost its acknowledged writes that were not flushed.

Add `LogStore::check_region_history` and `LogStore::start_region_history`,
whose defaults accept and do nothing, so Raft Engine and Kafka are
unchanged. The object store WAL reports the history of a region as missing
when recovery found no object under the prefix, or when the region's
watermark names an object above the newest object holding entries that
recovery indexed, unless the catalog holds the region's entries through the
watermark or the region's history starts in the store. Both rest on
invariants of the prefix: an opened prefix is never empty, and a persisted
watermark names an object at or below the newest object holding entries,
which collection never deletes. The segment of release records counts as
entries, since an object holding only release records can be the one
collection keeps; start objects hold no segment and do not move the bound.

When a store that found its prefix empty refuses a region, the actor gives
up its start object, so the next start refuses the region again. It agrees
only while nothing was handed an id, no batch, append, release or create
waits, no failed release is kept, no other object was listed, the catalog
holds only the start object and no region's history started in the store,
deciding under the lock region registration takes. It then records a
terminal error, deletes the object as one of its tracked deletes, which
`stop` waits for, and answers every refusal once that delete settled.

Mito runs the check before it replays an existing region on open, on
catch-up and when a create finds the region present, with the larger of
the flushed and truncated entry ids, and records the history of a region
it creates; regions that skip the WAL and noop regions are not checked. A
missing history fails the open with an error naming the region, the
prefix, the configured storage and how to move the WAL by copying its
objects. The new `[wal].accept_missing_history` option, off by default,
opens such a region without its unflushed writes instead, with a warning
and the counter
`greptime_logstore_object_store_wal_missing_history_accepted_total`.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe the object store WAL history check

Describe the open-time history check, the prefix invariants it relies on,
how release records bound the history, the start object withdrawal of a
refused open and the window that remains, the accept_missing_history
option and how to move a WAL by copying its objects, and update the
metrics, Mito integration, evidence, compatibility and cluster alignment
sections.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): unindex the start object a refused open withdrew

A withdrawal that deleted the start object left it in the catalog and in the indexed object and byte gauges for the rest of the process. Remove it from both once the delete succeeded, and keep it when the delete failed.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): separate the withdrawal windows of start objects and entries

An append or a release admitted before a refusal leaves an object holding entries, which may have collected the start object, so the next start also passes watermarks at or below that object.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): keep a successor's chain complete across a late withdrawal

A start object withdrawn after another instance recovered it was linked by that instance's start object, which carried reclaim boundary 0, so once the delete landed the next open found no complete chain. A start object now reclaims every object below it when the recovered chain holds no segment, so such a delete stays below its boundary.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(mito2): record a created region's WAL history before its manifest

A create recorded the region's WAL history after it persisted the manifest, so a withdrawal in between failed the create but left a manifest that the next start refused as a region without its history. Record the history first, so such a create fails before it writes anything.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe the start boundary of a chain without segments and the create order

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-15 12:38:01 +00:00
fys cf0f6c308a fix(prom): return empty remote read results for missing metrics (#9613)
* fix: return empty remote read results for missing metrics

Signed-off-by: fys <fengys1996@gmail.com>

* test(prom): cover empty reads for missing databases

Signed-off-by: fys <fengys1996@gmail.com>

* test(prom): simplify remote read regression cases

Signed-off-by: fys <fengys1996@gmail.com>

* fix(prom): log missing tables during remote read

Signed-off-by: fys <fengys1996@gmail.com>

---------

Signed-off-by: fys <fengys1996@gmail.com>
2026-10-15 12:16:14 +00:00
discord9 60097a0628 ci(coverage): set RUST_MIN_STACK=8MB in merge_group coverage job (#9615)
The merge_group coverage job did not set RUST_MIN_STACK, so test threads
ran with the default 2MiB stack while the regular test job (and the
production runtime in debug) use 8MiB. The deeper PromQL planning chain
from #9494 overflows 2MiB under llvm-cov instrumentation, aborting
tests::promql_test::anon_promql_ratio_repro::case_1_test_with_standalone
with SIGABRT (12/12 failures across three merge-queue candidates).
Align the coverage job with the existing 8MiB test policy.

Signed-off-by: discord9 <discord9@163.com>
2026-10-15 11:17:18 +00:00
discord9 c3469fad51 fix(flow): retain tracked write completion across transient failures (#9525)
* fix(flow): retain tracked write completion across transient failures

Use receiver-issued single-write capabilities at the frontend and datanode. Rejoin exact admitted writes across unknown transport outcomes, then close and drain before allowing subsequent rounds. Keep ordinary clients and reads on their existing paths.

Separate schema map equality from encoded row identity so fresh protobuf decodes replay consistently even with NaN values. Cover receiver admission, owner cancellation, all-child drain, and retired capabilities.

Local feature-worktree checkpoint only. Main verified core enterprise check and 484 tests, plus DN enterprise check and all four tracked owner tests. Corrected seven-case timer acceptance remains to be rerun; this checkpoint does not authorize publishing or integration.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(flow): preserve upstream dependencies after rebase

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(flow): fail fast on definitive tracked-write open rejection

A tracked write treats every application-level error from the frontend as
an ambiguous transport failure and retries the same pinned frontend
forever. During a rolling upgrade an older frontend does not recognize the
tracked-write command extension and processes Open as an ordinary empty
SQL query, rejecting it with InvalidSql (InvalidArguments); a non-internal
endpoint rejects the extension outright. Both are definitive rejections
that no same-frontend retry can ever resolve, so the flow stalls.

Classify the Open-phase errors by status code: a definitive rejection
(Unsupported / InvalidArguments / PermissionDenied) fails fast with a
terminal pre-write error, while genuinely ambiguous transport failures
(Unavailable, timeout, connection reset, ...) keep the same-capability
retry. Write/Close rejections are deliberately NOT failed fast: once a
write may have been admitted, a same-code rejection (e.g. WriterLost, or
UnknownCapability after a VIP moved Open->A/Write->B) leaves the outcome
ambiguous, and failing fast would let the caller replay and duplicate
rows.

Add a regression test that a legacy empty-SQL Open rejection fails fast
with a single attempt and surfaces as Error::External carrying a
TerminalError.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(flow): preflight tracked writes without submitting data

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(flow): retain tracked command extensions while decoding

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-10-15 10:49:09 +00:00
Lei, HUANG 33879b07c8 chore: bump rustls to 0.23.46 (#9614)
rustls 0.23.46 fixes rustls/rustls#3301: on TLS 1.2 with AES-GCM, reaching the 2^24 record limit dropped a fragment while reporting the write as complete, then kept sending records after close_notify. This stalled Kafka WAL produce requests until the request timeout.
2026-10-15 10:47:29 +00:00
shuiyisong ad823db020 fix(pipeline)!: disable VRL host access by default (#9610)
fix(pipeline): disable VRL host access by default

Signed-off-by: shuiyisong <xixing.sys@gmail.com>
2026-10-15 10:10:50 +00:00
Lei, HUANG 0dc81777e3 fix(pprof): initialize framehop before signal sampling (#9612)
fix(pprof): pin upstream framehop initialization fix

Pin pprof workspace-wide to 01cff82d containing tikv/pprof-rs#282. Initialize framehop before sampling instead of allocating and discovering shared libraries in the first SIGPROF handler. Regenerate the lockfile without unrelated dependency changes.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-10-15 10:07:35 +00:00
jeremyhi 7df99f946e test: add manual S3 metric snapshot benchmark (#9573)
* test: add repeatable metric snapshot S3 benchmark

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test: use only existing CI S3 permissions in the metric snapshot benchmark

The CI S3 user is not allowed GetBucketLocation or ListBucketMultipartUploads,
so the bucket probe and the prefix cleanup failed with AccessDenied. Use only
list, put, get and delete under the run prefix, as the object store WAL
benchmark does, and probe S3 before allocating the EC2 runner.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test: scope metric snapshot inventory to the current round

The full round's S3 inventory listed the whole run prefix, so it also counted
the smoke snapshot. List only the round's snapshot prefix while cleanup still
covers the run, and assert that the teardown's S3 cleanup step runs always()
with the validated run prefix.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs: record the AWS validation run of the metric snapshot benchmark

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-15 09:52:28 +00:00
Weny Xu cbfbad469f feat(meta): add affinity hooks (#9596)
* feat(meta): add affinity hooks

Signed-off-by: WenyXu <wenymedia@gmail.com>

* test(meta): cover load-based affinity fallback queries

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(meta): borrow affinity requirements during selection

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(meta): remove unused affinity error variant

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-15 09:41:31 +00:00
dennis zhuang f7a3a7033c fix(query): keep state column names unique when splitting aggregates (#9594)
* fix(query): keep state column names unique when splitting aggregates

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(query): probe allocated names when renaming colliding state columns

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-10-15 07:51:17 +00:00
dennis zhuang cf16c7313b fix(jaeger): return the most recent traces when a search hits its limit (#9595)
* fix(jaeger): return the most recent traces when a search hits its limit

Trace search applied LIMIT to an unordered DISTINCT trace_id, so a search
matching more traces than the limit returned an arbitrary subset that
changed between identical requests. Order traces by their latest matching
span before applying the limit.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(jaeger): name the trace dataframe builder with a verb and document execution

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-10-15 07:47:36 +00:00
Lei, HUANG af396e60a3 perf(query): infer safe aggregate input bounds from HAVING (#9582)
* perf(query): infer safe aggregate input bounds from HAVING

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(query): refresh explain snapshots for aggregate bound inference

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(query): avoid reinferring bounds across MergeScan

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(query): validate aggregate bound column provenance

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(query): retain zero-match groups for nonpositive HAVING thresholds

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(query): assert inferred bounds in remote scan plans

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-10-15 04:46:37 +00:00
Yingwen ce66d8d4ac fix: avoid pinning memtables during series-index reconciliation (#9588)
Signed-off-by: evenyag <realevenyag@gmail.com>
2026-10-15 03:51:05 +00:00
dennis zhuang 5cfdc30a69 fix(table): stop claiming exact null and distinct counts for append scans (#9593)
RegionScanExec reported null_count = 0 and distinct_count = total_rows for
every column of an append-only table. DataFusion answers count(col) and
count(DISTINCT col) from these statistics, so both returned the row count.
Keep the exact row count and an exact zero null count for non-nullable
columns, so count(*) is still answered from statistics.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-10-15 03:45:48 +00:00
dennis zhuang ef1298ce02 fix(query): accept narrowed nullability in MergeScan remote schema check (#9592)
On append-mode tables a region reports an exact row count. When it is
zero, DataFusion's AggregateStatistics replaces the region-side
__min_state/__max_state aggregate with a non-null struct literal, so the
remote stream advertises the state column as non-nullable. The MergeScan
schema check required equal nullability and failed the query.

Accept a remote field that is non-nullable where the expected field is
nullable, matching DataFusion's own physical-plan schema invariant.
Batches are already rebuilt with the expected schema. Widening is still
rejected, and nested field nullability is still compared exactly as part
of the data type.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-10-15 03:28:25 +00:00
jeremyhi 60655a933b fix(log-store): persist object store WAL region releases (#9579)
* fix(log-store): persist object store WAL region releases

A region's release lived only in memory: a restart after DROP TABLE and
before the next object never re-established the dropped region's
watermark, so its segments counted as live and pinned garbage collection
of the whole prefix.

A release now writes a release record (region id and the entry id the
region is released through) into an object sealed at once, and returns
once that object is durable and indexed, in both acknowledgement modes.
Recovery seeds the obsolete watermarks from the release records of the
indexed objects before it computes any reclaim boundary. obsolete_all
releases in full; the new LogStore::release_region, a no-op by default,
releases a dropped region through the largest entry id the store handed
out for it, and Mito calls it after obsolete when it drops a region.

Objects with release records use format version 2, the version 1 layout
with the records at the end of the footer; every other object is still
written as version 1. A counter of release records made durable is added.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe persisted object store WAL region releases

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): carry a failed region release into the next object

A release whose batch failed left its record only in an orphan object,
so a drop that failed there could still leave the region unreleased
after a restart. The store now keeps the release records of failed
batches and seals them with its next batch, on a timer tick when no
entry is admitted, so the release becomes durable once a create
succeeds again.

The version 1 and version 2 object fixtures are frozen under
tests/compatibility/wal/object_store and loaded by the format tests,
and the RFC no longer says that state is persisted only in headers.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(mito2): complete a region drop whose WAL release fails

A drop request is not sent again once the region was removed, so a drop
whose WAL release failed used to leave the region half dropped. The
drop now completes, cleaning up the region's runtime state and
scheduling its files for deletion, and reports the release failure.

In the durable mode the object store WAL now creates one more object at
stop with the release records of failed and dropped batches, so a
graceful stop does not lose a release that failed. The release record
counter is described as counting the records of indexed objects.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(log-store): describe the stop-time release create of the WAL actor

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): state the accepted window of unreleased dropped regions

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(log-store): describe release waiters in the WAL actor's outcome table

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): fail region releases while the object store WAL is failing

A failing store keeps its backlog and rejects appends until a create
succeeds, so a release would otherwise wait for an upload that is not
coming. A release that arrives in that state now fails at once with the
retryable error, and one whose batch is still pending when the store
enters it fails as well. Neither poisons the store: the record of the
first waits for the next sealed batch, like that of a batch that failed,
and the record of the second stays in the backlog, so both become durable
once a create succeeds.

Rejected releases count in rejected_appends_total.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe region releases while the object store WAL is failing

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): place the drop crash window in the drop procedure

The crash window between the deletion of a table's metadata and a
durable release record is a gap of the drop procedure, not of the WAL.
Describe it as far as the code shows, name the remedy that belongs in
the procedure, cleaning up offline a region a resumed region drop finds
not open, and list it under future work.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): keep rejected release records coalesced while failing

A release rejected while the store is failing kept its record for the
next sealed batch, but every timer tick then sealed that record alone
behind the refused backlog, so a release repeated across ticks grew the
backlog without bound. A failing store now keeps such records coalesced
and seals them on the first tick after a create succeeds.

The fault-matrix case of a release while the backlog is refused now runs
with a 10 ms flush interval, repeats the release, and checks that the
backlog does not grow and that recovery reads the record back.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): keep rejected release records unsealed while failing

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): cite the drop procedure issue for the crash window

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): let a stop seal rejected release records of a failing store

Keeping the records of rejected releases out of sealed batches while the
store is failing also kept them out of the seal a stop requests, so a
stop whose last attempt of the backlog succeeded dropped them and the
released region pinned collection after the restart. A stop now seals
them with the backlog.

A fault-matrix case rejects a release while the store is failing, stops,
lets both creates succeed, and checks the record after a reopen.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe the stop of a failing store with rejected releases

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): keep release records readable by older object store WAL readers

Release records were written as a version 2 footer, which a build without
it refuses to read, so rolling a node back after a drop failed to open
the whole WAL prefix. They are now the single entry of a segment of the
reserved region u64::MAX at the first position of a version 1 object:
an older reader indexes that segment as a region it never opens, and
recovery reads the segment back with one range read per object that
holds one. The segment never holds the reclaim boundary and names no
namespace.

A durable stop whose last create of release records fails now reports
the error instead of returning Ok and losing the records silently.

The tests are trimmed: the release unit tests and fault-matrix cases
that repeated each other are merged, and the Mito drop tests share one
parameterized case.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe release records as a segment of a reserved region

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): report release records a poisoning stop drops

A durable stop whose last create of release records met a conflict
poisoned the store and returned Ok, losing the records silently. Stop
now reports the error whenever release records are dropped after it
began, by a rollback or by poisoning. The test of a failed release
covers that conflict, and seals its record on a tick after a one-shot
create failure, so the next tick cannot fail too.

The documentation now says that recovery reads the segments of release
records, and that one that does not decode fails recovery.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe how recovery reads segments of release records

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): say that stop reports release records a conflict drops

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test(log-store): restore the transiently failing release create in enqueued mode

The fault matrix again covers a release whose create fails transiently in
the enqueued mode: the release waits for the repeat under the same
sequence and returns once it succeeds. The encode_batch doc now says the
release segment is the last segment of the object.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): place the release segment and count the restored case

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(mito2): do not fail a region drop on a failed WAL release

Returning the release error from the drop left a metric physical region
half dropped: the metric engine stops after the data region and never
drops the metadata region or forgets the physical region, and a retried
drop finds the data region gone and counts it as done. The release error
gave the caller nothing to retry, since the region is already removed
and the log store keeps the record for its next object. The drop now
logs the error and succeeds.

A metric engine test drops a physical region while the WAL releases of
both mito regions fail, and checks that both regions and the physical
region state are gone.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): a failed release no longer fails the drop

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(mito2): do not fail a region drop on a failed WAL obsolete

A store that the release of another region poisoned fails obsolete as
well, which left the metric engine with its metadata region undropped.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test(metric-engine): drop a physical region whose WAL obsolete or release fails

Cover a failed data release, two failed releases and a conflicting
release that poisons the store, after the regions wrote to the WAL, and
check that a store opened later keeps no segment of either region.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): a failed obsolete does not fail the drop either

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(mito2): fail the drop on an obsolete error of other WAL providers

Only the object store WAL is shared by the regions of a store that the
release of one can poison; Raft Engine and Kafka keep failing the drop
when obsolete fails.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): a stopped or poisoned store keeps no failed release

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-15 03:27:43 +00:00
Ning Sun 40770ddb72 test: only assert genuinely invalid read-preference values at request ingresses (#9576)
The flow and nested-MergeScan ingress tests hardcoded "follower" among
the read-preference values that must be rejected, coupling them to the
current leader-only ReadPreference enum. Assert only genuinely invalid
values there, matching the wire-values test which already limits itself
to ["", "unknown"]. This keeps the ingress tests valid for builds that
extend ReadPreference with more variants.

Signed-off-by: Ning Sun <sunning@greptime.com>
2026-10-14 12:49:56 +00:00
Lei, HUANG 3b442adba2 feat(mito): decouple compaction unit execution and publication (#9131)
* feat(mito): decouple compaction unit execution and publication

Execute shared-input dependency groups as independent local compaction units. Publish and acknowledge each unit separately, retain successful sibling results, and release each unit's input leases after worker apply.

Preserve picker priority, panic notifications, snapshot-free execution context, and indexed input leases. Include regression coverage for independent visibility, purge, cancellation, partial failure, and restart recovery.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): use crate visibility for compaction unit items

Replace the newly introduced pub(super) declarations with pub(crate), and make CompactingFiles::try_reserve private since it is only used within its module, per docs/style-guide.md.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): simplify compaction unit state and test fixtures

Keep local input leases in the task and derive running units from tracked and pending work. Replace the single-implementation task trait with an inherent async method and align exposed state type visibility.

Use snapshot-free region fixtures and named test scenarios, and cover independent input purging across three units with bounded parallelism.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): align compaction task and test module names

Rename CompactionTaskImpl to CompactionTask now that the CompactionTask
trait has been removed and the Impl suffix no longer marks a trait
implementation. Rename the state test module from lease_tests to tests
to follow the test module naming convention.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): align compaction task debug label

The Debug impl reported "TwcsCompactionTask" while the type is now
CompactionTask. Report the type name for consistency.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): label compaction elapsed metric per published unit

Record greptime_mito_compaction_total_elapsed once per published unit and
label it by type: a local dependency unit or a remote job. Update the
metric docs and group the Grafana compaction OPS/latency panels by type.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* docs(mito): clarify compacting file lease sharing

`CompactingFiles::for_inputs` clones the shared per-file leases instead of
transferring them. Document that the original collection keeps its leases,
so an input is released only after every owner drops its lease.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* docs(mito): document local compaction unit map key

Document that `LocalCompaction::units` is keyed by each unit's execution
plan ID, which matches `CompactionExecution::plan_id()` and the `plan_id`
carried by unit notifications.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): rename submit_prepared_compaction

The function submits remote jobs but only prepares local unit tasks; the
caller dispatches them after installing the returned phase. Rename it to
`prepare_or_submit_compaction` and document that ordering.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-10-14 12:21:32 +00:00
fengyue-xve a35661d69c fix(hdfs): clean up temporary file when an atomic write fails (#9483)
* fix(hdfs): clean up temporary file when an atomic write fails

Signed-off-by: fengyue-xve <1759519137@qq.com>

* style: apply rustfmt to hdfs layer test

Signed-off-by: fengyue-xve <1759519137@qq.com>

* fix(hdfs): report earlier write failures and log cleanup failures

- Later `write`/`close` calls on a writer whose failed write was
  cleaned up now mention the original failure instead of the bare
  "unavailable after close or abort" message.
- `abort_and_delete` logs abort and deletion failures with the
  temporary path instead of discarding them; the original write error
  is still returned to the caller.
- The temporary-file cleanup test now lists the directory holding the
  temporary file, so it fails if the cleanup is reverted.

Signed-off-by: 风月 <1759519137@qq.com>
Signed-off-by: fengyue-xve <1759519137@qq.com>

---------

Signed-off-by: fengyue-xve <1759519137@qq.com>
Signed-off-by: 风月 <1759519137@qq.com>
2026-10-14 09:46:15 +00:00
Weny Xu 36423a95c6 fix(operator): reuse catalog table resolution for write retries (#9574)
* fix(operator): inherit logical table partitions when retrying writes

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(operator): resolve retried writes through catalog manager

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-14 08:42:51 +00:00
dennis zhuang 5c4d9eb4f8 fix: align fulltext bloom tokens with matches_term and use them for LIKE (#9470)
* fix: align fulltext bloom tokens with matches_term and use them for LIKE

The bloom fulltext index stored tokens that did not follow
matches_term's word boundaries (`_`, ASCII next to Han, Han substrings),
so pruning dropped rows matches_term accepts.

Tokens and query probes now share the character classes of
matches_term, Han runs are indexed as bigrams, and LIKE patterns use the
same probes. The bloom blob is written under a new key; blobs from older
versions are no longer probed. Tantivy no longer serves matches_term.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: drop unused lazy_static from index and avoid typo-flagged test tokens

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* docs: link like_probes to tokenize instead of the downstream ScriptTokenizer

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor: name probe extraction with verbs and document CharClass

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: rebuild legacy fulltext bloom indexes and probe lower(col)

The manifest records the fulltext bloom version per column, so ADMIN
BUILD_INDEX now rebuilds SSTs whose bloom index predates the current
tokens, and ssts_index_meta shows the version.

Case-insensitive bloom indexes also store the tokens of the whole
lowercased text for rows where it can differ (U+0130, U+212A, sigma),
so matches_term(lower(col), ..) and lower(col) LIKE .. use the index.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: cover legacy bloom index rewrite by compaction in the compat case

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: log outdated fulltext bloom indexes in the consistency check

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* docs: explain the unrecorded fulltext bloom version

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-10-14 08:07:24 +00:00
fengyue-xve 09bbe1cf9f refactor(promql): centralize PromQL function registration in promql::functions (#9500)
* refactor(promql): centralize PromQL function registration in promql::functions

Move the PromQL scalar UDF and UDAF registrations out of the query plan
decoder into a single `promql::functions::register_promql_functions`
entry point, so plan decoding no longer has to enumerate every PromQL
function implementation. The registered function set, aliases (e.g.
`prom_holt_winters`) and registration order are unchanged.

Add a registration test pinning the full set of `prom_*` scalar
functions and the `prom_holt_winters` alias, plus a decode regression
test covering the centralized registration path.

Fixes #9493

Signed-off-by: fengyue-xve <1759519137@qq.com>

* refactor(promql): register Ieee UDFs centrally and address review

Rebase onto main picked up #9479, which registered the Ieee comparison
and sqrt UDFs from the decoder directly. Register them from
`register_promql_functions` instead so the single entry point stays
complete, and add the seven `prom_eq`..`prom_sqrt` names to the
registration test.

Also per review: drop the doc paragraph that explains why the function
was moved, drop the redundant `test_serializer_decode_centralized_promql_registration`
test and the registration comment in the decoder, move `use std::sync::Arc`
up with the imports, and simplify the registration test assertions.

Signed-off-by: 风月 <1759519137@qq.com>
Signed-off-by: fengyue-xve <1759519137@qq.com>

---------

Signed-off-by: fengyue-xve <1759519137@qq.com>
Signed-off-by: 风月 <1759519137@qq.com>
2026-10-14 07:33:52 +00:00
Yingwen 00aa65de7a fix(query): guard deep expressions during query planning (#9564)
* fix(query): avoid speculative clones in constant normalization

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix(query): reject deeply nested expressions before optimization

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
2026-10-14 06:49:35 +00:00
sun 4ff3296f97 feat: update dashboard to v0.14.2 (#9570) 2026-10-14 06:14:58 +00:00
jeremyhi a08e5bcceb fix(log-store): keep the enqueued backlog on permanent object store errors (#9558)
* fix(log-store): keep the enqueued backlog on permanent object store errors

On object storage the WAL's object store sits behind OpenDAL's retry
layer, which marks every error it returns as persistent. The enqueued
mode classified create failures by that status, so a 403 or a missing
bucket was repeated every 100 ms on every create in flight, logged
nothing, and made appends hang once the sealed batches were full.

Object store errors are now classified by kind: denied access, an
invalid configuration (how OpenDAL reports a missing S3 bucket) and a
write to a missing location are non-retriable. In the enqueued mode such
an error makes the store failing instead of poisoning it: the
acknowledged backlog is kept under its sequences and bytes, its lowest
pending batch is attempted alone with a delay that doubles from 100 ms
to 30 s, appends are rejected at once with a retryable error that
carries the last object store error, and the first create that succeeds
ends the state. Stop uploads the backlog at once and reports a failure
as before. The state is logged on entry, at most once a minute while it
lasts and on exit, and exported as the `failing` gauge and the
`rejected_appends_total` counter. Conflicts, encoding and catalog errors
still poison the store; the durable mode is unchanged.

An append held back because the sealed batches are full is now counted
and timed by the stall metrics in both modes.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(rfc): describe how the enqueued object store WAL handles refused creates

Describe the enqueued failure contract as the store now implements it:
non-retriable object store errors are told apart by kind because
OpenDAL's retry layer under the store marks every error persistent, a
failing store keeps its backlog and attempts it with backoff while it
rejects appends, and stop uploads the backlog at once. Add the failure
matrix row, the failing gauge and the rejected appends counter, the
sealed-batch admission limit and the stall metrics that now count it,
and the fault matrix case counts.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): time the failing attempts where they start and fix two statements

The test of the attempts of a failing store now records when each
refused write starts and checks the gaps between them, instead of
sampling a counter after a sleep of the test task. The delay comment and
the RFC describe 30 seconds as the longest delay between two attempts,
not as a bound on when appends resume, and the RFC states that the next
append is held once seven sealed batches wait.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test(log-store): drop the wait_until helper that main now defines

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* refactor(log-store): name errors that need an operator and trim the RFC contract

Rename is_non_retriable to requires_intervention: such a create is still
repeated, only slowly, until someone fixes the credentials, configuration
or bucket. Name the backoff test after what it asserts, cut the test of
the lowest pending batch to two failed rounds since the cadence is
covered by the backoff test, and shorten the RFC failure contract to
the contract and its rationale, leaving error mappings, request counts
and logging cadence to the code comments.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(log-store): tie the slow repeat to errors requiring intervention

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-14 06:10:26 +00:00
discord9 0e40281262 fix(promql): stop claiming scalar calculate preserves order (#9523)
* test: cover scalar calculate order contract

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(promql): stop claiming scalar calculate preserves order

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* docs(test): describe scalar ordering regression as pre-fix behavior

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-10-14 04:20:39 +00:00
Ning Sun f41e86f43a feat(meta-client): forward actor and event context for region follower RPCs (#9568)
The manage-region-follower chain submitted its procedures with an empty
executor context: `ProcedureServiceHandler::manage_region_follower`
accepted no query context, the operator built an
`ExecutorContext::default()`, and `MetaClient` dropped the context before
delegating to `RegionFollowerClient`. The submitting user (actor) and the
procedure event metadata therefore never reached the submitted
procedures.

- `ProcedureServiceHandler::manage_region_follower` now takes a
  `QueryContextRef`, consistent with `migrate_region`, `gc_regions` and
  `gc_table`.
- `ProcedureServiceOperator` derives the `ExecutorContext` (actor and
  `TriggerReason::Manual` event input) from the query context.
- The `RegionFollowerClient` trait methods now accept `&ExecutorContext`
  and `MetaClient` forwards it, so client implementations can transport
  the actor and event context on the wire.
- `procedure_event_context`/`procedure_actor` are now public so client
  implementations can reuse the trusted protocol derivation.
2026-10-14 04:11:53 +00:00
discord9 75bc4ce46d fix(table): stop claiming tag order for logical metric scans (#9522)
* test: cover metric logical scan tag ordering

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(table): only claim projected primary key prefix ordering

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(table): keep physical key ordering for metric projections

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(table): compare unknown partition counts explicitly

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(table): model scoped internal TSID scan properties

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-10-14 03:35:58 +00:00
NightG1owZandNightG1owZ caefcfd012 test: add inverted index compatibility case (#9519)
* test: add inverted index compatibility case (#5188)

Signed-off-by: NightG1owZ <316247938+NightG1owZ@users.noreply.github.com>

* test(compat): assert the newly indexed column stays queryable (#9535)

Signed-off-by: NightG1owZ <316247938+NightG1owZ@users.noreply.github.com>

* test(compat): narrow to_range to versions carrying #9545

The filtered read added in the previous commit only returns rows once #9545 is present. That fix is on main only (no backport-* labels), so it ships in the v1.4.0 line. Narrow to_range to >=v1.4.0-alpha.0 so the documented downgrade invocation (--to-version v1.1.4) is not broken.

Also add the missing trailing newline to the three case files.

Signed-off-by: NightG1owZ <316247938+NightG1owZ@users.noreply.github.com>

---------

Signed-off-by: NightG1owZ <316247938+NightG1owZ@users.noreply.github.com>
Co-authored-by: NightG1owZ <316247938+NightG1owZ@users.noreply.github.com>
2026-10-14 02:00:39 +00:00
Weny Xu f690bbb204 refactor!: remove datanode remote WAL index (#9563)
* refactor: remove datanode remote WAL index

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(log-store): update new WAL replay tests after index removal

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 15:31:04 +00:00
Weny Xu 863eebdecb feat(frontend): retry transient distributed write failures (#9543)
* refactor(operator): route shared requests through NodeManager

Remove the concrete NodeClients requester API and use the existing node manager for owned and shared requests. Preserve the original write hint while the legacy error adapter remains in place.

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(meta): preserve retry policy through error hints

Propagate client errors through External and let DDL read retry hints while preserving cleanup and terminal-child policies. Region transport failures retain the legacy Retryable classification, which now also participates in bounded write retries.

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(operator): restore sparse partition tags when rebuilding writes

Decode retained primary keys when refreshed partition expressions need different tags. Keep the partitioner and multi-region sparse write regression tests with the fix.

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(operator): stop detached write retries when callers cancel

Signed-off-by: WenyXu <wenymedia@gmail.com>

* feat(frontend): configure retries across distributed write paths

Wire the shared dispatcher through frontend and logical batching, preserving partition columns and request headers. Keep standalone retries disabled and include configuration, batching, and storage regression coverage.

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 14:51:35 +00:00
Lei, HUANG 4bd36cfd20 feat: support compaction options in HTTP hints (#9560)
* feat: support compaction options in HTTP hints

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: share TWCS compaction option prefix

Use the store-api constant for both HTTP hint inference and Mito region option validation so the two paths cannot drift.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-10-13 12:28:36 +00:00
jeremyhi 55d753ca58 perf(log-store): fetch object store WAL replay segments concurrently (#9555)
* perf(log-store): fetch object store WAL replay segments concurrently

A region read fetched each segment only after the previous object's
entries were yielded, so a replay paid the full request latency once per
object. Fetch up to READ_PREFETCH_DEPTH (8) segments ahead, each on its
own task, and handle their outcomes in object sequence order: entries,
collected-object skips, corrupted-segment holes and errors surface
exactly as before, and dropping the stream aborts the fetches in flight.
A read holds at most eight decoded segments besides the one it yields.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* perf(log-store): raise object store WAL recovery concurrency to 64

On S3, recovery reads the header and tail of every object, about 57 to
91 ms per object per lane on 4, 8 and 16 vCPUs alike, and its time
scales with objects divided by concurrency up to 128 lanes without
throttling: about 9,500 objects recovered in 99 s at 8 and 10.5 s at
64. At 64 recovery issues about 1,800 reads per second, a third of
S3's request rate per prefix, and holds one 64 KiB tail window per
lane, 4 MiB in all.

The recovery concurrency tests now scale with the constant.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* perf(log-store): share one prefetch byte budget among object store WAL reads

Each read fetched up to eight segments ahead on its own, so regions
opened in parallel (16 by default) could together hold 128 segments of
up to max_batch_bytes each. A read now always fetches the segment it
yields next, as before, and fetches a later one only while its length
fits in a 64 MiB budget shared by every read of the store. Regions
replayed in parallel thus hold one segment each plus at most 64 MiB,
however many open at once. Nothing waits on the budget: a read that
cannot reserve stops fetching ahead until its next poll.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): fail an object store WAL read whose fetch task panics

A fetch task that panicked was re-raised in the reader with
resume_unwind, which unwinds through the caller, such as Mito's region
opener task, past its cleanup. Return it as a WalSegmentFetch error
instead, so the read ends at that object like any other failed fetch.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix(log-store): bound replay prefetch by decoded size held by fetch tasks

The prefetch reservation sat in the read's queue, so dropping a read
released it at once while an aborted fetch could still hold its
buffers until it next yielded. The fetch task now holds the reservation
and returns it with its outcome, so it is released with the buffers.

A reservation also counted only the encoded segment length, while a
fetched segment is held decoded. It now counts the length plus one
Record per entry, and the comment states the whole bound.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* docs(log-store): round the measured figures in the recovery concurrency comment

Keep the magnitudes in the comment; the exact S3 figures belong to the
measurement run rather than the code.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* refactor(log-store): abort replay fetch tasks with tokio-util's AbortOnDropHandle

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* refactor(log-store): rename the replay prefetch reservation to try_reserve_prefetch_bytes

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test(log-store): share the bounded polling helper across the object store WAL tests

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-13 12:26:16 +00:00
dennis zhuang 2a70194930 feat: add per-column COMPRESSION option for SST columns (#9426)
* feat: add per-column COMPRESSION option for SST columns

CREATE TABLE accepts COMPRESSION WITH (type = 'zstd', level = N,
page_size = '<size>') on a column. The options are stored in the column
metadata, carried through gRPC column options, shown by SHOW CREATE
TABLE, and applied by the mito SST writer and bulk part encoder as
parquet column properties. Unset fields keep the SST defaults. Nested
types are rejected.

A page size below the dictionary page limit also lowers the column's
dictionary page limit: parquet sizes write batches by the dictionary
budget and keeps that size after falling back to plain encoding, which
would otherwise ignore the smaller data page limit.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: validate column compression options before persistence

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: reject compression overrides on metric logical tables

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-10-13 08:03:49 +00:00
discord9 2039f508fc fix(promql): stop fabricating histogram fold hash partitioning (#9509)
* fix(promql): stop fabricating histogram fold hash partitioning

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(promql): cover histogram fraction binary join missing rows

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(promql): normalize dictionary labels in histogram regression

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test: cover histogram joins on logical metric tables

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test: specify insert columns for logical metric fixture

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test: use supported histogram child replacement API

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(promql): keep histogram fold fixtures truthful

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-10-13 07:58:31 +00:00
Weny Xu d86741d0ad feat(operator): retry failed writes with refreshed partitions (#9542)
* feat(operator): retry failed writes with refreshed partitions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style(operator): simplify retry test type references

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(operator): clarify write request rebuilding names

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(operator): encapsulate write retry attempts

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style(operator): group inserter configuration methods

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(operator): share routed peers and separate retry decisions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(operator): avoid temporary write routing allocations

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 06:02:43 +00:00
Lei, HUANG 18634e17bb refactor(mito): retain region compaction and DDL lifecycle state (#9498)
* refactor(mito): retain region compaction and DDL lifecycle state

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito): finalize opening batch in the worker on registration

Clean up the `opening_regions` entry and reply to its waiters in the same
serialized worker step that registers an opened region, instead of waiting
for the background opener to resume after the registration acknowledgement.

Previously the entry was only removed by the background opener, so a close
followed by a reopen could join the stale opening batch and receive a false
success after the region no longer existed. Replying from the worker closes
that window because registration and waiter cleanup are now atomic with
respect to the worker loop.

Add a test-only `EventListener::on_region_open_registered` hook and a
regression test that holds the first background opener to verify a reopen
does not wait for the previous open task. On failure the region is still
stopped and waiters receive `RegionClosed`.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito): unregister drop runtime state before WAL cleanup

The region leaves the region map before its WAL entries are obsoleted. A
failure in `wal.obsolete(...).await?` returned early and skipped
`cleanup_dropped_region_runtime_state`, so the resident compaction, flush,
and index scheduler entries were never unregistered. Since the region is no
longer in the map, a later close cannot clean them up either, leaking the
entries for the rest of the worker's lifetime.

Move the runtime-state cleanup to immediately after the region leaves the
map, before the fallible WAL cleanup. The schedulers only touch their own
state and do not depend on the region map or WAL, so the reordering is safe
and leaves the success path unchanged.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): tighten visibility of new compaction state items

Keep `ActiveCompaction::idle` private (it is only used inside `state.rs`)
and expose the other items added by the resident-region refactor as
`pub(crate)` instead of `pub(super)`, per the style guide. Also drop a
stale comment in `on_compaction_finished`: DDL handoff now happens in
`take_ready_ddls` before this block, which only runs when no DDL is
queued.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito): skip compaction scheduling while a region is truncating

`handle_flush_finished` dispatches queued DDLs before scheduling
compaction. A truncate queued behind a committing flush marks the region
as `Truncating` synchronously, but `schedule_compaction` only skipped
staging states, so it could schedule a new automatic compaction while the
truncate was still running.

Add `MitoRegion::is_truncating` and skip compaction scheduling for a
truncating region. Add a regression test that queues a full truncate
behind a committing flush and asserts no compaction is scheduled.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito): log DDL-fenced compaction rejection

The refactor dropped the log emitted when a region was skipped because of
pending DDL requests. Automatic triggers carry no waiter, so the rejection
became silent and could not be told apart from a scheduling interval that
had not elapsed. Log the queued and executing DDL state before cancelling.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* docs(mito): document DDL reply fence invariants

Explain why fence_ddl_replies installs executing_ddl before handing off
the batch and why CompactionDdlComplete carries both a scheduler-wide
generation and a per-slot request_id. The generation fences replies from
superseded batches or region incarnations, while request_id makes
completion idempotent so only the last distinct reply releases the fence.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(mito): rename DDL completion request_id to request_index

The value is the DDL's index within the handed-off batch, not a globally
stable request identifier; request_id suggested otherwise. Rename it to
request_index across the scheduler, worker dispatch, and tests.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-10-13 05:17:41 +00:00
jeremyhi 394562aa9e fix: prevent stale leader metadata after concurrent writes (#9549)
fix: fence leader cache fills around store mutations

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-13 03:48:17 +00:00
Weny Xu 19a128f8d3 fix(session): respect supported read preferences in wire tests (#9550)
Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 03:37:15 +00:00
Weny Xu 287ced2de2 fix(mito2): ignore missing inverted indexes in old SSTs (#9545)
Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 03:18:37 +00:00
jeremyhi 83e62a7725 feat: remove the server-side Metric export gate (#9547)
* feat: remove the server-side Metric export gate

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* chore: remove unused export capability import

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* chore: remove unused CLI capability import

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* style: import the packed export error selector

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-13 02:32:30 +00:00
Weny Xu a2d28e6060 refactor(operator): centralize write partitioning and dispatch (#9541)
* refactor(operator): centralize write partitioning and dispatch

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(operator): preserve write dispatch behavior during refactor

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style(operator): import write dispatch error paths

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style(operator): align dispatch imports and test utilities

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style(operator): use imported types in partition tests

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 02:30:14 +00:00
Weny Xu 684c8ff291 feat(client): support region request reuse and route refresh hints (#9540)
* feat(client): support shared region requests without deep cloning

Signed-off-by: WenyXu <wenymedia@gmail.com>

* feat: propagate route refresh retry hints

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style: preserve local error variant imports in retry hints

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(mito2): distinguish staging rejection from write backpressure

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(meta): preserve legacy retry hints in instruction replies

Signed-off-by: WenyXu <wenymedia@gmail.com>

* test(client): inline retry hint compatibility cases

Signed-off-by: WenyXu <wenymedia@gmail.com>

* test(datanode): align batch-open retry hint assertion

Signed-off-by: WenyXu <wenymedia@gmail.com>

* style: use imported types in region request tests

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-10-13 02:29:54 +00:00
jeremyhi c1a0ca9595 ci: benchmark the object store WAL against S3 from an EC2 runner (#9536)
* ci: benchmark the object store WAL against S3 from an EC2 runner

Add a workflow_dispatch workflow that loads the o11ybench agent observability
dataset into a fresh GreptimeDB container per cell and compares three WAL
configurations that differ only in [wal]: Raft Engine with sync_write on the
instance store, and the object store WAL in durable and enqueued mode, with
the data files on S3 in the runner's region for all three. Rounds alternate
the configuration order. A summary reports rows per second, D/R and E/R as
the geometric mean over rounds, append acknowledgement p50 and p99, and the
object store WAL counters. A smoke mode runs the same chain on ubuntu-latest
against the MinIO fixture.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: scrape WAL metrics on failed loads and keep logic out of the benchmark YAML

Scrape the object store WAL metrics before stopping a cell's server whether
the load succeeded or failed, so failed cells keep their stall, poison and
create failure counters. Build the summary from the plan so that cells which
never ran are listed and leave their ratios undefined. Move budget, region,
runtime image, manifest and credential scan logic from the workflow into the
helper scripts, and drive the cell lifecycle in the tests through fake docker
and curl binaries.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: drop redundant required flags from benchmark inputs

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: fail a benchmark cell whose metrics scrape fails and zero untouched WAL counters

A load that succeeds without its metrics scrape now fails the cell with exit
code 4 and records metrics_scraped in cell.json. The summary reports an
event counter that never registered as zero when the cell is an object store
WAL cell whose scrape succeeded and created objects, and as unknown otherwise.
Planned cells that never ran are read through the same path as recorded ones.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: register the S3 benchmark workflow for dispatch from its branch

A workflow_dispatch workflow can only be dispatched once GitHub has
registered it, which happens on the default branch or when one of its
triggers fires. A push trigger limited to this branch registers it; validate
runs only for workflow_dispatch, so a push run skips every job.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: delete the benchmark S3 prefix one object at a time

boto3 now sends a CRC checksum instead of Content-MD5 with DeleteObjects,
which the MinIO fixture of the smoke run rejects. DeleteObject needs neither
and the prefix of one run holds at most a few thousand objects.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: default the S3 benchmark to c6id.2xlarge

c7id is not offered in the runner region ap-southeast-1, where DescribeInstanceTypes
rejects it. c6id is the compute optimized x86 family with a local NVMe instance
store that the region offers, with the same 8 vCPU and 16 GiB at 2xlarge.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: drop the registration trigger of the S3 benchmark workflow

The workflow is registered now, so dispatches no longer need a push trigger
on its branch.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: fail an S3 benchmark run on EC2 without a local instance store

Without an instance store the Raft Engine WAL of the R cells silently stayed
on the root EBS volume, so the run measured a different baseline. Only a smoke
run may keep it on the root volume now.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* ci: let the instance store check fail its workflow step

The step piped wal-disk into tee without pipefail, so a rejected host still
passed. wal-disk now writes its record itself and the step runs it alone.

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-10-12 13:36:55 +00:00
Yingwen 674ba72669 fix(mito): preserve version ordering in bulk merges and flushes (#9517)
* fix(mito): preserve delete barriers in flat last-non-null dedup

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix(mito): respect sequence ranges in bulk merges and flushes

Signed-off-by: evenyag <realevenyag@gmail.com>

* perf(mito): avoid merge selection on the bulk write path

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
2026-10-12 13:16:52 +00:00