@@ -15,6 +15,7 @@ use stackable_operator::{
15
15
commons:: tls_verification:: { CaCert , TlsServerVerification , TlsVerification } ,
16
16
crd:: s3,
17
17
k8s_openapi:: api:: core:: v1:: { Volume , VolumeMount } ,
18
+ k8s_openapi:: apimachinery:: pkg:: api:: resource:: Quantity ,
18
19
schemars:: { self , JsonSchema } ,
19
20
time:: Duration ,
20
21
} ;
@@ -56,7 +57,7 @@ pub struct QueryRetryConfig {
56
57
57
58
/// Data size of the coordinator's in-memory buffer used to store output of query stages.
58
59
#[ serde( skip_serializing_if = "Option::is_none" ) ]
59
- pub exchange_deduplication_buffer_size : Option < String > ,
60
+ pub exchange_deduplication_buffer_size : Option < Quantity > ,
60
61
61
62
/// Exchange manager configuration for spooling intermediate data during fault tolerant execution.
62
63
/// Optional for Query retry policy, recommended for large result sets.
@@ -85,7 +86,7 @@ pub struct TaskRetryConfig {
85
86
86
87
/// Data size of the coordinator's in-memory buffer used to store output of query stages.
87
88
#[ serde( skip_serializing_if = "Option::is_none" ) ]
88
- pub exchange_deduplication_buffer_size : Option < String > ,
89
+ pub exchange_deduplication_buffer_size : Option < Quantity > ,
89
90
90
91
/// Exchange manager configuration for spooling intermediate data during fault tolerant execution.
91
92
/// Required for Task retry policy.
@@ -111,7 +112,7 @@ pub struct ExchangeManagerConfig {
111
112
112
113
/// Max data size of files written by exchange sinks.
113
114
#[ serde( skip_serializing_if = "Option::is_none" ) ]
114
- pub sink_max_file_size : Option < String > ,
115
+ pub sink_max_file_size : Option < Quantity > ,
115
116
116
117
/// Number of concurrent readers to read from spooling storage. The larger the number of
117
118
/// concurrent readers, the larger the read parallelism and memory usage.
@@ -140,7 +141,7 @@ pub enum ExchangeManagerBackend {
140
141
Local ( LocalExchangeConfig ) ,
141
142
}
142
143
143
- #[ derive( Clone , Debug , Deserialize , Eq , JsonSchema , PartialEq , Serialize ) ]
144
+ #[ derive( Clone , Debug , Deserialize , JsonSchema , PartialEq , Serialize ) ]
144
145
#[ serde( rename_all = "camelCase" ) ]
145
146
pub struct S3ExchangeConfig {
146
147
/// S3 bucket URIs for spooling data (e.g., s3://bucket1,s3://bucket2).
@@ -164,10 +165,10 @@ pub struct S3ExchangeConfig {
164
165
165
166
/// Part data size for S3 multi-part upload.
166
167
#[ serde( skip_serializing_if = "Option::is_none" ) ]
167
- pub upload_part_size : Option < String > ,
168
+ pub upload_part_size : Option < Quantity > ,
168
169
}
169
170
170
- #[ derive( Clone , Debug , Deserialize , Eq , JsonSchema , PartialEq , Serialize ) ]
171
+ #[ derive( Clone , Debug , Deserialize , JsonSchema , PartialEq , Serialize ) ]
171
172
#[ serde( rename_all = "camelCase" ) ]
172
173
pub struct HdfsExchangeConfig {
173
174
/// HDFS URIs for spooling data.
@@ -178,7 +179,7 @@ pub struct HdfsExchangeConfig {
178
179
179
180
/// Block data size for HDFS storage.
180
181
#[ serde( skip_serializing_if = "Option::is_none" ) ]
181
- pub block_size : Option < String > ,
182
+ pub block_size : Option < Quantity > ,
182
183
183
184
/// Skip directory scheme validation to support Hadoop-compatible file systems.
184
185
#[ serde( skip_serializing_if = "Option::is_none" ) ]
@@ -201,6 +202,12 @@ pub enum Error {
201
202
202
203
#[ snafu( display( "trino does not support disabling the TLS verification of S3 servers" ) ) ]
203
204
S3TlsNoVerificationNotSupported ,
205
+
206
+ #[ snafu( display( "failed to convert data size for [{field}] to bytes" ) ) ]
207
+ QuantityConversion {
208
+ source : stackable_operator:: memory:: Error ,
209
+ field : & ' static str ,
210
+ } ,
204
211
}
205
212
206
213
/// Fault tolerant execution configuration with external resources resolved
@@ -237,6 +244,21 @@ impl ResolvedFaultTolerantExecutionConfig {
237
244
}
238
245
}
239
246
247
+ /// Helper function to insert optional Quantity values after converting to Trino bytes string
248
+ fn insert_quantity_if_present (
249
+ properties : & mut BTreeMap < String , String > ,
250
+ key : & ' static str ,
251
+ quantity : Option < & Quantity > ,
252
+ ) -> Result < ( ) , Error > {
253
+ if let Some ( q) = quantity {
254
+ use snafu:: ResultExt ;
255
+ let v = crate :: crd:: quantity_to_trino_bytes ( q)
256
+ . context ( QuantityConversionSnafu { field : key } ) ?;
257
+ properties. insert ( key. to_string ( ) , v) ;
258
+ }
259
+ Ok ( ( ) )
260
+ }
261
+
240
262
/// Create a resolved fault tolerant execution configuration from the cluster config
241
263
pub async fn from_config (
242
264
config : & FaultTolerantExecutionConfig ,
@@ -275,11 +297,11 @@ impl ResolvedFaultTolerantExecutionConfig {
275
297
"retry-delay-scale-factor" ,
276
298
query_config. retry_delay_scale_factor . as_ref ( ) ,
277
299
) ;
278
- Self :: insert_if_present (
300
+ Self :: insert_quantity_if_present (
279
301
& mut config_properties,
280
302
"exchange.deduplication-buffer-size" ,
281
303
query_config. exchange_deduplication_buffer_size . as_ref ( ) ,
282
- ) ;
304
+ ) ? ;
283
305
284
306
( "QUERY" , query_config. exchange_manager . as_ref ( ) )
285
307
}
@@ -311,11 +333,11 @@ impl ResolvedFaultTolerantExecutionConfig {
311
333
"retry-delay-scale-factor" ,
312
334
task_config. retry_delay_scale_factor . as_ref ( ) ,
313
335
) ;
314
- Self :: insert_if_present (
336
+ Self :: insert_quantity_if_present (
315
337
& mut config_properties,
316
338
"exchange.deduplication-buffer-size" ,
317
339
task_config. exchange_deduplication_buffer_size . as_ref ( ) ,
318
- ) ;
340
+ ) ? ;
319
341
320
342
( "TASK" , Some ( & task_config. exchange_manager ) )
321
343
}
@@ -340,11 +362,11 @@ impl ResolvedFaultTolerantExecutionConfig {
340
362
"exchange.sink-buffers-per-partition" ,
341
363
exchange_config. sink_buffers_per_partition ,
342
364
) ;
343
- Self :: insert_if_present (
365
+ Self :: insert_quantity_if_present (
344
366
& mut exchange_manager_properties,
345
367
"exchange.sink-max-file-size" ,
346
368
exchange_config. sink_max_file_size . as_ref ( ) ,
347
- ) ;
369
+ ) ? ;
348
370
Self :: insert_if_present (
349
371
& mut exchange_manager_properties,
350
372
"exchange.source-concurrent-readers" ,
@@ -378,11 +400,11 @@ impl ResolvedFaultTolerantExecutionConfig {
378
400
"exchange.s3.max-error-retries" ,
379
401
s3_config. max_error_retries ,
380
402
) ;
381
- Self :: insert_if_present (
403
+ Self :: insert_quantity_if_present (
382
404
& mut exchange_manager_properties,
383
405
"exchange.s3.upload.part-size" ,
384
406
s3_config. upload_part_size . as_ref ( ) ,
385
- ) ;
407
+ ) ? ;
386
408
}
387
409
ExchangeManagerBackend :: Hdfs ( hdfs_config) => {
388
410
exchange_manager_properties
@@ -392,11 +414,11 @@ impl ResolvedFaultTolerantExecutionConfig {
392
414
hdfs_config. base_directories . join ( "," ) ,
393
415
) ;
394
416
395
- Self :: insert_if_present (
417
+ Self :: insert_quantity_if_present (
396
418
& mut exchange_manager_properties,
397
419
"exchange.hdfs.block-size" ,
398
420
hdfs_config. block_size . as_ref ( ) ,
399
- ) ;
421
+ ) ? ;
400
422
Self :: insert_if_present (
401
423
& mut exchange_manager_properties,
402
424
"exchange.hdfs.skip-directory-scheme-validation" ,
@@ -562,7 +584,7 @@ mod tests {
562
584
retry_initial_delay : Some ( Duration :: from_secs ( 15 ) ) ,
563
585
retry_max_delay : Some ( Duration :: from_secs ( 90 ) ) ,
564
586
retry_delay_scale_factor : Some ( 3.0 ) ,
565
- exchange_deduplication_buffer_size : Some ( "64MB ". to_string ( ) ) ,
587
+ exchange_deduplication_buffer_size : Some ( Quantity ( "64Mi ". to_string ( ) ) ) ,
566
588
exchange_manager : None ,
567
589
} ) ;
568
590
@@ -595,7 +617,7 @@ mod tests {
595
617
fte_config
596
618
. config_properties
597
619
. get( "exchange.deduplication-buffer-size" ) ,
598
- Some ( & "64MB " . to_string( ) )
620
+ Some ( & "67108864B " . to_string( ) )
599
621
) ;
600
622
}
601
623
@@ -606,12 +628,12 @@ mod tests {
606
628
retry_initial_delay : Some ( Duration :: from_secs ( 10 ) ) ,
607
629
retry_max_delay : Some ( Duration :: from_secs ( 60 ) ) ,
608
630
retry_delay_scale_factor : Some ( 2.0 ) ,
609
- exchange_deduplication_buffer_size : Some ( "100MB ". to_string ( ) ) ,
631
+ exchange_deduplication_buffer_size : Some ( Quantity ( "100Mi ". to_string ( ) ) ) ,
610
632
exchange_manager : Some ( ExchangeManagerConfig {
611
633
encryption_enabled : Some ( true ) ,
612
634
sink_buffer_pool_min_size : Some ( 10 ) ,
613
635
sink_buffers_per_partition : Some ( 2 ) ,
614
- sink_max_file_size : Some ( "1GB ". to_string ( ) ) ,
636
+ sink_max_file_size : Some ( Quantity ( "1Gi ". to_string ( ) ) ) ,
615
637
source_concurrent_readers : Some ( 4 ) ,
616
638
backend : ExchangeManagerBackend :: Local ( LocalExchangeConfig {
617
639
base_directories : vec ! [ "/tmp/exchange" . to_string( ) ] ,
@@ -662,7 +684,7 @@ mod tests {
662
684
fte_config
663
685
. config_properties
664
686
. get( "exchange.deduplication-buffer-size" ) ,
665
- Some ( & "100MB " . to_string( ) )
687
+ Some ( & "104857600B " . to_string( ) )
666
688
) ;
667
689
assert_eq ! (
668
690
fte_config
@@ -684,7 +706,7 @@ mod tests {
684
706
encryption_enabled : None ,
685
707
sink_buffer_pool_min_size : Some ( 20 ) ,
686
708
sink_buffers_per_partition : Some ( 4 ) ,
687
- sink_max_file_size : Some ( "2GB ". to_string ( ) ) ,
709
+ sink_max_file_size : Some ( Quantity ( "2Gi ". to_string ( ) ) ) ,
688
710
source_concurrent_readers : Some ( 8 ) ,
689
711
backend : ExchangeManagerBackend :: S3 ( S3ExchangeConfig {
690
712
base_directories : vec ! [ "s3://my-bucket/exchange" . to_string( ) ] ,
@@ -694,7 +716,7 @@ mod tests {
694
716
iam_role : Some ( "arn:aws:iam::123456789012:role/TrinoRole" . to_string ( ) ) ,
695
717
external_id : Some ( "external-id-123" . to_string ( ) ) ,
696
718
max_error_retries : Some ( 5 ) ,
697
- upload_part_size : Some ( "10MB ". to_string ( ) ) ,
719
+ upload_part_size : Some ( Quantity ( "10Mi ". to_string ( ) ) ) ,
698
720
} ) ,
699
721
config_overrides : std:: collections:: HashMap :: new ( ) ,
700
722
} ,
@@ -751,7 +773,7 @@ mod tests {
751
773
fte_config
752
774
. exchange_manager_properties
753
775
. get( "exchange.s3.upload.part-size" ) ,
754
- Some ( & "10MB " . to_string( ) )
776
+ Some ( & "10485760B " . to_string( ) )
755
777
) ;
756
778
assert_eq ! (
757
779
fte_config
@@ -769,7 +791,7 @@ mod tests {
769
791
fte_config
770
792
. exchange_manager_properties
771
793
. get( "exchange.sink-max-file-size" ) ,
772
- Some ( & "2GB " . to_string( ) )
794
+ Some ( & "2147483648B " . to_string( ) )
773
795
) ;
774
796
assert_eq ! (
775
797
fte_config
@@ -808,7 +830,7 @@ mod tests {
808
830
iam_role : None ,
809
831
external_id : None ,
810
832
max_error_retries : None ,
811
- upload_part_size : Some ( "original-value ". to_string ( ) ) ,
833
+ upload_part_size : Some ( Quantity ( "10Mi ". to_string ( ) ) ) ,
812
834
} ) ,
813
835
config_overrides,
814
836
} ,
0 commit comments