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

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-3406-78f1762aca16cc4745bc913d6e782416b5705299
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git

commit da5cc19a9f7c9e8ea14dc40d4a82974cd26def42
Author: NoahKusaba <[email protected]>
AuthorDate: Tue Oct 20 03:46:45 2026 +0000

    feat(table): add Table::with_runtime that keeps the manifest cache (#3406)
    
    * feat(table): add Table::with_runtime that keeps the manifest cache
    
    A table gets its runtime only when it is built, and rebuilding it through
    Table::builder() starts with an empty ObjectCache. An engine that caches a
    Table and wants its scans to run on the runtime executing the query has no
    way to switch runtimes without losing the cached manifests and manifest
    lists.
    
    * docs(table): tighten Table::with_runtime docs
    
    Co-authored-by: Copilot App <[email protected]>
    
    ---------
    
    Co-authored-by: Kevin Liu <[email protected]>
    Co-authored-by: Copilot App <[email protected]>
---
 crates/iceberg/public-api.txt |  1 +
 crates/iceberg/src/table.rs   | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/crates/iceberg/public-api.txt b/crates/iceberg/public-api.txt
index b86e48c77..9d65474ad 100644
--- a/crates/iceberg/public-api.txt
+++ b/crates/iceberg/public-api.txt
@@ -3404,6 +3404,7 @@ pub fn iceberg::table::Table::metadata_ref(&self) -> 
iceberg::spec::TableMetadat
 pub fn iceberg::table::Table::reader_builder(&self) -> 
iceberg::arrow::ArrowReaderBuilder
 pub fn iceberg::table::Table::readonly(&self) -> bool
 pub fn iceberg::table::Table::scan(&self) -> 
iceberg::scan::TableScanBuilder<'_>
+pub fn iceberg::table::Table::with_runtime(self, runtime: iceberg::Runtime) -> 
Self
 impl core::clone::Clone for iceberg::table::Table
 pub fn iceberg::table::Table::clone(&self) -> iceberg::table::Table
 impl core::fmt::Debug for iceberg::table::Table
diff --git a/crates/iceberg/src/table.rs b/crates/iceberg/src/table.rs
index 78c2dff05..f33c246eb 100644
--- a/crates/iceberg/src/table.rs
+++ b/crates/iceberg/src/table.rs
@@ -219,6 +219,15 @@ impl Table {
         self
     }
 
+    /// Returns this table bound to `runtime`, sharing its manifest cache.
+    ///
+    /// Tasks such as scan planning and reads are spawned on `runtime`. A 
table rebuilt
+    /// through [`Table::builder`] starts with an empty cache.
+    pub fn with_runtime(mut self, runtime: Runtime) -> Self {
+        self.runtime = runtime;
+        self
+    }
+
     /// Returns a TableBuilder to build a table
     pub fn builder() -> TableBuilder {
         TableBuilder::new()
@@ -497,6 +506,31 @@ mod tests {
         assert_eq!(table.identifier.name(), "table");
     }
 
+    #[tokio::test]
+    async fn test_table_with_runtime_moves_work_and_keeps_object_cache() {
+        let old = tokio::runtime::Builder::new_current_thread()
+            .build()
+            .unwrap();
+        let table = Table::builder()
+            .metadata(load_test_metadata("TableMetadataV2Valid.json"))
+            .identifier(TableIdent::from_strs(["ns", "table"]).unwrap())
+            .file_io(FileIO::new_with_memory())
+            .runtime(Runtime::new(&old))
+            .build()
+            .unwrap();
+        // With the old runtime shut down, the spawn below succeeds only if
+        // `rebound` uses the new one.
+        old.shutdown_background();
+
+        let rebound = 
table.clone().with_runtime(Runtime::try_current().unwrap());
+
+        assert!(Arc::ptr_eq(&table.object_cache(), &rebound.object_cache()));
+        assert_eq!(
+            rebound.runtime().io().spawn(async { 42 }).await.unwrap(),
+            42
+        );
+    }
+
     fn make_kms() -> Arc<dyn KeyManagementClient> {
         let kms = MemoryKeyManagementClient::new();
         kms.add_master_key("master-1").unwrap();

Reply via email to