mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-11-13 14:27:14 +00:00
+10








602fdd3a27
* fix: bound metric snapshot memory and reduce export overhead (#9505) * fix(mito): bound retained scan memory Compact unused tag dictionary values before merge retention and avoid splitting a single scan source into redundant batches. Include regression coverage. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * perf(snapshot): bound writes and reduce logical export overhead Bound metadata writes to 8 MiB and abort failed writers. Preserve compatible string dictionaries, bound conversion work, combine Parquet row groups and filter single-table exports before routing. Include resource-boundary and packed-restore regression coverage. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * docs: clarify metric snapshot acceptance criteria Specify populated scale fixtures, controlled S3 request delay, native macOS validation, paging exclusions and alternating comparison rounds. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito): split batches only for merged readers Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test(snapshot): cover supported types in both layouts Signed-off-by: jeremyhi <fengjiachun@gmail.com> * docs: consolidate metric snapshot experiment conclusions Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito): honor series statistics when splitting L0 scans Apply the existing series-density heuristic to L0 files with known statistics and include them in the batch-size estimate. Preserve the fallback for older files without statistics. Cover short-series overlapping L0 files with an ordered latest-value regression. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * docs(mito): explain memory risk of splitting short L0 series Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: address snapshot export review feedback Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(cli): accept source errors in lazy snapshot contexts Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit18726c7602) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(prom): align remote read label matcher semantics (#9633) * fix(prom): align remote read label matcher semantics Signed-off-by: fys <fengys1996@gmail.com> * chore: optimize comment of validate_matchers * fix(prom): preserve existing binary label regex handling Signed-off-by: fys <fengys1996@gmail.com> * refactor: condition * test(prom): simplify remote read matcher tests and clarify comments * fix(prom): return binary remote read labels as UTF-8 * fix(prom): reject binary labels in remote read * refactor(prom): align remote read null label handling with PromQL Signed-off-by: fys <fengys1996@gmail.com> * refactor(prom): simplify null handling in label matcher branches Signed-off-by: fys <fengys1996@gmail.com> * fix(prom): restrict remote read labels to string types Signed-off-by: fys <fengys1996@gmail.com> * test(prom): use string label in default value column test Signed-off-by: fys <fengys1996@gmail.com> * fix: code review --------- Signed-off-by: fys <fengys1996@gmail.com> (cherry picked from commit4e8bc6df86) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): restore source splitting for cross-range series merges (#9818) * fix: restore batched series merges across ranges Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): split range sources before last-row selection Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): avoid tiny splits for single-source cross-range merges Signed-off-by: WenyXu <wenymedia@gmail.com> --------- Signed-off-by: WenyXu <wenymedia@gmail.com> (cherry picked from commit27c531336a) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): pick TWCS L1 merges by closed units so compaction terminates (#9741) * refactor(mito2): pick TWCS L1 merges by closed units TWCS could keep rewriting L1 files without new writes. Overlap-only picks could split their inputs into one more file than they read, and L1 file reduction then rewrote up to 16 files to remove that single file. The outputs, split by key, created new overlaps and the cycle repeated. Replace the three global pick phases with one pick per window, scheduled by class across windows. Every pick now decreases a termination measure when the window receives no writes. - Active windows only take merges that remove files. L1 files are grouped by conflicts and merged in key order, so size-split tails are merged together. A reduction rewrites at most 4 output files' worth of bytes per removed file. - Inactive windows absorb L0 files, then take closed merges: no other file intrudes on the inputs' bounding box, so outputs cannot add overlaps. Each merge resolves conflicts or removes files, decreasing (conflicts, files). Files that do not take part in an overlap are not rewritten. - Overlaps that only share a boundary key no longer count as conflicts, so a size-split sorted run does not look overlapping. - Closed merges may take 4x the input limit to resolve a whole window once. - Cache primary key ranges per pick instead of resolving them per comparison. - Log the pick branch of each compaction output. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * docs(mito2): state the compactor assumptions behind TWCS termination Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * feat(mito2): resolve active window overlaps on manual compaction A window that stops receiving writes keeps being the active window, whose picks only remove files, so its overlaps were never resolved. Manual compactions now pick every window as inactive, so a closed merge can resolve them. Automatic compactions are unchanged. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): defer overlap resolution in the window before the active one Late data keeps landing in the window right before the active window. A closed merge that resolves its overlaps early rewrites the whole window, then the late data brings the overlaps back, and the balanced run check keeps them there. Overlap-only merges now skip that window until it is older. File-reducing merges and manual compactions are unchanged. On the 12h/1GB out-of-order bench this reaches overlap depth 1.0 instead of 2.08 at the same write amplification (3.01 vs 3.02). Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito2): only check earlier-starting files when closing units Closing units only checks files that start before a unit ends, and the overlap checks compare key bounds without cloning them. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): keep settling windows from rewriting L1 files The window before the active one still receives late data. Skipping only its overlap-only merges was not enough: file-reducing merges of conflicting files and mixed L0/L1 merges still rewrote its L1 files, and a mixed merge could rewrite a nearly full output for each small late file. A settling window now only merges L0 files among themselves and conflict-free files; the window resolves its overlaps once it is older. On the out-of-order bench, write amplification drops from 3.88 to 3.30 at 2GB/6h, 3.05 to 2.94 at 1GB/6h and 3.01 to 2.96 at 1GB/12h, with overlap depth 1.0 in all three. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): resolve late overlaps once a window is quiet Late data that lands in a window older than the settling one is merged into a small file covering the whole key range. Resolving it rewrites the window's dominant sorted run, which the balanced run check refuses, so the overlap stayed. Removing the check instead rewrites the window for every late flush. A window is quiet once the region has written at least as many rows as the window holds since its newest file. Overlap merges in a quiet window may rewrite a dominant run, so each quiet period pays for at most one such rewrite. Sequences are per row and kept by compaction, so this needs no state. On the bench with late data up to 2 hours, mean overlap depth drops from 1.67 to 1.17 at 2GB/6h and from 2.33 to 1.83 at 1GB/6h, at write amplification 3.70 to 4.25 and 3.26 to 3.74; all inactive windows of 2GB/6h realtime reach depth 1 (write amplification 2.80 to 3.30). The remaining depth is in the final active window. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * test(mito2): check closed merges of quiet and settling windows terminate Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): split TWCS closures over the input limit A file spanning the keys of a large sorted run joins every run file into one closure. Once a closure held more files than one compaction accepts, closed merges skipped it, so the window never merged those files again and late files kept piling up. Split such closures into single files, like active-window picks do, and replace the closed check with a conflict bound: outputs only conflict with files intruding on the inputs' box, so a merge is taken if `outputs · I` does not exceed the conflicts its inputs had with other files. Intervals of whole closures have no such conflicts and still need to be closed, so other windows pick as before, and `(conflicts, files)` still strictly decreases. Small run files and late files over a large run can be merged again. A late file over a run that cannot shrink stays: resolving it would rewrite the whole run. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): address TWCS picker review findings - Manual compactions may rewrite a dominant sorted run to resolve overlaps. The active window is never quiet, so manual compactions could not resolve its late-data overlaps before. - Single-key intervals predict one output: the writer never splits a series, so large files of one series were never merged. - The active window falls back to single files when no group of conflicting files qualifies, so a large file no longer keeps its small peers unmerged. - Compute the settling window distance with checked_sub, which overflowed for windows at the timestamp limits. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): count inner keys as TWCS conflicts and check balance per group - A single key strictly inside another file's key range now conflicts, so a late file of one series inside a wide file is resolved like other overlaps. Files sharing only a boundary key still do not conflict. Intrusion covers the new pairs, which a randomized test checks. - Check the dominant-run guard per group of conflicting files. Runs of separate groups never overlap, so pairing one group's run with another group's peer made an interval of two dominant runs look balanced. - A window with unknown row counts, written before they were recorded, is not quiet: its threshold would drop to a single row. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * perf(mito2): index TWCS files by key to avoid quadratic grouping Grouping a window's files compared every file with all files sharing its time range, and closing groups and checking intrusions scanned the whole window. A sorted run split by key shares one time range, so a window of N such files took O(N²) checks without any conflict. The 1024-file fallback only covers the sorted-run path, not these groups. Index the files by lower primary key in a segment tree that keeps each subtree's largest upper key and its time bounds. Grouping, closing, and the conflict bound only check the files whose key and time ranges meet, so a file of a key-sliced run only meets its neighbors. Conflicts among split files are precomputed per file and counted per interval with a binary search instead of pairwise. On a run of 20,000 key-sliced files with 5 late files spanning all keys, a closed merge pick takes ~62 ms instead of ~3.9 s and an active pick ~19 ms instead of ~3.5 s. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * test(object-store): retry transient S3 transport failures Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): bound TWCS closed-merge conflict graph work Budget the candidate files visited while building conflict units and split-unit adjacency. When the budget is exceeded, treat every file as a split unit and pick a bounded file reduction instead of materializing a quadratic graph. The fallback candidate is admitted only through adds_no_conflicts, so outputs do not add conflict pairs and the (P, N) termination invariant still holds. Dense picks are logged with their own branch. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): charge TWCS index nodes to the conflict-graph budget The conflict-graph work budget only counted files that reached a callback, so a traversal with poor pruning could still visit a quadratic number of internal nodes without triggering the dense fallback. Charge every ExtentIndex node, including pruned nodes, and stop the traversal as soon as the shared budget is exhausted. Add a regression test where the root straddles the query time but neither leaf matches, so a callback-only budget would never fire. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): retry smaller TWCS dense compaction candidates If a dense fallback candidate fails admission, try one single-output subinterval within it before giving up. Reuse the reduction guards and check both candidates against the full window's external conflicts, preserving bounded work and termination.\n\nCover the chain regression through both fallback unit constructions and reject one-output retries that introduce conflicts across time gaps. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): compact shared primary-key boundaries Count shared primary-key endpoints as conflicts and apply the same overlap rule to bounding-box intrusions. Existing compaction writers keep series intact, so fresh output ranges remain disjoint. Align simulated output splits with the writer and cover boundary-only cleanup in inactive and manual windows, plus stable real output files after a subsequent TWCS request. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): compact small L1 files in inactive windows Allow bounded small-L1 reductions in settling and older inactive windows when normal picks cannot proceed. Preserve full-window conflict checks, large-file protection, and LastNonNull closure semantics.\n\nCover selection limits, termination, and real SST compaction with tombstones and reopen checks. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * docs(mito2): clarify TWCS unit grouping guarantees Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> --------- Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> (cherry picked from commitbb3f07b482) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: reclaim HDFS temporary files left behind by a datanode crash (#9616) * fix: reclaim HDFS temporary files left behind by a datanode crash Signed-off-by: lczllx <2181719471@qq.com> * fix(mito2): stop the temporary file sweep from starving GC jobs Signed-off-by: lczllx <2181719471@qq.com> * feat(mito2): add metrics for the temporary file sweep Signed-off-by: lczllx <2181719471@qq.com> * refactor(object-store): share one definition of the temporary file name Signed-off-by: lczllx <2181719471@qq.com> * fix(mito2): skip the temporary file sweep when no GC job is allowed Signed-off-by: lczllx <2181719471@qq.com> * refactor: gate the temporary file sweep behind the hdfs-object-store feature Signed-off-by: lczllx <2181719471@qq.com> * fix(mito2): sweep temporary files when a create opens an existing region Signed-off-by: lczllx <2181719471@qq.com> * docs(config): document the temporary file sweep in the GC settings Signed-off-by: lczllx <2181719471@qq.com> * refactor: align the temporary file sweep code with the surrounding style Signed-off-by: lczllx <2181719471@qq.com> --------- Signed-off-by: lczllx <2181719471@qq.com> (cherry picked from commit88cb2a986e) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(meta): fence datanode processes replaced by a newer process (#9878) * fix(meta): fence datanode processes replaced by a newer process Two datanode processes can run with the same node id, and metasrv grants leases and delivers instructions by node id only. Every datanode heartbeat already carries node_epoch, the time the process started. The metasrv leader records the highest accepted epoch per node id under __datanode_epoch/{node_id}, a prefix of the leader cache, and raises it with compare-and-put. The heartbeat session checks each datanode request with a non-zero epoch before the handler chain: a lower epoch gets a reply without running the chain, so no lease, keep-alive, stats or mailbox reply. An epoch more than 5 minutes ahead of the leader's clock is not recorded and is fenced too. Datanode pushers carry the epoch of their process: a lower epoch cannot replace a higher one, and a stream removes only its own pusher. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): keep the leader cache load and pusher updates coherent A write made while the leader cache is disabled, as during the load at leader start, went to the store without the cache noticing, so the load could install a value read before the write. Such writes now create new cache versions around the store call, and the load drops what it loaded for a prefix if a write happened meanwhile. This also covers node addresses, which heartbeats write during the load. A stream's pusher that takes its first epoch is updated in place instead of being replaced, so messages waiting on it are not cancelled, and the connection gauge counts only a pusher that fills an empty slot. The epoch check moves into the heartbeat service. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): keep the leader cache coherent with writes while it is disabled A write that started while the cache was disabled could commit after the load had read the old value and the cache had been enabled, leaving the old value cached. Writes now maintain the cache whether or not it is enabled, as enabled writes already did: new versions around the store call, then the key is updated or invalidated. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test(meta): pin the epoch 0 exemption and pusher order, and update docs The datanode test without an epoch now runs after another process has recorded one, and the pusher test checks that a stream's first accepted request receives what its handlers broadcast. The leader cache load no longer claims that writes must not run while it loads, and the meta-srv guide states that epoch 0 is not checked. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): register a datanode pusher only after its first request passes A datanode stream registered an epoch-0 pusher on its handshake, so an older process's reconnecting stream could take an empty slot, or a newer process's pusher before its first heartbeat, for about a round trip. A datanode stream now registers its pusher on its first request that passes the epoch check (epoch-0 requests after the handshake included), still before the handlers run. Pusher registration is logged only when the insert happens. Tests cover a fenced stream removing its own pusher, a handshake not taking an empty slot, and a KV error failing the request; two steps that could not fail are removed. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): check a datanode epoch again before replying A request could pass the epoch check, wait in the handler chain while a newer process of the node was recorded, and still return a region lease. After the handlers run, the session checks the epoch again against the cached record and, if a newer process has been recorded, replies as to a fenced request and removes the stream's own pusher. This costs one more read of the cached record per checked datanode request. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): handle a datanode's requests one at a time A request of an older process could pass the epoch check, wait in the handlers while a newer process was admitted, and then keep the node alive with its own address. Checking the epoch again after the handlers only dropped the reply. The heartbeat session now takes an in-memory lock for the node id before checking a request that carries an epoch, and releases it after the handlers, before the reply is sent. A newer process is therefore admitted only after the handlers of an older request finish. The check after the handlers is removed. Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit6f5c064f54) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: acknowledge writes only within the region's leader lease (#9904) * fix: acknowledge writes only within the region's leader lease Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: drop cached logical columns after a failed logical drop Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: keep the prepared region for the lease check after the WAL append Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: serialize a logical drop with fills of the logical column cache Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test: check the drop lock and grant long leases deterministically Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test: cover a bulk insert that loses its lease during the WAL append Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit91a59b82fb) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito): preserve SST lifetime across index replacement (#9950) * fix(mito): preserve SST lifetime across index replacement Share retirement and final purge across immutable index metadata views. Keep version-specific GC references until readers release them and match Parquet liveness by file identity. Fixes #9944 Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): list-based SST purge and single FilePurger::remove_file The final purge of a retired SST no longer depends on FileMeta: index files of every version are discovered by listing ({region_dir}/index/{file_id}. prefix), so even when the last live view is a stale one, the purge still removes all newer index files. - SstLifetime is slimmed down to { deleted, file_purger }; the purge now runs in the last FileHandleInner::drop (Arc::strong_count == 1, which is race-free here since only inners of the same file hold the lifetime). - FilePurger is merged back into a single remove_file(file_meta, is_delete) method; is_delete means the file was retired AND this is the last live view. - LocalFilePurger deletes the SST and all its index files via the new delete_file_and_all_indexes helper (list before delete, so a listing failure leaves the file untouched). - Remove the dead index_outdated flag and its accessors, which had no callers in the entire repo. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito): elect final SST view release atomically Track metadata views with an atomic counter instead of inspecting the lifetime Arc strong count. Concurrent destructors now elect exactly one final releaser while preserving the single remove_file interface. Add a deterministic concurrent-drop regression covering retired and live files. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): restore Arc-owned SST cleanup and clarify reference release Restore the lifetime design from835227dcbc, using the final Arc drop and latest metadata instead of manual view counting and per-SST index listing. Rename FilePurger::remove_file to release_file_ref while retaining purge_file for final cleanup. Preserve and adapt the concurrent view-release regression test. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): track SST references by file lifetime Register one reference guard per logical SST lifetime and release it on final drop, including normal region close. Remove per-view release_file_ref and index_outdated handling. Protect all index generations while their SST is referenced. Preserve the existing GC snapshot format by expanding the recorded index generation upper bound for older version-aware workers. Update coverage for independent references, normal close, cross-region ownership, concurrent final cleanup and both GC listing modes. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): release SST references directly on lifetime drop Remove the redundant FileReferenceGuard and let SstLifetime register and unregister its file reference directly. Preserve unconditional reference release on normal close and retirement-only purge. Expose the reference manager through FilePurger and adapt reference manager tests without changing GC or snapshot behavior. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * test(mito): verify SST cleanup with real storage and isolate GC policy cases Replace the recording-only concurrent purge test with filesystem assertions using LocalFilePurger and shared fixtures. Keep intermediate-view retention and retired versus live file cleanup coverage without claiming exhaustive thread interleavings. Separate GC reference-policy cases from reader-release ordering and reuse their setup. Production code remains unchanged. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * style(mito): format SST lifetime changes Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito): reclaim obsolete indexes by reader version Track exact index-version references per metadata view and restore version-specific Puffin liveness in both GC paths. Keep file-level Parquet protection and shared SST lifetime cleanup, without expanding snapshots into unreferenced index generations. Include old readers of imported files even when the source region is not open locally. Add real-storage GC coverage for reader release and lingering while retaining Parquet and the current index. Validated workspace checks with default and all features, all-target all-feature Clippy with warnings denied, and all 1853 mito2 tests. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> --------- Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> (cherry picked from commit17ed988f49) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): coordinate range cache invalidation and singleflight reads (#9935) * fix(mito2): invalidate retired SST range results and coalesce loads Coordinate decoded range loads by their full scan key, bound shared work, and prevent late fills after SST retirement. Invalidate range results for local purge and object-store GC while preserving old snapshot reads. Fixes #9934 Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito): preserve SST lifetime across index replacement Share retirement and final purge across immutable index metadata views. Keep version-specific GC references until readers release them and match Parquet liveness by file identity. Fixes #9944 Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): list-based SST purge and single FilePurger::remove_file The final purge of a retired SST no longer depends on FileMeta: index files of every version are discovered by listing ({region_dir}/index/{file_id}. prefix), so even when the last live view is a stale one, the purge still removes all newer index files. - SstLifetime is slimmed down to { deleted, file_purger }; the purge now runs in the last FileHandleInner::drop (Arc::strong_count == 1, which is race-free here since only inners of the same file hold the lifetime). - FilePurger is merged back into a single remove_file(file_meta, is_delete) method; is_delete means the file was retired AND this is the last live view. - LocalFilePurger deletes the SST and all its index files via the new delete_file_and_all_indexes helper (list before delete, so a listing failure leaves the file untouched). - Remove the dead index_outdated flag and its accessors, which had no callers in the entire repo. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito): elect final SST view release atomically Track metadata views with an atomic counter instead of inspecting the lifetime Arc strong count. Concurrent destructors now elect exactly one final releaser while preserving the single remove_file interface. Add a deterministic concurrent-drop regression covering retired and live files. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): restore Arc-owned SST cleanup and clarify reference release Restore the lifetime design from835227dcbc, using the final Arc drop and latest metadata instead of manual view counting and per-SST index listing. Rename FilePurger::remove_file to release_file_ref while retaining purge_file for final cleanup. Preserve and adapt the concurrent view-release regression test. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): track SST references by file lifetime Register one reference guard per logical SST lifetime and release it on final drop, including normal region close. Remove per-view release_file_ref and index_outdated handling. Protect all index generations while their SST is referenced. Preserve the existing GC snapshot format by expanding the recorded index generation upper bound for older version-aware workers. Update coverage for independent references, normal close, cross-region ownership, concurrent final cleanup and both GC listing modes. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor(mito): release SST references directly on lifetime drop Remove the redundant FileReferenceGuard and let SstLifetime register and unregister its file reference directly. Preserve unconditional reference release on normal close and retirement-only purge. Expose the reference manager through FilePurger and adapt reference manager tests without changing GC or snapshot behavior. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * test(mito): verify SST cleanup with real storage and isolate GC policy cases Replace the recording-only concurrent purge test with filesystem assertions using LocalFilePurger and shared fixtures. Keep intermediate-view retention and retired versus live file cleanup coverage without claiming exhaustive thread interleavings. Separate GC reference-policy cases from reader-release ordering and reuse their setup. Production code remains unchanged. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * style(mito): format SST lifetime changes Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): use crate-rooted range cache imports Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(mito2): account for range cache delivery lifetime Keep completed range results charged while watch subscribers or replay streams retain them. Cache entries keep weak delivery references, allowing cache-only ownership to release the delivery reservation. Cache hits reuse or nonblockingly acquire the reservation, falling back when the budget is exhausted. Resize input reservations to completed-result estimates and cover successive slow consumers, cache-only handoff, hit sharing, invalidation, admission rejection, and cancellation with regression tests. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> --------- Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> (cherry picked from commit44df6e5ded) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(meta): exclude route followers from failover targets (#10001) * fix(meta): exclude route followers from failover targets Failover target selection did not exclude the region's route followers. The selector could keep picking a follower, the submit rejected it as a peer conflict, and the region never failed over. Group the failed regions by their followers and exclude them per group. A group without a candidate is skipped instead of failing every region of the datanode. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test: check failover continues after a group without candidates Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): keep failover going when follower routes can't be read Fall back to selecting without follower exclusion when the routes can't be read, log skipped groups with their followers at warn level, and test a region without a route. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor(meta): select failover targets per exclusion set in select_peers generate_failover_tasks now only reads the route followers of the regions. select_peers resolves the affinity and the unschedulable datanodes once, then selects per group of regions that exclude the same datanodes. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor(meta): drop a comment that repeats the code Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor(meta): tighten failover target selection Name the route followers after the parameter they fill, read the routes with unwrap_or_else, and log a group without a candidate as an error, as the caller did before. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): let the region-stat-aware selector balance the whole batch The region-stat-aware selector now receives each region's excluded peers along with the whole batch, so it can still balance load across the regions while keeping a region off its own followers. A region without a candidate is left out of its output instead of failing the others. The selectors driven by SelectorOptions keep selecting per group of regions that exclude the same datanodes. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test: name the batch type of the stat-aware recorder Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor(meta): treat a selector without candidates the same in both arms Both selector arms now place what they can and treat NoEnoughAvailableNode as nothing placed; the stat-aware selector's contract says so. Rename its parameter to exclude_peer_ids_by_region, check for unplaced regions in linear time, and describe what the code does in the comments. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test: keep the stat-aware recorder's placements off excluded peers Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit62ebf71f90) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(log-store): make raft-engine periodic WAL sync actually fsync (#9715) * fix(log-store): make raft-engine periodic WAL sync actually fsync On raft-engine 0.4.2, Engine::sync() writes an empty LogBatch and write() returns before fsync (tikv/raft-engine#395). The periodic sync task therefore never durable-flushed acknowledged WAL data. Work around by writing a minimal non-empty marker with sync=true so the fsync path is reached until a crates.io release includes tikv/raft-engine#400. Fixes #9712 Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> * perf(log-store): reuse LogBatch across periodic WAL syncs Keep the periodic sync task's LogBatch across ticks instead of allocating a fresh one (4 KiB encode buffer plus item vec) every period. A successful Engine::write drains the batch but retains its buffers; after a failed write or a panicked blocking task the batch is discarded and recreated on the next tick, since it may be left partially encoded. Keep the marker put rather than deleting an empty key: the put overwrites a single key, whereas every delete would become a recovery tombstone that raft-engine keeps in memory while replaying append files. Also document that the marker value must not decode as a NamespaceImpl (the marker key lies inside the range scanned by list_namespaces), add a test covering batch reuse and namespace listing, and apply rustfmt. Refs #9712 Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> --------- Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> (cherry picked from commit180e2716fc) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(catalog): propagate frontend process-list failures (#9999) * fix(catalog): propagate frontend process-list failures Return the existing invocation error when a selected frontend cannot list processes, so a successful response cannot omit that peer. Signed-off-by: Byte-Naut <Byte-Naut@proton.me> * test(frontend): cover remote process-list errors and aggregation Exercise real metadata discovery and gRPC listeners for a missing management service and successful catalog-scoped aggregation. Signed-off-by: Byte-Naut <Byte-Naut@proton.me> --------- Signed-off-by: Byte-Naut <Byte-Naut@proton.me> (cherry picked from commit3d2b73762a) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(log-store): skip records with unparsable keys instead of aborting the read (#9749) * fix(log-store): skip records with unparsable keys instead of aborting the read Signed-off-by: lczllx <2181719471@qq.com> * fix(log-store): keep undecodable RecordMeta keys fatal Signed-off-by: lczllx <2181719471@qq.com> --------- Signed-off-by: lczllx <2181719471@qq.com> (cherry picked from commit5f0e22171e) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(meta): register failure detectors for regions switched before a rollback (#9989) * fix(meta): register failure detectors for regions switched before a rollback A region migration switches the routes of its tables one table at a time. If it aborts after some tables were switched, those regions are already served by the target, but the rollback deregistered the target's failure detectors for every region and registered only the source's. The target's next heartbeat registers them again, so if the target stopped before sending one, nothing detected its failure and the switched regions stayed unavailable until the metasrv leader changed or the target came back. The rollback now collects, from the routes it already reads, the regions whose leader is the target and resets the target's failure detectors for them at the end. It also skips a table whose route no longer exists, so a table dropped meanwhile no longer fails the rollback before the detectors are handled. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test(meta): roll back a downgrading leader in the rollback detector test The table that was not switched yet keeps a downgrading leader in a real abort, so the test now builds it that way and checks that the rollback clears it. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(meta): monitor regions switched before a rollback only on the target The rollback registered the source's failure detectors for every region of the migration, including the regions already switched to the target. Those regions are served by the target after the rollback, so their source detectors watched the wrong peer: when one fired, the failover found the leader had changed and only removed it. The rollback now registers the source's detectors only for the regions that were not switched, and keeps resetting the target's detectors for the others. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor(meta): rename reset_failure_detectors_for_candidate_regions to reset_failure_detectors Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit05536cd7f5) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: ignore stale leader grants after a region is downgraded (#9987) * fix: ignore stale leader grants after a region is downgraded Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: compare stale leader grants with the longest lease seen Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: treat a lease too long to store as unknown A lease longer than a u64 of nanoseconds saturated to a shorter one, so the derived send time could be later than the real one. Now such a lease makes the send time unknown, which counts as earlier than any gate. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: address review comments on stale leader grants Scope the early send time claim to after a lease has been seen, drop the unused role parameter of demote, clarify a test comment and check that a fresh grant still makes a reopened region writable. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: compare stale leader grants with the heartbeat send time Pass the send time of the heartbeat behind a lease to set_region_role_with_lease, and return whether the role was applied. Mito compares the send time with the grant gate directly, so it no longer derives it from the longest lease seen. The datanode finalizes leadership only when the grant was applied. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test: cover stale grants through the datanode and repeated downgrades Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: keep leader grant rules in one region method Apply a role grant in MitoRegion::apply_role_grant, which renews the lease and decides whether the role changes; the engine only looks up the region. Rename the gate to downgrade_started_at and demote to begin_downgrade, keep the field private, and copy it on reopen through inherit_downgrade_state_from. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: drop a needless borrow Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: keep lease concepts in the engine and role ordering in the region ManifestContext, which owns the role, records when the role was last demoted and promotes a region only for a promotion issued after that. The time starts when the context is created, so a reopened region ignores grants for heartbeats sent before the reopen, without copying state. The engine translates leases: it renews the deadline and promotes with the heartbeat send time. MitoRegion keeps no grant state. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix: keep the data region of a metric region off a grant its metadata region ignores The metric engine applies a grant to the metadata region first and stops if it is ignored, so the data region, whose role the engine reports, never becomes a leader that skips finalization. Also describe what promoting returns. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * docs: describe when a lease grant is ignored and flatten the finalize check Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: move lease types out of the region and the Leader deadline into ManifestContext Signed-off-by: jeremyhi <fengjiachun@gmail.com> * refactor: name the promotion fence after the downgrade it records Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit89a5df3141) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): preserve live index files across remote compactions (#10046) fix(mito2): reuse executor-owned compaction index resources Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> (cherry picked from commitc7ea80558f) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(datanode): pick a node epoch above the recorded one (#9984) * fix(datanode): pick a node epoch above the recorded one The metasrv fences a datanode whose node epoch is lower than the highest one it has recorded for the node id. A datanode used its start time as its epoch, so after a restart on a host whose clock is behind the previous process's, or after the clock stepped back, the new process picked a lower epoch and was fenced for good: no region lease, no keep-alive. Before it creates the heartbeat task, the datanode now reads the recorded epoch through its metadata backend and uses one more than it if its start time is not higher. The node info still reports the local start time. A failed read fails the startup, like the other metadata reads. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test(datanode): tighten the node epoch tests Use a lower record that leaves room below the start time, so the test fails if the start time is ignored, and a nonzero node id, so it fails if the node id is ignored. Clarify the doc comment of the epoch choice. This assumes the previous process of a node id has stopped before a new one starts. Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commitc40e86c653) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(auth): preserve physical metric table targets (#10084) * fix(auth): preserve physical metric table targets Signed-off-by: shuiyisong <xixing.sys@gmail.com> * fix: nit Signed-off-by: shuiyisong <xixing.sys@gmail.com> --------- Signed-off-by: shuiyisong <xixing.sys@gmail.com> (cherry picked from commitc17a5e09f7) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: include peer context in distributed query errors (#10118) Signed-off-by: WenyXu <wenymedia@gmail.com> (cherry picked from commit8deb3872b3) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(auth): redact inline user-provider credentials (#10115) * fix(auth): redact inline user-provider credentials Signed-off-by: shuiyisong <xixing.sys@gmail.com> * fix(auth): close user-provider redaction gaps Signed-off-by: shuiyisong <xixing.sys@gmail.com> --------- Signed-off-by: shuiyisong <xixing.sys@gmail.com> (cherry picked from commitadf29740b2) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: register trigger procedure loaders through DdlManager (#10123) Add a loader registration hook to TriggerDdlManager and invoke it before procedure recovery. Test that registration reaches the configured trigger DDL manager. Signed-off-by: fys <fengys1996@gmail.com> (cherry picked from commitb6cf3384dc) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(time): parse zero-hour timezone offsets correctly (#10091) fix(time): preserve zero-hour timezone offset signs Signed-off-by: Minh Vu <vuhoangminh97@gmail.com> (cherry picked from commit25003cea16) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(meta): invalidate all datanode tables on address change (#9986) When a datanode restarts with a new address, metasrv invalidated cached table routes only for the tables in that heartbeat's region stats. The first heartbeat after a restart often reports few or no regions (e.g. with init_regions_in_background), so frontends kept dialing the old address until metadata_cache_ttl expired. Read the previous address via prev_kv when saving it, and when it changed (or a failed save of the same epoch is retried) invalidate every table registered for the datanode in __dn_table. Signed-off-by: Floris Smit <florissmit10@gmail.com> Co-authored-by: Weny Xu <wenymedia@gmail.com> (cherry picked from commit351f4207b4) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(function): require ADMIN statement privileges to execute admin functions (#10120) * fix(function): require ADMIN statement privileges to execute admin functions Read-only accounts could execute the admin UDFs (flush_table, compact_table, flush_flow, gc_regions, migrate_region, reconcile_*, build_index, ...) through ordinary SELECT statements: SELECT is a read-only statement so it passes the statement-level privilege check, and the functions were only guarded by the greptime-catalog scope check inside the UDF. That let read-only users trigger WAL flushes, manifest version bumps, compactions, flow-sink writes and, in distributed mode, region GC/migration and SST deletion. Wrap the privilege check into the admin_fn macro itself, next to the existing greptime-catalog check: before executing, every #[admin_fn] function now requires the same privileges as its ADMIN statement. The check synthesizes the PermissionReq::SqlStatement request an ADMIN <fn>(...) statement produces and evaluates it with the same PermissionCheckerRef plugin the frontend installs, so query invocation (SELECT <fn>(...), EXPLAIN, views, flows) and the ADMIN statement path are gated identically — in particular read-only accounts are denied with PermissionDenied (7006), while write-privileged users keep both invocation styles. With auth disabled (no permission checker), the functions stay invocable by everyone, exactly like ADMIN statements. The denial is wrapped as External(BoxedError) so the 7006 status code survives both the query execution path and the admin statement executor. Regression tests: unit tests for the check (no-checker allows, read-only denied 7006, read-write allowed), an end-to-end test over the macro-generated flush_table UDF, and an integration test where a read-only account is denied 7006 on all 13 functions from SELECT while a read-write account keeps SELECT and ADMIN FLUSH_TABLE working. Signed-off-by: Ning Sun <sunning@greptime.com> * fix(function): expose admin privilege check to downstream macros Signed-off-by: Ning Sun <sunning@greptime.com> --------- Signed-off-by: Ning Sun <sunning@greptime.com> (cherry picked from commitb21b1cdb69) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(catalog): use advertised peer address as process identity (#10153) * fix(catalog): use advertised peer address as process identity The process manager identified the local frontend by its public gRPC address, while metasrv discovers peers by the address advertised in the heartbeat (the internal gRPC address when configured). With separate public and internal listeners, list_all_processes failed to exclude the local node, queried its own management service as a remote frontend, and appended the local registry again, so every local query was listed twice. The same mismatch broke routing of KILL to other frontends. Identify a frontend by the address it advertises to metasrv: - add FrontendOptions::peer_addr, shared by the heartbeat and the process manager, and FrontendOptions::create_process_manager to wire it once; - use the advertised address as the process identity, for self-exclusion in list_all_processes, and for local/remote routing in kill_process. Process ids now carry the address other frontends use to reach the node. When no internal gRPC listener is configured this is the public gRPC address, so the previous behavior is unchanged. The internal listener is the only one serving the frontend management service, so process ids stay routable. The new distributed regression tests exercise separate public and internal addresses: the local query must be listed exactly once while remote frontends are still listed, and KILL must route to a remote frontend. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * test: keep local peer address reserved in kill-routing test The test reserved the local frontend address with a temporary listener that was dropped immediately, then reserved the remote address separately. The kernel could assign the same port to the remote frontend, so the remote kill request would take the local branch and fail to find the remote process. Bind the local address once and keep the listener alive for the whole test so the local and remote frontend identities cannot collide. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> --------- Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> (cherry picked from commit557843dd68) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito): use stored recovery-set bytes for manifest size (#10142) * fix(mito): track stored bytes for manifest recovery Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito): retain manifest sizes on checkpoint and sync Signed-off-by: WenyXu <wenymedia@gmail.com> * test(mito): cover logical manifest size accounting Signed-off-by: WenyXu <wenymedia@gmail.com> * docs(mito): clarify manifest size retention invariants Signed-off-by: WenyXu <wenymedia@gmail.com> --------- Signed-off-by: WenyXu <wenymedia@gmail.com> (cherry picked from commitd7036df73c) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(grpc): propagate cancellation for read query execution (#10166) * x * fix(grpc): restrict cascading cancellation to read query variants Signed-off-by: luofucong <luofc@foxmail.com> --------- Signed-off-by: luofucong <luofc@foxmail.com> (cherry picked from commit2cb473607d) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(datatypes): escape object keys when rendering jsonb as text (#10112) * fix(datatypes): escape object keys when rendering jsonb as text Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> * fix(datatypes): skip unicode normalization for escaped jsonb keys Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> * refactor(datatypes): serialize jsonb to text directly with serde_json Serialize the binary jsonb with serde_json::to_string(&RawJsonb) so that both object keys and string values are escaped by serde_json. This drops fix_unicode_point, its regex and the hand-written key escaping. Errors are propagated instead of falling back to lossy raw bytes. Characters such as U+2028 are now emitted as-is, which is still valid JSON, so the affected sqlness result lines are regenerated. Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> * fix(datatypes): accept JSON text bytes in jsonb_to_string Some write paths (COPY FROM csv/json/parquet, JSON bound as text via MySQL) store JSON text instead of binary jsonb in JSON columns. Re-encode such bytes as jsonb before serializing with serde_json, so they still render (properly escaped) instead of failing with InvalidJsonb. Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> --------- Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> (cherry picked from commitec1ad1f15b) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): share bulk memtable compaction dispatcher across workers (#10022) Each region worker built its own MemtableBuilderProvider, and every provider created its own CompactDispatcher. The limit on background bulk memtable compactions was therefore num_workers times max_background_compactions, while SST compaction uses one engine-wide pool of max_background_compactions. Create one dispatcher in WorkerGroup::start (and start_for_test), pass it to every worker, and make MemtableBuilderProvider::new take it instead of creating its own. SST and memtable compaction keep separate budgets of the same size. Signed-off-by: luckys <190197589+luckysxx@users.noreply.github.com> Co-authored-by: luckys <190197589+luckysxx@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: dennis zhuang <killme2008@gmail.com> (cherry picked from commit9f7cedf58f) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito): decode cached manifest payloads (#10179) * test(mito2): cover compressed manifest cache recovery Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): decode cached manifest object payloads Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): address manifest cache review feedback Signed-off-by: WenyXu <wenymedia@gmail.com> --------- Signed-off-by: WenyXu <wenymedia@gmail.com> (cherry picked from commit4263f5fc01) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: prioritize region ALTER over queued edits (#10193) * fix: prioritize region ALTER over queued edits Signed-off-by: evenyag <realevenyag@gmail.com> * test: use valid edits in ALTER priority regression Signed-off-by: evenyag <realevenyag@gmail.com> * refactor: make region edit dispatch outcomes explicit Signed-off-by: evenyag <realevenyag@gmail.com> * fix: reject queued alters and edits when dropping regions Signed-off-by: evenyag <realevenyag@gmail.com> * test: cover queued ALTER handoff before region edits Signed-off-by: evenyag <realevenyag@gmail.com> --------- Signed-off-by: evenyag <realevenyag@gmail.com> (cherry picked from commitae422ef465) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(meta-srv): invalidate leader cache on transaction errors (#10219) Signed-off-by: WenyXu <wenymedia@gmail.com> (cherry picked from commit4688fa4be8) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): avoid reporting reader filter metrics twice (#10222) * perf(mito2): cache fixed-label reader metric counters Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(mito2): report reader filter metrics only once Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commit5d88d283e5) Signed-off-by: WenyXu <wenymedia@gmail.com> * perf(mito2): reuse static manifest checks across row groups (#10220) * perf(mito2): reuse static manifest checks for cached readers Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * test(mito2): drop redundant pruner test and release entry lock early Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * perf(mito2): cache static manifest keep verdicts directly Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commitc844d44721) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: adapt v1.3.1 backports to release interfaces Signed-off-by: WenyXu <wenymedia@gmail.com> * fix!: enforce sparse primary key schema (#10020) * fix: preserve required sorting for ordinary sparse scans Signed-off-by: shuiyisong <xixing.sys@gmail.com> * fix: enforce sparse primary key schema Signed-off-by: shuiyisong <xixing.sys@gmail.com> * test: fix Signed-off-by: shuiyisong <xixing.sys@gmail.com> --------- Signed-off-by: shuiyisong <xixing.sys@gmail.com> (cherry picked from commitefed847ca6) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: test (#10149) fix: fixture Signed-off-by: shuiyisong <xixing.sys@gmail.com> (cherry picked from commit4633c37dbb) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: tolerate invalid UTF-8 in JSON log ingestion (#10245) * fix: tolerate invalid UTF-8 in JSON ingestion Signed-off-by: shuiyisong <xixing.sys@gmail.com> * fix: tolerate invalid UTF-8 in NDJSON ingestion Signed-off-by: shuiyisong <xixing.sys@gmail.com> * chore: upgrade simd json Signed-off-by: shuiyisong <xixing.sys@gmail.com> * feat: add server default for ignore_errors Signed-off-by: shuiyisong <xixing.sys@gmail.com> --------- Signed-off-by: shuiyisong <xixing.sys@gmail.com> (cherry picked from commit0cb70d4f84) Signed-off-by: WenyXu <wenymedia@gmail.com> * test: simplify backported JSON recovery cases Signed-off-by: WenyXu <wenymedia@gmail.com> * feat(otlp): add v1 schema for auto-created OTLP log tables (#10207) * feat(otlp): add v1 schema for auto-created OTLP log tables New tables created by direct OTLP logs ingestion get a v1 built-in schema: service_name tag from resource service.name ahead of scope_name in the primary key, a skipping index on trace_id, and event_name and observed_timestamp fields. The table is marked with table_data_model=greptime_log_v1. Existing tables without the marker keep the legacy schema. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * refactor(otlp): share resource service.name parsing between logs and traces Log tables now derive service_name with the same rules as trace spans, so both signals agree on the value used to correlate them. The integration test writes twice to cover the existing v1 table path. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commit2714687ab7) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(promql): bound scatter time filter expression depth (#10272) Signed-off-by: evenyag <realevenyag@gmail.com> (cherry picked from commit361f3595db) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(query): use current partition columns in prepared plans (#10244) A prepared statement keeps its logical plan, and that plan holds the table as it was at prepare time. The analyzer reads the partition columns from that table while the regions to scan come from the current route. After a table's partition columns change, the analyzer can consider a query safe to push down, so each region runs the whole query and the frontend concatenates their results. The same happens to the source of a prepared INSERT ... SELECT, which then stores wrong values. Before executing a kept plan, compare each scanned table's partition columns with the current table found by id. Scans of a table whose columns changed get the current table when the schema is unchanged. Otherwise they keep their schema, because a scan's projection holds indices into it, and report the current columns as absent from it, so the query keeps merging on the frontend. Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit297a343fd4) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(time): avoid i32 overflow when converting an out-of-range date (#10299) Signed-off-by: Arpit Jain <arpitjain099@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> (cherry picked from commit402e4a97fc) Signed-off-by: WenyXu <wenymedia@gmail.com> * feat: update dashboard to v0.14.5 (#10270) Co-authored-by: dennis zhuang <killme2008@gmail.com> (cherry picked from commit4c4c8a58fd) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(mito2): keep rows written during staging in the WAL (#10253) * fix(mito2): keep rows written during staging in the WAL A flush during staging committed its SSTs to the staging manifest, then dropped the memtable and released the WAL. If staging did not end successfully those rows were gone. A flush that committed after staging had ended lost its rows even though staging succeeded. Staging regions no longer flush. They are skipped by memory-pressure, periodic and region-limit flushes, and their writes are rejected instead of queued at twice the region limit or when the node's staging memtables reach half of the engine's flush limit. A manual or repartition flush on a staging region with data gets a retryable error; the migration pre-flush and the WAL prune flush reply success without flushing. Closing a staging region leaves staging first, so skip-WAL rows are flushed to the normal manifest. Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): keep accounting and closing staging regions during staged edits Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): track staged edits without relying on the partition info Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test(mito2): synchronize staging close tests with worker admission Signed-off-by: jeremyhi <fengjiachun@gmail.com> * test(mito2): observe the manifest lock wait when closing staging regions Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): detect staged edits through the staging partition info Signed-off-by: jeremyhi <fengjiachun@gmail.com> * docs(mito2): record that staging regions must not flush Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): do not restore staging after a close abandons the edit Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): reject region edits during a close-time flush Signed-off-by: jeremyhi <fengjiachun@gmail.com> * style(mito2): format the staging tests Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): reject staging edits once staging is abandoned Signed-off-by: jeremyhi <fengjiachun@gmail.com> * fix(mito2): bind apply-staging edits to their partition expression Signed-off-by: jeremyhi <fengjiachun@gmail.com> * docs(mito2): note that staging regions pin their topic's prune point Signed-off-by: jeremyhi <fengjiachun@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> (cherry picked from commit8da533c35f) Signed-off-by: WenyXu <wenymedia@gmail.com> * perf(query): push column projections through MergeScan (#10221) * perf(query): push column projections through MergeScan Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(query): retain empty projections and refresh sqlness plans Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * test(query): update TSID join plans after projection pushdown Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commit16123d806b) Signed-off-by: WenyXu <wenymedia@gmail.com> * test: adapt staging and prepared-plan regressions to v1.3 Signed-off-by: WenyXu <wenymedia@gmail.com> * test: regenerate MergeScan semi-join snapshot on v1.3 Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: restrict JSON retries to invalid UTF-8 errors (#10302) * fix: restrict JSON retries to invalid UTF-8 errors Signed-off-by: shuiyisong <xixing.sys@gmail.com> * test: isolate UTF-8 retry counter assertions Signed-off-by: shuiyisong <xixing.sys@gmail.com> --------- Signed-off-by: shuiyisong <xixing.sys@gmail.com> (cherry picked from commit09c0291575) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(ci): prepare Ubuntu build runners and default EC2 disks to 500 GiB (#10156) * ci: share Linux runner dependency setup for builds and benchmarks Signed-off-by: WenyXu <wenymedia@gmail.com> * ci: configure EC2 build runner volumes with a 500 GiB default Signed-off-by: WenyXu <wenymedia@gmail.com> --------- Signed-off-by: WenyXu <wenymedia@gmail.com> (cherry picked from commitc02e1f58af) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(ci): increase nightly JSONBench runner root volume (#10146) Signed-off-by: luofucong <luofc@foxmail.com> (cherry picked from commite80cf9a9ae) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(datatypes): render jsonb stored as JSON text without panics or wrong values (#10197) * fix(datatypes): decode jsonb before rendering it as text jsonb_to_string serialized the bytes through RawJsonb's Serialize impl, which panics with an out-of-range slice index on JSON text such as "hello world" or " null" (stored by COPY FROM and MySQL text parameters) and on truncated jsonb. Its text fallback was also stricter than the extended parser reads used before. Decode with jsonb::from_slice, as reads did before #10112, then write the value out with serde_json escaping for keys and strings. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * perf(datatypes): keep streaming jsonb serialization in jsonb_to_string Decoding into a jsonb::Value tree allocates per array, object and key on every JSON cell returned over PostgreSQL and MySQL. Go back to serializing the raw bytes with RawJsonb's Serialize impl, and bump jsonb to a rev whose Serialize returns an error instead of panicking on out-of-range payloads (GreptimeTeam/jsonb#2). Bytes that fail to serialize are parsed as JSON text with the extended parser, as jsonb::from_slice does. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * test(datatypes): pin text values that used to read back as false Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * chore: bump jsonb to reject scalar headers with non-zero length bits JSON text over ~2 MB could still pass the payload bounds check and read back as a wrong value (GreptimeTeam/jsonb#2). Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(datatypes): report the text parse error when JSON bytes are neither jsonb nor text Also pin jsonb_to_serde_json on JSON text scalars that used to decode as false. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * chore: pin jsonb to the merged commit on main GreptimeTeam/jsonb#2 reached main through GreptimeTeam/jsonb#3. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commitddc16bafe8) Signed-off-by: WenyXu <wenymedia@gmail.com> * revert(mito2): exclude range cache singleflight changes from v1.3.1 Revertb33634417e(#9935) from the release candidate. Preserve the separate SST lifetime fix (#9950). The range cache admission experiment did not restore Q2 performance. Signed-off-by: WenyXu <wenymedia@gmail.com> * fix: redact credential table options in user-visible output (#10346) information_schema.tables.create_options (and SHOW TABLE STATUS) printed object store credentials of external tables verbatim, and SHOW CREATE TABLE masked only access_key_id and secret_access_key. Mask all four credential keys in both paths, and sort extra options in create_options by key. Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commit62dad907d0) Signed-off-by: WenyXu <wenymedia@gmail.com> * perf(mito2): prefilter single-column dynamic filters (#10340) * perf(mito2): prefilter dynamic join membership Read the narrow dynamic-membership column before the full projection and use a stable per-row-group mask to select rows. The live filter above the scan stays authoritative; bounds-only and unsupported shapes keep all rows. Signed-off-by: discord9 <discord9@163.com> * test: cover dynamic prefilter cache and generations Prove the prefilter-result cache keeps the static mask but never reuses a dynamic mask across producer generations. Document why a superseded dynamic mask is discarded rather than assumed monotone. Signed-off-by: discord9 <discord9@163.com> --------- Signed-off-by: discord9 <discord9@163.com> (cherry picked from commitc937e3997b) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(servers): authorize HTTP database overrides (#10378) * fix(servers): authorize HTTP database overrides Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(servers): update the HTTP output benchmark handler call Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(servers): authorize Prometheus database overrides Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(servers): retain authorized label lookup scope Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commit5d88de5290) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(config)!: redact credentials from diagnostic TOML (#10381) * fix(config): redact credentials from diagnostic TOML Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(config): redact credentials at their owning fields Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(config): cover skipped SAS tokens and export logs Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(cli): mask SAS tokens before overlapping account names Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(cli): redact SAS tokens before overlapping account fields Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(cli): mask containing credentials before shorter values Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commitca1b8c7c98) Signed-off-by: WenyXu <wenymedia@gmail.com> * feat: update dashboard to v0.14.6 (#10365) (cherry picked from commit2e1ce9808a) Signed-off-by: WenyXu <wenymedia@gmail.com> * feat(query): serialize remote dynamic membership (#10341) * feat(query): serialize remote dynamic membership Recover single-column UTF-8 build-key membership from InList and HashTableLookupExpr producers and send it to remote datanodes using the existing PhysicalInListNode. Non-monotone or unsupported subtrees widen to true; the receiver keeps the live filter authoritative. Signed-off-by: discord9 <discord9@163.com> * refactor(query): send lookup membership as a key list Serialize a HashTableLookupExpr as the existing PhysicalInListNode and preserve the rest of the expression tree. Remove per-subtree monotone and true rewrites; only an unrepresentable lookup or an over-budget payload falls back at the whole-payload level. Signed-off-by: discord9 <discord9@163.com> * docs: tighten narrow membership contract Clarify that the key-list transport is a positive pruning hint, not universal Boolean equivalence, and test that a NULL probe survives the IS NULL wrapper. Signed-off-by: discord9 <discord9@163.com> * fix(query): retain safe bounds on membership fallback When a key-list predicate cannot be shipped, keep top-level conjuncts that contain no membership and re-encode their conjunction. Drop membership-bearing conjuncts whole; fall back to true only when no safe bounds remain. Signed-off-by: discord9 <discord9@163.com> * fix(query): skip unrepresentable dynamic filter snapshots Do not synthesize a true predicate when a runtime hash-table lookup has no wire representation. Capture and fanout skip the affected snapshot, keep the query running, and report PushedDown::No so the parent filter is retained. Safe membership-free conjuncts still travel, and a producer-supplied true remains encodable. Cover restrictive-to-true updates, unsupported initial registrations with later supported updates, final unsupported cleanup, and NULL build keys. Signed-off-by: discord9 <discord9@163.com> * docs(query): clarify 642-key payload budget comment Signed-off-by: discord9 <discord9@163.com> * refactor(query): tighten dynamic membership encoding Preserve static IN conjuncts when only a runtime lookup is unrepresentable, apply the IN-list exclusion only on the over-budget path, and derive the membership count guard from the byte budget before materializing literals. Document that decoded dynamic filters are pruning-only, fix the NOT/CASE contract wording, deduplicate test helpers, and justify the schema-less InList proto encoding. Signed-off-by: discord9 <discord9@163.com> * fix(query): reset stale dynamic filters on unsupported updates Publish an explicit true reset when a producer generation cannot be carried, instead of leaving an older narrower predicate that could prune rows after widening. Keep the unsupported expression unrewritten; the reset is a transport-built invalidation. Type over-budget build-key memberships as DynFilterPayloadTooLarge, accept scalar-subquery IN lists under the conjunct-retention contract, and clarify the no-initial-predicate wording. Signed-off-by: discord9 <discord9@163.com> * docs(query): scope no-true rule to the encoder Clarify that the encoder never substitutes true for a producer node, while the long-lived fanout path publishes an explicit true reset to invalidate a stale region predicate. Point at the fanout caller instead of claiming producers always skip refused generations. Signed-off-by: discord9 <discord9@163.com> * docs(query): correct reset wording Fix the inverted conjunct-retention sentence and describe initial capture versus ongoing fanout resets consistently in the error docs. Signed-off-by: discord9 <discord9@163.com> --------- Signed-off-by: discord9 <discord9@163.com> (cherry picked from commitf88af153ec) Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(auth): secure MySQL and PostgreSQL database selection (#10382) * fix(mysql): authorize the default database at login Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(auth): validate MySQL handshake scope and SQL USE Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(auth): authorize PostgreSQL schema selection Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(servers): defer PostgreSQL database lookup until authorized Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * test(servers): propagate catalog lookup errors in protocol tests Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(postgres): skip unusable search path candidates Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(auth): log database authorization and selection outcomes Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(auth): preserve search path responses and schema boundaries Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(auth): clarify database selection diagnostics Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(mysql): format handshake username in structured logs Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(auth): secure database-less sessions and failed startup Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * fix(mysql): retain authorized default database selection Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * refactor(auth): separate database selection from request dispatch Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * test(mysql): align schema validation with database-less login Signed-off-by: Dennis Zhuang <killme2008@gmail.com> * docs(auth): explain database-less session restrictions Signed-off-by: Dennis Zhuang <killme2008@gmail.com> --------- Signed-off-by: Dennis Zhuang <killme2008@gmail.com> (cherry picked from commit6e025eef61) Signed-off-by: WenyXu <wenymedia@gmail.com> * chore: bump candidate release version to v1.3.1 Signed-off-by: WenyXu <wenymedia@gmail.com> --------- Signed-off-by: jeremyhi <fengjiachun@gmail.com> Signed-off-by: WenyXu <wenymedia@gmail.com> Signed-off-by: fys <fengys1996@gmail.com> Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> Signed-off-by: lczllx <2181719471@qq.com> Signed-off-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> Signed-off-by: Byte-Naut <Byte-Naut@proton.me> Signed-off-by: shuiyisong <xixing.sys@gmail.com> Signed-off-by: Minh Vu <vuhoangminh97@gmail.com> Signed-off-by: Floris Smit <florissmit10@gmail.com> Signed-off-by: Ning Sun <sunning@greptime.com> Signed-off-by: luofucong <luofc@foxmail.com> Signed-off-by: luckys <190197589+luckysxx@users.noreply.github.com> Signed-off-by: evenyag <realevenyag@gmail.com> Signed-off-by: Dennis Zhuang <killme2008@gmail.com> Signed-off-by: Arpit Jain <arpitjain099@gmail.com> Signed-off-by: discord9 <discord9@163.com> Co-authored-by: jeremyhi <jiachun_feng@proton.me> Co-authored-by: fys <40801205+fengys1996@users.noreply.github.com> Co-authored-by: Lei, HUANG <6406592+v0y4g3r@users.noreply.github.com> Co-authored-by: Dragon Roar <2181719471@qq.com> Co-authored-by: Yvan Wang <131545713+BootstrapperSBL@users.noreply.github.com> Co-authored-by: B. Naut <Byte-Naut@proton.me> Co-authored-by: shuiyisong <113876041+shuiyisong@users.noreply.github.com> Co-authored-by: Minh Vu <vuhoangminh97@gmail.com> Co-authored-by: Floris Smit <florissmit10@users.noreply.github.com> Co-authored-by: Ning Sun <sunng@protonmail.com> Co-authored-by: LFC <990479+MichaelScofield@users.noreply.github.com> Co-authored-by: luckysxx <2824602789@qq.com> Co-authored-by: luckys <190197589+luckysxx@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: dennis zhuang <killme2008@gmail.com> Co-authored-by: Yingwen <realevenyag@gmail.com> Co-authored-by: Arpit Jain <3242828+arpitjain099@users.noreply.github.com> Co-authored-by: sun <sunchang_long@163.com> Co-authored-by: discord9 <discord9@163.com>