Skip to content

Commit db400d5

Browse files
authored
refactor: extract SchemaApiTestSuite to standalone crate (#19219)
* refactor: use FnOnce for TimedFuture callback The timing callback is only invoked once when the future completes, so `FnOnce` is more appropriate than `Fn`. Combined `start` and `callback` into a single `on_ready` field since they are always consumed together. Changes: - Change callback bound from `Fn` to `FnOnce` - Combine `start` and `callback` into `on_ready: Option<(Instant, F)>` - Simplify `poll()` to consume both fields atomically * refactor: extract SchemaApiTestSuite to standalone crate Move `schema_api_test_suite.rs` from `databend-common-meta-api` to a new standalone crate `databend-common-meta-schema-api-test-suite`. This follows the existing pattern of `databend-common-meta-kvapi-test-suite`. Also fix `TimedFuture` to initialize the start time on the first poll instead of when constructing, so that idle time before polling is excluded from total duration measurement. Changes: - Create `databend-common-meta-schema-api-test-suite` crate - Move `SchemaApiTestSuite` to the new crate - Copy helper functions `get_kv_data()` and `get_kv_u64_data()` locally - Update consumer test imports in `databend-meta` service tests - Fix `TimedFuture` to start timing on first poll, not construction
1 parent 0476efd commit db400d5

File tree

12 files changed

+114
-43
lines changed

12 files changed

+114
-43
lines changed

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ databend-common-meta-kvapi = { path = "src/meta/kvapi" }
6363
databend-common-meta-kvapi-test-suite = { path = "src/meta/kvapi-test-suite" }
6464
databend-common-meta-process = { path = "src/meta/process" }
6565
databend-common-meta-raft-store = { path = "src/meta/raft-store" }
66+
databend-common-meta-schema-api-test-suite = { path = "src/meta/schema-api-test-suite" }
6667
databend-common-meta-semaphore = { path = "src/meta/semaphore" }
6768
databend-common-meta-sled-store = { path = "src/meta/sled-store" }
6869
databend-common-meta-stoerr = { path = "src/meta/stoerr" }

src/common/base/src/future.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,41 +32,42 @@ pin_project! {
3232
#[must_use = "futures do nothing unless you `.await` or poll them"]
3333
pub struct TimedFuture<'a, Fu, F>
3434
where
35-
F: Fn(&Fu::Output, Duration, Duration),
35+
F: FnOnce(&Fu::Output, Duration, Duration),
3636
F: 'a,
3737
Fu: Future,
3838
{
3939
#[pin]
4040
inner: Fu,
4141

42-
start: Option<Instant>,
4342
busy: Duration,
44-
callback: F,
45-
_p : PhantomData<&'a ()>,
46-
43+
// Start time, initialized on first poll.
44+
start: Option<Instant>,
45+
// Callback, consumed when the future completes.
46+
on_ready: Option<F>,
47+
_p: PhantomData<&'a ()>,
4748
}
4849
}
4950

5051
impl<'a, Fu, F> TimedFuture<'a, Fu, F>
5152
where
52-
F: Fn(&Fu::Output, Duration, Duration),
53+
F: FnOnce(&Fu::Output, Duration, Duration),
5354
F: 'a,
5455
Fu: Future,
5556
{
5657
pub fn new(inner: Fu, callback: F) -> Self {
5758
Self {
5859
inner,
59-
start: None,
6060
busy: Duration::default(),
61-
callback,
62-
_p: Default::default(),
61+
start: None,
62+
on_ready: Some(callback),
63+
_p: PhantomData,
6364
}
6465
}
6566
}
6667

6768
impl<'a, Fu, F> Future for TimedFuture<'a, Fu, F>
6869
where
69-
F: Fn(&Fu::Output, Duration, Duration),
70+
F: FnOnce(&Fu::Output, Duration, Duration),
7071
F: 'a,
7172
Fu: Future,
7273
{
@@ -75,20 +76,21 @@ where
7576
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
7677
let this = self.project();
7778

78-
if this.start.is_none() {
79+
// Initialize start time on first poll, only if callback is present.
80+
if this.start.is_none() && this.on_ready.is_some() {
7981
*this.start = Some(Instant::now());
8082
}
8183

8284
let t0 = Instant::now();
83-
8485
let res = this.inner.poll(cx);
85-
8686
*this.busy += t0.elapsed();
8787

8888
match &res {
8989
Poll::Ready(output) => {
90-
let total = this.start.unwrap().elapsed();
91-
(this.callback)(output, total, *this.busy);
90+
if let Some(callback) = this.on_ready.take() {
91+
let total = this.start.map(|s| s.elapsed()).unwrap_or_default();
92+
(callback)(output, total, *this.busy);
93+
}
9294
}
9395
Poll::Pending => {}
9496
}
@@ -104,7 +106,7 @@ where Self: Future
104106
/// Wrap the future with a timing future.
105107
fn with_timing<'a, F>(self, f: F) -> TimedFuture<'a, Self, F>
106108
where
107-
F: Fn(&Self::Output, Duration, Duration) + 'a,
109+
F: FnOnce(&Self::Output, Duration, Duration) + 'a,
108110
Self: Future + Sized;
109111

110112
/// Wrap the future with a timing future,
@@ -113,9 +115,9 @@ where Self: Future
113115
self,
114116
threshold: Duration,
115117
f: F,
116-
) -> TimedFuture<'a, Self, impl Fn(&Self::Output, Duration, Duration)>
118+
) -> TimedFuture<'a, Self, impl FnOnce(&Self::Output, Duration, Duration)>
117119
where
118-
F: Fn(&Self::Output, Duration, Duration) + 'a,
120+
F: FnOnce(&Self::Output, Duration, Duration) + 'a,
119121
Self: Future + Sized,
120122
{
121123
self.with_timing::<'a>(move |output, total, busy| {
@@ -130,7 +132,7 @@ where Self: Future
130132
fn log_elapsed_debug<'a>(
131133
self,
132134
ctx: impl fmt::Display + 'a,
133-
) -> TimedFuture<'a, Self, impl Fn(&Self::Output, Duration, Duration)>
135+
) -> TimedFuture<'a, Self, impl FnOnce(&Self::Output, Duration, Duration)>
134136
where
135137
Self: Future + Sized,
136138
{
@@ -158,7 +160,7 @@ where Self: Future
158160
fn log_elapsed_info<'a>(
159161
self,
160162
ctx: impl fmt::Display + 'a,
161-
) -> TimedFuture<'a, Self, impl Fn(&Self::Output, Duration, Duration)>
163+
) -> TimedFuture<'a, Self, impl FnOnce(&Self::Output, Duration, Duration)>
162164
where
163165
Self: Future + Sized,
164166
{
@@ -187,7 +189,7 @@ where T: Future + Sized
187189
{
188190
fn with_timing<'a, F>(self, f: F) -> TimedFuture<'a, Self, F>
189191
where
190-
F: Fn(&Self::Output, Duration, Duration),
192+
F: FnOnce(&Self::Output, Duration, Duration),
191193
F: 'a,
192194
{
193195
TimedFuture::new(self, f)

src/meta/api/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,11 @@ pub mod name_id_value_api;
4040
pub mod name_value_api;
4141
pub mod reply;
4242
mod schema_api;
43-
mod schema_api_test_suite;
4443
pub mod security_api;
4544
mod sequence_api;
4645
pub mod serialization_util;
4746
pub mod table_api;
4847
pub mod tag_api;
49-
pub(crate) mod testing;
5048
pub mod txn_backoff;
5149
pub mod txn_condition_util;
5250
pub mod txn_core_util;
@@ -96,7 +94,6 @@ pub use kv_fetch_util::mget_pb_values;
9694
pub use lock_api::LockApi;
9795
pub use row_access_policy_api::RowAccessPolicyApi;
9896
pub use schema_api::SchemaApi;
99-
pub use schema_api_test_suite::SchemaApiTestSuite;
10097
pub use security_api::SecurityApi;
10198
pub use sequence_api::SequenceApi;
10299
// Re-export from new serialization_util module for backward compatibility
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "databend-common-meta-schema-api-test-suite"
3+
version = { workspace = true }
4+
authors = { workspace = true }
5+
license = { workspace = true }
6+
publish = { workspace = true }
7+
edition = { workspace = true }
8+
9+
[dependencies]
10+
anyhow = { workspace = true }
11+
chrono = { workspace = true }
12+
databend-common-base = { workspace = true }
13+
databend-common-exception = { workspace = true }
14+
databend-common-expression = { workspace = true }
15+
databend-common-meta-api = { workspace = true }
16+
databend-common-meta-app = { workspace = true }
17+
databend-common-meta-kvapi = { workspace = true }
18+
databend-common-meta-types = { workspace = true }
19+
databend-common-proto-conv = { workspace = true }
20+
fastrace = { workspace = true }
21+
log = { workspace = true }
22+
maplit = { workspace = true }
23+
24+
[lints]
25+
workspace = true
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2021 Datafuse Labs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#![allow(clippy::uninlined_format_args)]
16+
#![allow(clippy::diverging_sub_expression)]
17+
#![allow(clippy::type_complexity)]
18+
#![allow(clippy::collapsible_if)]
19+
#![allow(clippy::unnecessary_unwrap)]
20+
#![feature(try_blocks)]
21+
22+
mod schema_api_test_suite;
23+
mod testing;
24+
25+
pub use schema_api_test_suite::SchemaApiTestSuite;

src/meta/api/src/schema_api_test_suite.rs renamed to src/meta/schema-api-test-suite/src/schema_api_test_suite.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ use databend_common_expression::TableDataType;
3030
use databend_common_expression::TableField;
3131
use databend_common_expression::TableSchema;
3232
use databend_common_expression::types::NumberDataType;
33+
use databend_common_meta_api::DEFAULT_MGET_SIZE;
34+
use databend_common_meta_api::DatamaskApi;
35+
use databend_common_meta_api::RowAccessPolicyApi;
36+
use databend_common_meta_api::SchemaApi;
37+
use databend_common_meta_api::SequenceApi;
38+
use databend_common_meta_api::TableApi;
39+
use databend_common_meta_api::deserialize_struct;
40+
use databend_common_meta_api::kv_app_error::KVAppError;
41+
use databend_common_meta_api::kv_pb_api::KVPbApi;
42+
use databend_common_meta_api::kv_pb_api::UpsertPB;
43+
use databend_common_meta_api::serialize_struct;
44+
use databend_common_meta_api::util::IdempotentKVTxnSender;
3345
use databend_common_meta_app::KeyWithTenant;
3446
use databend_common_meta_app::app_error::AppError;
3547
use databend_common_meta_app::data_mask::CreateDatamaskReq;
@@ -145,20 +157,8 @@ use fastrace::func_name;
145157
use log::debug;
146158
use log::info;
147159

148-
use crate::DEFAULT_MGET_SIZE;
149-
use crate::DatamaskApi;
150-
use crate::RowAccessPolicyApi;
151-
use crate::SchemaApi;
152-
use crate::SequenceApi;
153-
use crate::TableApi;
154-
use crate::deserialize_struct;
155-
use crate::kv_app_error::KVAppError;
156-
use crate::kv_pb_api::KVPbApi;
157-
use crate::kv_pb_api::UpsertPB;
158-
use crate::serialize_struct;
159160
use crate::testing::get_kv_data;
160161
use crate::testing::get_kv_u64_data;
161-
use crate::util::IdempotentKVTxnSender;
162162

163163
/// Test suite of `SchemaApi`.
164164
///

src/meta/api/src/testing.rs renamed to src/meta/schema-api-test-suite/src/testing.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
//! Supporting utilities for tests.
1616
17+
use databend_common_meta_api::deserialize_struct;
18+
use databend_common_meta_api::kv_app_error::KVAppError;
19+
use databend_common_meta_api::serialization_util::deserialize_u64;
1720
use databend_common_meta_kvapi::kvapi;
1821
use databend_common_meta_kvapi::kvapi::KvApiExt;
1922
use databend_common_meta_types::MetaAPIError;
@@ -23,9 +26,6 @@ use databend_common_meta_types::MetaError;
2326
use databend_common_meta_types::anyerror::AnyError;
2427
use databend_common_proto_conv::FromToProto;
2528

26-
use crate::kv_app_error::KVAppError;
27-
use crate::serialization_util::deserialize_u64;
28-
2929
/// Get existing value by key. Panic if key is absent.
3030
pub(crate) async fn get_kv_data<T>(
3131
kv_api: &(impl kvapi::KVApi<Error = MetaError> + ?Sized),
@@ -36,7 +36,7 @@ where
3636
{
3737
let res = kv_api.get_kv(&key.to_string_key()).await?;
3838
if let Some(res) = res {
39-
let s = crate::deserialize_struct(&res.data)?;
39+
let s = deserialize_struct(&res.data)?;
4040
return Ok(s);
4141
};
4242

src/meta/service/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ watcher = { workspace = true }
7373
[dev-dependencies]
7474
databend-common-meta-cache = { workspace = true }
7575
databend-common-meta-kvapi-test-suite = { workspace = true }
76+
databend-common-meta-schema-api-test-suite = { workspace = true }
7677
databend-common-meta-semaphore = { workspace = true }
7778
databend-common-version = { workspace = true }
7879
env_logger = { workspace = true }

src/meta/service/tests/it/grpc/metasrv_grpc_schema_api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::sync::Arc;
1818
use std::sync::Mutex;
1919

2020
use databend_common_meta_api::AutoIncrementApiTestSuite;
21-
use databend_common_meta_api::SchemaApiTestSuite;
21+
use databend_common_meta_schema_api_test_suite::SchemaApiTestSuite;
2222
use test_harness::test;
2323

2424
use crate::testing::meta_service_test_harness;

0 commit comments

Comments
 (0)