This is an automated email from the ASF dual-hosted git repository.

gavinchou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new fe923893522 [fix](cloud) refresh tablet meta of continuously ingested 
tablets (#67972)
fe923893522 is described below

commit fe923893522b884bef31e2972ed00a2339e59c60
Author: Xin Liao <[email protected]>
AuthorDate: Wed Sep 16 10:01:54 2026 +0800

    [fix](cloud) refresh tablet meta of continuously ingested tablets (#67972)
    
    
    Problem Summary:
    
    `CloudTabletMgr::sync_tablets()` selected the tablets it would work on
    by `last_sync_time_s`, then did two things to each one: `sync_meta()`
    followed by `sync_rowsets()`.
    
    But that clock only tracks how stale a tablet's **rowsets** are. It is
    advanced inside `sync_tablet_rowsets()`, and only when that actually
    issues its RPC. A tablet under continuous ingest therefore keeps it
    permanently fresh, never falls below the staleness bound, and never has
    `sync_meta()` called on it at all.
    
    Its `TabletMeta` then stays at whatever it was built with for the
    lifetime of the object, so properties that only arrive through the
    tablet meta are never picked up. `ttl_seconds` is the one that shows:
    `CloudTablet::sync_meta()` is the only thing that refreshes it, and it
    feeds the file cache expiration computed on the write path
    (`CloudRowsetBuilder`, compaction output), the read path
    (`TabletReader`, `OlapScanner`) and warm-up. An `ALTER TABLE ... SET
    ("file_cache_ttl_seconds" = ...)` on a table under load therefore has no
    effect on those blocks, which keep landing in the wrong queue with an
    expiration derived from the stale value.
    
    ### Release note
    
    Fixed tablet metadata never being refreshed for tablets under continuous
    ingest, which left properties such as `file_cache_ttl_seconds` stale on
    those tablets after an ALTER.
    
    ### What is changed and how it works?
    
    **1. Give meta staleness its own clock.** `last_sync_tablet_meta_time_s`
    is advanced only by `sync_meta()`.
    
    **2. Rename `last_sync_time_s` to `last_sync_rowsets_time_s`** (separate
    commit, mechanical). The old name says "sync" while the clock only ever
    tracked rowsets, and reading it as "when this tablet was last synced" is
    exactly the mistake that let meta work be gated on it. With a second
    clock alongside it the old name would be actively misleading. This also
    keeps the field named the same as on branch-3.1.
    
    **3. `sync_tablets()` decides per tablet which of the two RPCs it is due
    for**, rather than sorting tablets into a single bucket:
    
    - rowsets stale -> sync rowsets, and the meta too. Pulling rowsets
    implies pulling the meta, which is the relationship the single pass had:
    the rowsets are only as trustworthy as the meta they belong to.
    - rowsets fresh but meta stale -> sync the meta only, one RPC instead of
    the two a full sync costs. This is the case that used to be skipped
    entirely.
    - both fresh -> skip.
    
    Work is still ordered by the older of the two clocks, so a mid-run stop
    has already served the tablets that waited longest.
    
    New bvars `sync_tablets_meta_num` and `sync_tablets_rowsets_num` split
    what `num_sync` used to lump together, and the finish log reports both.
---
 be/src/cloud/cloud_base_compaction.cpp             |   6 +-
 be/src/cloud/cloud_cumulative_compaction.cpp       |   6 +-
 be/src/cloud/cloud_full_compaction.cpp             |   2 +-
 be/src/cloud/cloud_index_change_compaction.cpp     |   4 +-
 be/src/cloud/cloud_meta_mgr.cpp                    |   2 +-
 be/src/cloud/cloud_tablet.cpp                      |   1 +
 be/src/cloud/cloud_tablet.h                        |   9 +-
 be/src/cloud/cloud_tablet_mgr.cpp                  |  85 +++++++++++++----
 be/src/storage/compaction/compaction.cpp           |   2 +-
 be/test/cloud/cloud_compaction_test.cpp            |  16 ++--
 be/test/cloud/cloud_tablet_mgr_test.cpp            | 101 +++++++++++++++++++++
 .../cloud_index_change_compaction_test.cpp         |   4 +-
 12 files changed, 196 insertions(+), 42 deletions(-)

diff --git a/be/src/cloud/cloud_base_compaction.cpp 
b/be/src/cloud/cloud_base_compaction.cpp
index 87e2378fdba..3570abe492f 100644
--- a/be/src/cloud/cloud_base_compaction.cpp
+++ b/be/src/cloud/cloud_base_compaction.cpp
@@ -67,7 +67,7 @@ Status CloudBaseCompaction::prepare_compact() {
         // synchronized with meta-service.
         if (_tablet->tablet_meta()->all_rs_metas().size() >=
                     cloud_tablet()->fetch_add_approximate_num_rowsets(0) &&
-            cloud_tablet()->last_sync_time_s > 0) {
+            cloud_tablet()->last_sync_rowsets_time_s > 0) {
             need_sync_tablet = false;
         }
     }
@@ -136,7 +136,7 @@ Status CloudBaseCompaction::request_global_lock() {
         cloud_tablet()->set_last_base_compaction_failure_time(UnixMillis());
         if (resp.status().code() == cloud::STALE_TABLET_CACHE) {
             // set last_sync_time to 0 to force sync tablet next time
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
         } else if (resp.status().code() == cloud::TABLET_NOT_FOUND) {
             // tablet not found
             cloud_tablet()->clear_cache();
@@ -440,7 +440,7 @@ Status CloudBaseCompaction::modify_rowsets() {
         // the tablet to be unable to synchronize the rowset meta changes 
generated by cumu compaction.
         cloud_tablet()->set_base_compaction_cnt(stats.base_compaction_cnt());
         if (stats.cumulative_point() > 
cloud_tablet()->cumulative_layer_point()) {
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
         }
         if (output_rowset_delete_bitmap) {
             
_tablet->tablet_meta()->delete_bitmap().merge(*output_rowset_delete_bitmap);
diff --git a/be/src/cloud/cloud_cumulative_compaction.cpp 
b/be/src/cloud/cloud_cumulative_compaction.cpp
index 42c97932c0b..10c00bebae1 100644
--- a/be/src/cloud/cloud_cumulative_compaction.cpp
+++ b/be/src/cloud/cloud_cumulative_compaction.cpp
@@ -157,7 +157,7 @@ Status CloudCumulativeCompaction::prepare_compact() {
         // synchronized with meta-service.
         if (_tablet->tablet_meta()->all_rs_metas().size() >=
                     cloud_tablet()->fetch_add_approximate_num_rowsets(0) &&
-            cloud_tablet()->last_sync_time_s > 0) {
+            cloud_tablet()->last_sync_rowsets_time_s > 0) {
             need_sync_tablet = false;
         }
     }
@@ -238,7 +238,7 @@ Status CloudCumulativeCompaction::request_global_lock() {
     if (!st.ok()) {
         if (resp.status().code() == cloud::STALE_TABLET_CACHE) {
             // set last_sync_time to 0 to force sync tablet next time
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
         } else if (resp.status().code() == cloud::TABLET_NOT_FOUND) {
             // tablet not found
             cloud_tablet()->clear_cache();
@@ -925,7 +925,7 @@ void 
CloudCumulativeCompaction::update_cumulative_point(int64_t input_cumulative
     if (!st.ok()) {
         if (start_resp.status().code() == cloud::STALE_TABLET_CACHE) {
             // set last_sync_time to 0 to force sync tablet next time
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
         } else if (start_resp.status().code() == cloud::TABLET_NOT_FOUND) {
             // tablet not found
             cloud_tablet()->clear_cache();
diff --git a/be/src/cloud/cloud_full_compaction.cpp 
b/be/src/cloud/cloud_full_compaction.cpp
index 12ea9c87c99..1133330baa4 100644
--- a/be/src/cloud/cloud_full_compaction.cpp
+++ b/be/src/cloud/cloud_full_compaction.cpp
@@ -113,7 +113,7 @@ Status CloudFullCompaction::request_global_lock() {
     if (!st.ok()) {
         if (resp.status().code() == cloud::STALE_TABLET_CACHE) {
             // set last_sync_time to 0 to force sync tablet next time
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
         } else if (resp.status().code() == cloud::TABLET_NOT_FOUND) {
             // tablet not found
             cloud_tablet()->clear_cache();
diff --git a/be/src/cloud/cloud_index_change_compaction.cpp 
b/be/src/cloud/cloud_index_change_compaction.cpp
index 3bb55f46ce8..f9bbd5dea3d 100644
--- a/be/src/cloud/cloud_index_change_compaction.cpp
+++ b/be/src/cloud/cloud_index_change_compaction.cpp
@@ -170,7 +170,7 @@ Status 
CloudIndexChangeCompaction::request_global_lock(bool& should_skip_err) {
     if (!st.ok()) {
         if (resp.status().code() == cloud::STALE_TABLET_CACHE) {
             // set last_sync_time to 0 to force sync tablet next time
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
             should_skip_err = true;
         } else if (resp.status().code() == cloud::TABLET_NOT_FOUND) {
             // tablet not found
@@ -380,7 +380,7 @@ void 
CloudIndexChangeCompaction::_update_tablet_for_base_compaction(
         // the tablet to be unable to synchronize the rowset meta changes 
generated by cumu compaction.
         cloud_tablet()->set_base_compaction_cnt(stats.base_compaction_cnt());
         if (stats.cumulative_point() > 
cloud_tablet()->cumulative_layer_point()) {
-            cloud_tablet()->last_sync_time_s = 0;
+            cloud_tablet()->last_sync_rowsets_time_s = 0;
         }
         if (output_rowset_delete_bitmap) {
             
_tablet->tablet_meta()->delete_bitmap().merge(*output_rowset_delete_bitmap);
diff --git a/be/src/cloud/cloud_meta_mgr.cpp b/be/src/cloud/cloud_meta_mgr.cpp
index 688c18ecb9f..be2124d2c50 100644
--- a/be/src/cloud/cloud_meta_mgr.cpp
+++ b/be/src/cloud/cloud_meta_mgr.cpp
@@ -885,7 +885,7 @@ Status 
CloudMetaMgr::sync_tablet_rowsets_unlocked(CloudTablet* tablet,
         }
 
         int64_t now = 
duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
-        tablet->last_sync_time_s = now;
+        tablet->last_sync_rowsets_time_s = now;
 
         if (sync_stats) {
             sync_stats->get_remote_rowsets_rpc_ns +=
diff --git a/be/src/cloud/cloud_tablet.cpp b/be/src/cloud/cloud_tablet.cpp
index da45f5e87db..de3394688af 100644
--- a/be/src/cloud/cloud_tablet.cpp
+++ b/be/src/cloud/cloud_tablet.cpp
@@ -1623,6 +1623,7 @@ Status CloudTablet::sync_meta() {
         }
     }
 
+    last_sync_tablet_meta_time_s = ::time(nullptr);
     return Status::OK();
 }
 
diff --git a/be/src/cloud/cloud_tablet.h b/be/src/cloud/cloud_tablet.h
index 96fa5e6faa5..6a2bfff05a1 100644
--- a/be/src/cloud/cloud_tablet.h
+++ b/be/src/cloud/cloud_tablet.h
@@ -348,7 +348,14 @@ public:
 
     const auto& rowset_map() const { return _rs_version_map; }
 
-    int64_t last_sync_time_s = 0;
+    // How long since this tablet's ROWSETS were pulled from MS. Only 
sync_rowsets() advances
+    // it, and only when it actually issues the RPC.
+    int64_t last_sync_rowsets_time_s = 0;
+    // How long since this tablet's META was pulled from MS, which is what 
carries properties
+    // such as the file cache TTL. Only sync_meta() advances it. Tracked 
separately on
+    // purpose: a tablet under continuous ingest keeps the rowsets clock 
permanently fresh,
+    // so gating meta work on that one starves the meta refresh entirely.
+    int64_t last_sync_tablet_meta_time_s = 0;
     int64_t last_load_time_ms = 0;
     int64_t last_base_compaction_success_time_ms = 0;
     int64_t last_cumu_compaction_success_time_ms = 0;
diff --git a/be/src/cloud/cloud_tablet_mgr.cpp 
b/be/src/cloud/cloud_tablet_mgr.cpp
index 82dd46a924d..d65c2fcbeef 100644
--- a/be/src/cloud/cloud_tablet_mgr.cpp
+++ b/be/src/cloud/cloud_tablet_mgr.cpp
@@ -19,7 +19,10 @@
 
 #include <bthread/countdown_event.h>
 
+#include <algorithm>
 #include <chrono>
+#include <set>
+#include <utility>
 
 #include "cloud/cloud_cluster_info.h"
 #include "cloud/cloud_meta_mgr.h"
@@ -40,6 +43,8 @@ bvar::Adder<uint64_t> g_base_compaction_not_frozen_tablet_num(
         "base_compaction_not_frozen_tablet_num");
 bvar::Adder<uint64_t> g_cumu_compaction_not_frozen_tablet_num(
         "cumu_compaction_not_frozen_tablet_num");
+bvar::Adder<uint64_t> g_sync_tablets_meta_num("sync_tablets_meta_num");
+bvar::Adder<uint64_t> g_sync_tablets_rowsets_num("sync_tablets_rowsets_num");
 namespace {
 
 // port from
@@ -386,53 +391,93 @@ std::vector<std::weak_ptr<CloudTablet>> 
CloudTabletMgr::get_weak_tablets() {
 
 void CloudTabletMgr::sync_tablets(const CountDownLatch& stop_latch) {
     LOG_INFO("begin to sync tablets");
-    int64_t last_sync_time_bound = ::time(nullptr) - 
config::tablet_sync_interval_s;
 
-    auto weak_tablets = get_weak_tablets();
+    // A tablet carries two staleness clocks and each one gates a different 
RPC:
+    //
+    //   last_sync_rowsets_time_s
+    //       how long since we pulled this tablet's ROWSETS from MS. Only 
sync_rowsets()
+    //       advances it, and only when it actually issues the RPC -- a query 
whose requested
+    //       version we already hold returns early and leaves the clock 
untouched.
+    //
+    //   last_sync_tablet_meta_time_s
+    //       how long since we pulled this tablet's META from MS, which is 
what carries
+    //       properties such as the file cache TTL. Only sync_meta() advances 
it.
+    //
+    // They have to be read separately. A tablet under continuous ingest keeps 
the rowsets
+    // clock permanently fresh, so selecting meta work by it -- as this used 
to -- means such a
+    // tablet never has its meta refreshed at all, and it keeps serving 
whatever TTL it was
+    // built with.
+    const int64_t stale_before = ::time(nullptr) - 
config::tablet_sync_interval_s;
+
+    struct Work {
+        std::weak_ptr<CloudTablet> tablet;
+        bool needs_meta = false;
+        bool needs_rowsets = false;
+    };
 
-    // sort by last_sync_time
+    // Ordered by the older of the two clocks, so that if we are told to stop 
half way, the
+    // tablets that have been waiting longest have already been served.
     static auto cmp = [](const auto& a, const auto& b) { return a.first < 
b.first; };
-    std::multiset<std::pair<int64_t, std::weak_ptr<CloudTablet>>, 
decltype(cmp)>
-            sync_time_tablet_set(cmp);
+    std::multiset<std::pair<int64_t, Work>, decltype(cmp)> due(cmp);
 
-    for (auto& weak_tablet : weak_tablets) {
-        if (auto tablet = weak_tablet.lock()) {
-            int64_t last_sync_time = tablet->last_sync_time_s;
-            if (last_sync_time <= last_sync_time_bound) {
-                sync_time_tablet_set.emplace(last_sync_time, weak_tablet);
-            }
+    for (auto& weak_tablet : get_weak_tablets()) {
+        auto tablet = weak_tablet.lock();
+        if (!tablet) {
+            continue;
+        }
+        const bool needs_rowsets = tablet->last_sync_rowsets_time_s <= 
stale_before;
+        Work work {
+                .tablet = weak_tablet,
+                // Pulling rowsets implies pulling the tablet meta: the 
rowsets we are about
+                // to take are only as trustworthy as the meta they belong to, 
and this is
+                // the relationship the previous single pass had.
+                .needs_meta = needs_rowsets || 
tablet->last_sync_tablet_meta_time_s <= stale_before,
+                .needs_rowsets = needs_rowsets};
+        if (!work.needs_meta && !work.needs_rowsets) {
+            continue;
         }
+        due.emplace(
+                std::min(tablet->last_sync_tablet_meta_time_s, 
tablet->last_sync_rowsets_time_s),
+                std::move(work));
     }
 
     int num_sync = 0;
-    for (auto&& [_, weak_tablet] : sync_time_tablet_set) {
+    int num_sync_meta = 0;
+    for (auto&& [_, work] : due) {
         if (stop_latch.count() <= 0) {
             break;
         }
+        auto tablet = work.tablet.lock();
+        if (!tablet) {
+            continue;
+        }
 
-        if (auto tablet = weak_tablet.lock()) {
-            if (tablet->last_sync_time_s > last_sync_time_bound) {
-                continue;
-            }
-
-            ++num_sync;
+        if (work.needs_meta) {
+            ++num_sync_meta;
+            g_sync_tablets_meta_num << 1;
             auto st = tablet->sync_meta();
             if (!st) {
                 LOG_WARNING("failed to sync tablet meta {}", 
tablet->tablet_id()).error(st);
                 if (st.is<ErrorCode::NOT_FOUND>()) {
+                    // the tablet is gone from MS, there is nothing left to 
sync
                     continue;
                 }
             }
+        }
+
+        if (work.needs_rowsets) {
+            ++num_sync;
+            g_sync_tablets_rowsets_num << 1;
             SyncOptions options;
             options.query_version = -1;
             options.merge_schema = true;
-            st = tablet->sync_rowsets(options);
+            auto st = tablet->sync_rowsets(options);
             if (!st) {
                 LOG_WARNING("failed to sync tablet rowsets {}", 
tablet->tablet_id()).error(st);
             }
         }
     }
-    LOG_INFO("finish sync tablets").tag("num_sync", num_sync);
+    LOG_INFO("finish sync tablets").tag("num_sync", 
num_sync).tag("num_sync_meta", num_sync_meta);
 }
 
 Status CloudTabletMgr::get_topn_tablets_to_compact(
diff --git a/be/src/storage/compaction/compaction.cpp 
b/be/src/storage/compaction/compaction.cpp
index d4e2ec24030..015c6ee497a 100644
--- a/be/src/storage/compaction/compaction.cpp
+++ b/be/src/storage/compaction/compaction.cpp
@@ -2112,7 +2112,7 @@ bool 
CloudCompactionMixin::should_apply_cumulative_compaction_result(
     }
     if (response_cumulative_compaction_cnt != local_cumulative_compaction_cnt 
+ 1) {
         // Only the current task's output is available locally. Sync all 
missing outputs instead.
-        cloud_tablet()->last_sync_time_s = 0;
+        cloud_tablet()->last_sync_rowsets_time_s = 0;
         LOG_INFO("defer applying cumulative compaction result until tablet 
sync")
                 .tag("tablet_id", _tablet->tablet_id())
                 .tag("job_id", _uuid)
diff --git a/be/test/cloud/cloud_compaction_test.cpp 
b/be/test/cloud/cloud_compaction_test.cpp
index 9f0ac135bc0..683e72b3064 100644
--- a/be/test/cloud/cloud_compaction_test.cpp
+++ b/be/test/cloud/cloud_compaction_test.cpp
@@ -456,7 +456,7 @@ TEST_F(CloudCompactionTest, 
cumulative_global_lock_failure_keeps_thread_count_ba
         std::unique_lock lock(tablet->get_header_lock());
         tablet->add_rowsets(std::move(rowsets), false, lock);
     }
-    tablet->last_sync_time_s = 1;
+    tablet->last_sync_rowsets_time_s = 1;
     tablet->_approximate_num_rowsets = 0;
 
     ASSERT_TRUE(ThreadPoolBuilder("CumuCompactionTaskThreadPoolTest")
@@ -579,16 +579,16 @@ public:
 TEST_F(CloudCompactionTest, cumulative_result_requires_next_counter) {
     auto tablet = std::make_shared<CloudTablet>(_engine, _tablet_meta);
     tablet->set_cumulative_compaction_cnt(1);
-    tablet->last_sync_time_s = 1;
+    tablet->last_sync_rowsets_time_s = 1;
     TestableCloudCompaction compaction(_engine, tablet);
 
     std::unique_lock lock(tablet->get_header_lock());
     EXPECT_FALSE(compaction.test_should_apply_cumulative_compaction_result(1));
-    EXPECT_EQ(tablet->last_sync_time_s, 1);
+    EXPECT_EQ(tablet->last_sync_rowsets_time_s, 1);
     EXPECT_TRUE(compaction.test_should_apply_cumulative_compaction_result(2));
-    EXPECT_EQ(tablet->last_sync_time_s, 1);
+    EXPECT_EQ(tablet->last_sync_rowsets_time_s, 1);
     EXPECT_FALSE(compaction.test_should_apply_cumulative_compaction_result(3));
-    EXPECT_EQ(tablet->last_sync_time_s, 0);
+    EXPECT_EQ(tablet->last_sync_rowsets_time_s, 0);
 }
 
 class TestableCloudCumulativeCompaction : public CloudCumulativeCompaction {
@@ -627,7 +627,7 @@ static CloudTabletSPtr 
create_cloud_tablet_with_rowsets(CloudStorageEngine& engi
     tablet->set_cumulative_layer_point(cumulative_point);
     
tablet->fetch_add_approximate_num_rowsets(static_cast<int64_t>(num_rowsets) -
                                               
tablet->fetch_add_approximate_num_rowsets(0));
-    tablet->last_sync_time_s = 1;
+    tablet->last_sync_rowsets_time_s = 1;
     return tablet;
 }
 
@@ -694,7 +694,7 @@ TEST_F(CloudCompactionTest, 
base_result_with_newer_cumulative_point_forces_sync)
 
         ASSERT_TRUE(compaction.modify_rowsets().ok());
         EXPECT_EQ(tablet->cumulative_layer_point(), 6);
-        EXPECT_EQ(tablet->last_sync_time_s, expected_sync_time);
+        EXPECT_EQ(tablet->last_sync_rowsets_time_s, expected_sync_time);
     };
 
     run_case(10008, 8, 0);
@@ -903,7 +903,7 @@ TEST_F(CloudCompactionTest, 
parallel_pick_keeps_mode_after_dynamic_config_change
     EXPECT_TRUE(commit_called);
     EXPECT_EQ(tablet->cumulative_compaction_cnt(), 0);
     EXPECT_EQ(tablet->cumulative_layer_point(), 2);
-    EXPECT_EQ(tablet->last_sync_time_s, 0);
+    EXPECT_EQ(tablet->last_sync_rowsets_time_s, 0);
 }
 
 TEST_F(CloudCompactionTest, 
parallel_pick_advances_continuous_low_prefix_through_delete) {
diff --git a/be/test/cloud/cloud_tablet_mgr_test.cpp 
b/be/test/cloud/cloud_tablet_mgr_test.cpp
index c893b72a475..2859a476e3e 100644
--- a/be/test/cloud/cloud_tablet_mgr_test.cpp
+++ b/be/test/cloud/cloud_tablet_mgr_test.cpp
@@ -26,10 +26,15 @@
 #include <memory>
 #include <mutex>
 #include <thread>
+#include <unordered_map>
+#include <vector>
 
 #include "cloud/cloud_storage_engine.h"
+#include "cloud/cloud_tablet.h"
+#include "cloud/config.h"
 #include "cpp/sync_point.h"
 #include "storage/tablet/tablet_meta.h"
+#include "util/countdown_latch.h"
 #include "util/uid_util.h"
 
 namespace doris {
@@ -210,4 +215,100 @@ TEST_F(CloudTabletMgrTest, 
TestGetTabletIfCachedOnlyReturnsCachedTablet) {
     sp->clear_all_call_backs();
 }
 
+// A tablet under continuous ingest keeps last_sync_rowsets_time_s permanently 
fresh, because every
+// rowset sync advances it. Selecting meta work by that same clock meant such 
a tablet never had
+// sync_meta() called on it at all, so it kept serving the tablet properties 
-- the file cache
+// TTL among them -- that it happened to be built with.
+TEST_F(CloudTabletMgrTest, 
SyncTabletsRefreshesMetaOfContinuouslyIngestedTablet) {
+    auto sp = SyncPoint::get_instance();
+    sp->clear_all_call_backs();
+    sp->enable_processing();
+
+    std::mutex mutex;
+    std::unordered_map<int64_t, TabletMetaSharedPtr> metas;
+    std::unordered_map<int64_t, int> meta_syncs;
+    std::unordered_map<int64_t, int> rowset_syncs;
+
+    auto meta_for = [&](int64_t tablet_id) {
+        std::lock_guard<std::mutex> lock(mutex);
+        auto it = metas.find(tablet_id);
+        if (it == metas.end()) {
+            it = metas.emplace(tablet_id, std::make_shared<TabletMeta>(
+                                                  1, 2, tablet_id, 15674, 4, 
5, TTabletSchema(), 6,
+                                                  std::unordered_map<uint32_t, 
uint32_t> {{7, 8}},
+                                                  UniqueId(9, 10), 
TTabletType::TABLET_TYPE_DISK,
+                                                  TCompressionType::LZ4F))
+                         .first;
+        }
+        return it->second;
+    };
+
+    sp->set_call_back("CloudMetaMgr::get_tablet_meta", [&](auto&& args) {
+        auto tablet_id = try_any_cast<int64_t>(args[0]);
+        auto* tablet_meta_ptr = try_any_cast<TabletMetaSharedPtr*>(args[1]);
+        *tablet_meta_ptr = meta_for(tablet_id);
+        {
+            std::lock_guard<std::mutex> lock(mutex);
+            ++meta_syncs[tablet_id];
+        }
+        try_any_cast_ret<Status>(args)->second = true;
+    });
+    sp->set_call_back("CloudMetaMgr::sync_tablet_rowsets", [&](auto&& args) {
+        auto* tablet = try_any_cast<CloudTablet*>(args[0]);
+        {
+            std::lock_guard<std::mutex> lock(mutex);
+            ++rowset_syncs[tablet->tablet_id()];
+        }
+        try_any_cast_ret<Status>(args)->second = true;
+    });
+
+    CloudTabletMgr mgr(_engine);
+    constexpr int64_t kBothStale = 70001;
+    constexpr int64_t kIngesting = 70002;
+    constexpr int64_t kFresh = 70003;
+
+    std::vector<std::shared_ptr<CloudTablet>> tablets;
+    for (int64_t tablet_id : {kBothStale, kIngesting, kFresh}) {
+        auto res = mgr.get_tablet(tablet_id);
+        ASSERT_TRUE(res.has_value()) << res.error();
+        tablets.push_back(res.value());
+    }
+
+    const int64_t now = ::time(nullptr);
+    const int64_t stale = now - config::tablet_sync_interval_s - 10;
+
+    tablets[0]->last_sync_rowsets_time_s = stale;
+    tablets[0]->last_sync_tablet_meta_time_s = stale;
+    // Rowsets pulled a moment ago, meta left behind.
+    tablets[1]->last_sync_rowsets_time_s = now;
+    tablets[1]->last_sync_tablet_meta_time_s = stale;
+    tablets[2]->last_sync_rowsets_time_s = now;
+    tablets[2]->last_sync_tablet_meta_time_s = now;
+
+    {
+        std::lock_guard<std::mutex> lock(mutex);
+        meta_syncs.clear();
+        rowset_syncs.clear();
+    }
+
+    CountDownLatch latch(1);
+    mgr.sync_tablets(latch);
+
+    std::lock_guard<std::mutex> lock(mutex);
+    EXPECT_EQ(1, meta_syncs[kBothStale]);
+    EXPECT_EQ(1, rowset_syncs[kBothStale]);
+
+    // The regression: meta has to be refreshed even though the rowset clock 
never goes stale,
+    // and it costs one RPC rather than the two a full sync would.
+    EXPECT_EQ(1, meta_syncs[kIngesting]);
+    EXPECT_EQ(0, rowset_syncs[kIngesting]);
+    EXPECT_GE(tablets[1]->last_sync_tablet_meta_time_s, now);
+
+    EXPECT_EQ(0, meta_syncs[kFresh]);
+    EXPECT_EQ(0, rowset_syncs[kFresh]);
+
+    sp->disable_processing();
+    sp->clear_all_call_backs();
+}
+
 } // namespace doris
diff --git a/be/test/storage/compaction/cloud_index_change_compaction_test.cpp 
b/be/test/storage/compaction/cloud_index_change_compaction_test.cpp
index 62e5f27d7a4..cf0d8871d2f 100644
--- a/be/test/storage/compaction/cloud_index_change_compaction_test.cpp
+++ b/be/test/storage/compaction/cloud_index_change_compaction_test.cpp
@@ -421,7 +421,7 @@ TEST_F(CloudIndexChangeCompactionTest, ms_ret_status_test) {
     {
         tablet->set_base_compaction_cnt(0);
         tablet->set_cumulative_layer_point(6);
-        tablet->last_sync_time_s = 1;
+        tablet->last_sync_rowsets_time_s = 1;
         auto index_change_compact = 
std::make_shared<CloudIndexChangeCompaction>(
                 *_engine, tablet, 0, index_list, columns);
         index_change_compact->_input_rowsets.push_back(rowset_ptr);
@@ -435,7 +435,7 @@ TEST_F(CloudIndexChangeCompactionTest, ms_ret_status_test) {
         index_change_compact->_update_tablet_for_base_compaction(response, 
nullptr);
 
         EXPECT_EQ(tablet->cumulative_layer_point(), 6);
-        EXPECT_EQ(tablet->last_sync_time_s, 0);
+        EXPECT_EQ(tablet->last_sync_rowsets_time_s, 0);
     }
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to