@@ -127,6 +127,112 @@ pub trait KVPbApi: KVApi {
127
127
}
128
128
}
129
129
130
+ /// Same as `get_pb_stream` but does not return keys, only values.
131
+ #[ deprecated( note = "stream may be closed. The caller must check it" ) ]
132
+ fn get_pb_values < K , I > (
133
+ & self ,
134
+ keys : I ,
135
+ ) -> impl Future <
136
+ Output = Result <
137
+ BoxStream <
138
+ ' static , //
139
+ Result < Option < SeqV < K :: ValueType > > , Self :: Error > ,
140
+ > ,
141
+ Self :: Error ,
142
+ > ,
143
+ > + Send
144
+ where
145
+ K : kvapi:: Key + ' static ,
146
+ K :: ValueType : FromToProto + Send + ' static ,
147
+ I : IntoIterator < Item = K > ,
148
+ Self :: Error : From < PbApiReadError < Self :: Error > > ,
149
+ {
150
+ self . get_pb_stream_low ( keys)
151
+ // This `map()` handles Future result
152
+ . map ( |r| match r {
153
+ Ok ( strm) => {
154
+ // These two `map_xx()` handles Stream result
155
+ Ok ( strm. map_ok ( |( _k, v) | v) . map_err ( Self :: Error :: from) . boxed ( ) )
156
+ }
157
+ Err ( e) => Err ( e) ,
158
+ } )
159
+ }
160
+
161
+ /// Get protobuf encoded values by a series of kvapi::Key.
162
+ ///
163
+ /// The key will be converted to string and the returned value is decoded by `FromToProto`.
164
+ /// It returns the same error as `KVApi::Error`,
165
+ /// thus it requires KVApi::Error can describe a decoding error, i.e., `impl From<PbApiReadError>`.
166
+ #[ deprecated( note = "stream may be closed. The caller must check it" ) ]
167
+ fn get_pb_stream < K , I > (
168
+ & self ,
169
+ keys : I ,
170
+ ) -> impl Future <
171
+ Output = Result <
172
+ BoxStream <
173
+ ' static , //
174
+ Result < ( K , Option < SeqV < K :: ValueType > > ) , Self :: Error > ,
175
+ > ,
176
+ Self :: Error ,
177
+ > ,
178
+ > + Send
179
+ where
180
+ K : kvapi:: Key + ' static ,
181
+ K :: ValueType : FromToProto + Send + ' static ,
182
+ I : IntoIterator < Item = K > ,
183
+ Self :: Error : From < PbApiReadError < Self :: Error > > ,
184
+ {
185
+ self . get_pb_stream_low ( keys) . map ( |r| match r {
186
+ Ok ( strm) => Ok ( strm. map_err ( Self :: Error :: from) . boxed ( ) ) ,
187
+ Err ( e) => Err ( e) ,
188
+ } )
189
+ }
190
+
191
+ /// Same as `get_pb_stream` but returns [`PbApiReadError`]. No require of `From<PbApiReadError>` for `Self::Error`.
192
+ fn get_pb_stream_low < K , I > (
193
+ & self ,
194
+ keys : I ,
195
+ ) -> impl Future <
196
+ Output = Result <
197
+ BoxStream <
198
+ ' static , //
199
+ Result < ( K , Option < SeqV < K :: ValueType > > ) , PbApiReadError < Self :: Error > > ,
200
+ > ,
201
+ Self :: Error ,
202
+ > ,
203
+ > + Send
204
+ where
205
+ K : kvapi:: Key + ' static ,
206
+ K :: ValueType : FromToProto + Send + ' static ,
207
+ I : IntoIterator < Item = K > ,
208
+ {
209
+ let keys = keys
210
+ . into_iter ( )
211
+ . map ( |k| kvapi:: Key :: to_string_key ( & k) )
212
+ . collect :: < Vec < _ > > ( ) ;
213
+
214
+ async move {
215
+ let strm = self . get_kv_stream ( & keys) . await ?;
216
+
217
+ let strm = strm. map ( |r : Result < StreamItem , Self :: Error > | {
218
+ let item = r. map_err ( PbApiReadError :: KvApiError ) ?;
219
+
220
+ let k = K :: from_str_key ( & item. key ) . map_err ( PbApiReadError :: KeyError ) ?;
221
+
222
+ let v = if let Some ( pb_seqv) = item. value {
223
+ let seqv = decode_seqv :: < K :: ValueType > ( SeqV :: from ( pb_seqv) ) ?;
224
+ Some ( seqv)
225
+ } else {
226
+ None
227
+ } ;
228
+
229
+ Ok ( ( k, v) )
230
+ } ) ;
231
+
232
+ Ok ( strm. boxed ( ) )
233
+ }
234
+ }
235
+
130
236
/// Same as `list_pb` but does not return values, only keys.
131
237
fn list_pb_keys < K > (
132
238
& self ,
@@ -216,3 +322,164 @@ pub trait KVPbApi: KVApi {
216
322
}
217
323
218
324
impl < T > KVPbApi for T where T : KVApi + ?Sized { }
325
+
326
+ #[ cfg( test) ]
327
+ mod tests {
328
+ use std:: collections:: BTreeMap ;
329
+
330
+ use async_trait:: async_trait;
331
+ use chrono:: DateTime ;
332
+ use chrono:: Utc ;
333
+ use databend_common_meta_app:: schema:: CatalogIdIdent ;
334
+ use databend_common_meta_app:: schema:: CatalogMeta ;
335
+ use databend_common_meta_app:: schema:: CatalogOption ;
336
+ use databend_common_meta_app:: schema:: HiveCatalogOption ;
337
+ use databend_common_meta_app:: storage:: StorageS3Config ;
338
+ use databend_common_meta_app:: tenant:: Tenant ;
339
+ use databend_common_meta_kvapi:: kvapi:: KVApi ;
340
+ use databend_common_meta_kvapi:: kvapi:: KVStream ;
341
+ use databend_common_meta_kvapi:: kvapi:: UpsertKVReply ;
342
+ use databend_common_meta_kvapi:: kvapi:: UpsertKVReq ;
343
+ use databend_common_meta_types:: protobuf:: StreamItem ;
344
+ use databend_common_meta_types:: MetaError ;
345
+ use databend_common_meta_types:: SeqV ;
346
+ use databend_common_meta_types:: SeqValue ;
347
+ use databend_common_meta_types:: TxnReply ;
348
+ use databend_common_meta_types:: TxnRequest ;
349
+ use databend_common_proto_conv:: FromToProto ;
350
+ use futures:: StreamExt ;
351
+ use futures:: TryStreamExt ;
352
+ use prost:: Message ;
353
+
354
+ use crate :: kv_pb_api:: KVPbApi ;
355
+
356
+ //
357
+ struct Foo {
358
+ kvs : BTreeMap < String , SeqV > ,
359
+ }
360
+
361
+ #[ async_trait]
362
+ impl KVApi for Foo {
363
+ type Error = MetaError ;
364
+
365
+ async fn upsert_kv ( & self , _req : UpsertKVReq ) -> Result < UpsertKVReply , Self :: Error > {
366
+ todo ! ( )
367
+ }
368
+
369
+ async fn get_kv_stream (
370
+ & self ,
371
+ keys : & [ String ] ,
372
+ ) -> Result < KVStream < Self :: Error > , Self :: Error > {
373
+ let mut res = Vec :: with_capacity ( keys. len ( ) ) ;
374
+ for key in keys {
375
+ let k = key. clone ( ) ;
376
+ let v = self . kvs . get ( key) . cloned ( ) ;
377
+
378
+ let item = StreamItem :: new ( k, v. map ( |v| v. into ( ) ) ) ;
379
+ res. push ( Ok ( item) ) ;
380
+ }
381
+
382
+ let strm = futures:: stream:: iter ( res) ;
383
+ Ok ( strm. boxed ( ) )
384
+ }
385
+
386
+ async fn list_kv ( & self , _prefix : & str ) -> Result < KVStream < Self :: Error > , Self :: Error > {
387
+ todo ! ( )
388
+ }
389
+
390
+ async fn transaction ( & self , _txn : TxnRequest ) -> Result < TxnReply , Self :: Error > {
391
+ todo ! ( )
392
+ }
393
+ }
394
+
395
+ // TODO: test upsert_kv
396
+ // TODO: test upsert_kv
397
+ // TODO: test list_kv
398
+
399
+ #[ tokio:: test]
400
+ async fn test_mget ( ) -> anyhow:: Result < ( ) > {
401
+ let catalog_meta = CatalogMeta {
402
+ catalog_option : CatalogOption :: Hive ( HiveCatalogOption {
403
+ address : "127.0.0.1:10000" . to_string ( ) ,
404
+ storage_params : Some ( Box :: new (
405
+ databend_common_meta_app:: storage:: StorageParams :: S3 ( StorageS3Config {
406
+ endpoint_url : "http://127.0.0.1:9900" . to_string ( ) ,
407
+ region : "hello" . to_string ( ) ,
408
+ bucket : "world" . to_string ( ) ,
409
+ access_key_id : "databend_has_super_power" . to_string ( ) ,
410
+ secret_access_key : "databend_has_super_power" . to_string ( ) ,
411
+ ..Default :: default ( )
412
+ } ) ,
413
+ ) ) ,
414
+ } ) ,
415
+ created_on : DateTime :: < Utc > :: MIN_UTC ,
416
+ } ;
417
+ let v = catalog_meta. to_pb ( ) ?. encode_to_vec ( ) ;
418
+
419
+ let foo = Foo {
420
+ kvs : vec ! [
421
+ ( s( "__fd_catalog_by_id/1" ) , SeqV :: new( 1 , v. clone( ) ) ) ,
422
+ ( s( "__fd_catalog_by_id/2" ) , SeqV :: new( 2 , v. clone( ) ) ) ,
423
+ ( s( "__fd_catalog_by_id/3" ) , SeqV :: new( 3 , v. clone( ) ) ) ,
424
+ ]
425
+ . into_iter ( )
426
+ . collect ( ) ,
427
+ } ;
428
+
429
+ let tenant = Tenant :: new_literal ( "dummy" ) ;
430
+
431
+ // Get key value pairs
432
+ {
433
+ #[ allow( deprecated) ]
434
+ let strm = foo
435
+ . get_pb_stream ( [
436
+ CatalogIdIdent :: new ( & tenant, 1 ) ,
437
+ CatalogIdIdent :: new ( & tenant, 2 ) ,
438
+ CatalogIdIdent :: new ( & tenant, 4 ) ,
439
+ ] )
440
+ . await ?;
441
+
442
+ let got = strm. try_collect :: < Vec < _ > > ( ) . await ?;
443
+
444
+ assert_eq ! ( CatalogIdIdent :: new( & tenant, 1 ) , got[ 0 ] . 0 ) ;
445
+ assert_eq ! ( CatalogIdIdent :: new( & tenant, 2 ) , got[ 1 ] . 0 ) ;
446
+ assert_eq ! ( CatalogIdIdent :: new( & tenant, 4 ) , got[ 2 ] . 0 ) ;
447
+
448
+ assert_eq ! ( 1 , got[ 0 ] . 1 . seq( ) ) ;
449
+ assert_eq ! ( 2 , got[ 1 ] . 1 . seq( ) ) ;
450
+ assert_eq ! ( 0 , got[ 2 ] . 1 . seq( ) ) ;
451
+
452
+ assert_eq ! ( Some ( & catalog_meta) , got[ 0 ] . 1 . value( ) ) ;
453
+ assert_eq ! ( Some ( & catalog_meta) , got[ 1 ] . 1 . value( ) ) ;
454
+ assert_eq ! ( None , got[ 2 ] . 1 . value( ) ) ;
455
+ }
456
+
457
+ // Get values
458
+ {
459
+ #[ allow( deprecated) ]
460
+ let strm = foo
461
+ . get_pb_values ( [
462
+ CatalogIdIdent :: new ( & tenant, 1 ) ,
463
+ CatalogIdIdent :: new ( & tenant, 2 ) ,
464
+ CatalogIdIdent :: new ( & tenant, 4 ) ,
465
+ ] )
466
+ . await ?;
467
+
468
+ let got = strm. try_collect :: < Vec < _ > > ( ) . await ?;
469
+
470
+ assert_eq ! ( 1 , got[ 0 ] . seq( ) ) ;
471
+ assert_eq ! ( 2 , got[ 1 ] . seq( ) ) ;
472
+ assert_eq ! ( 0 , got[ 2 ] . seq( ) ) ;
473
+
474
+ assert_eq ! ( Some ( & catalog_meta) , got[ 0 ] . value( ) ) ;
475
+ assert_eq ! ( Some ( & catalog_meta) , got[ 1 ] . value( ) ) ;
476
+ assert_eq ! ( None , got[ 2 ] . value( ) ) ;
477
+ }
478
+
479
+ Ok ( ( ) )
480
+ }
481
+
482
+ fn s ( x : impl ToString ) -> String {
483
+ x. to_string ( )
484
+ }
485
+ }
0 commit comments