@@ -25,7 +25,9 @@ use anyhow::{bail, ensure};
25
25
use bytesize:: ByteSize ;
26
26
use http:: HeaderMap ;
27
27
use quickwit_common:: net:: HostAddr ;
28
- use quickwit_common:: shared_consts:: DEFAULT_SHARD_THROUGHPUT_LIMIT ;
28
+ use quickwit_common:: shared_consts:: {
29
+ DEFAULT_SHARD_BURST_LIMIT , DEFAULT_SHARD_SCALE_UP_FACTOR , DEFAULT_SHARD_THROUGHPUT_LIMIT ,
30
+ } ;
29
31
use quickwit_common:: uri:: Uri ;
30
32
use quickwit_proto:: indexing:: CpuCapacity ;
31
33
use quickwit_proto:: types:: NodeId ;
@@ -39,7 +41,7 @@ use crate::{ConfigFormat, MetastoreConfigs};
39
41
40
42
pub const DEFAULT_QW_CONFIG_PATH : & str = "config/quickwit.yaml" ;
41
43
42
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
44
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
43
45
#[ serde( deny_unknown_fields) ]
44
46
pub struct RestConfig {
45
47
pub listen_addr : SocketAddr ,
@@ -50,7 +52,7 @@ pub struct RestConfig {
50
52
pub tls : Option < TlsConfig > ,
51
53
}
52
54
53
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
55
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
54
56
#[ serde( deny_unknown_fields) ]
55
57
pub struct GrpcConfig {
56
58
#[ serde( default = "GrpcConfig::default_max_message_size" ) ]
@@ -83,7 +85,7 @@ impl Default for GrpcConfig {
83
85
}
84
86
}
85
87
86
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
88
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
87
89
#[ serde( deny_unknown_fields) ]
88
90
pub struct TlsConfig {
89
91
pub cert_path : String ,
@@ -193,7 +195,7 @@ impl Default for IndexerConfig {
193
195
}
194
196
}
195
197
196
- #[ derive( Debug , Clone , Copy , Eq , PartialEq , Serialize , Deserialize ) ]
198
+ #[ derive( Debug , Clone , Copy , PartialEq , Serialize , Deserialize ) ]
197
199
#[ serde( deny_unknown_fields) ]
198
200
pub struct SplitCacheLimits {
199
201
pub max_num_bytes : ByteSize ,
@@ -219,7 +221,7 @@ impl SplitCacheLimits {
219
221
}
220
222
}
221
223
222
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
224
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
223
225
#[ serde( deny_unknown_fields, default ) ]
224
226
pub struct SearcherConfig {
225
227
pub aggregation_memory_limit : ByteSize ,
@@ -254,7 +256,7 @@ pub struct SearcherConfig {
254
256
/// This policy is inspired by this guidance. It does not track instanteneous throughput, but
255
257
/// computes an overall timeout using the following formula:
256
258
/// `timeout_offset + num_bytes_get_request / min_throughtput`
257
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
259
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
258
260
pub struct StorageTimeoutPolicy {
259
261
pub min_throughtput_bytes_per_secs : u64 ,
260
262
pub timeout_millis : u64 ,
@@ -338,14 +340,25 @@ impl SearcherConfig {
338
340
}
339
341
}
340
342
341
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
343
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
342
344
#[ serde( deny_unknown_fields, default ) ]
343
345
pub struct IngestApiConfig {
346
+ /// Maximum memory space taken by the ingest WAL
344
347
pub max_queue_memory_usage : ByteSize ,
348
+ /// Maximum disk space taken by the ingest WAL
345
349
pub max_queue_disk_usage : ByteSize ,
346
350
replication_factor : usize ,
347
351
pub content_length_limit : ByteSize ,
352
+ /// (hidden) Targeted throughput for each shard
348
353
pub shard_throughput_limit : ByteSize ,
354
+ /// (hidden) Maximum accumulated throughput capacity for underutilized
355
+ /// shards, allowing the throughput limit to be temporarily exceeded
356
+ pub shard_burst_limit : ByteSize ,
357
+ /// (hidden) new_shard_count = ceil(old_shard_count * shard_scale_up_factor)
358
+ ///
359
+ /// Setting this too high will be cancelled out by the arbiter that prevents
360
+ /// creating too many shards at once.
361
+ pub shard_scale_up_factor : f32 ,
349
362
}
350
363
351
364
impl Default for IngestApiConfig {
@@ -356,6 +369,8 @@ impl Default for IngestApiConfig {
356
369
replication_factor : 1 ,
357
370
content_length_limit : ByteSize :: mib ( 10 ) ,
358
371
shard_throughput_limit : DEFAULT_SHARD_THROUGHPUT_LIMIT ,
372
+ shard_burst_limit : DEFAULT_SHARD_BURST_LIMIT ,
373
+ shard_scale_up_factor : DEFAULT_SHARD_SCALE_UP_FACTOR ,
359
374
}
360
375
}
361
376
}
@@ -398,20 +413,34 @@ impl IngestApiConfig {
398
413
self . max_queue_memory_usage
399
414
) ;
400
415
info ! (
401
- "ingestion shard throughput limit: {:? }" ,
416
+ "ingestion shard throughput limit: {}" ,
402
417
self . shard_throughput_limit
403
418
) ;
404
419
ensure ! (
405
420
self . shard_throughput_limit >= ByteSize :: mib( 1 )
406
421
&& self . shard_throughput_limit <= ByteSize :: mib( 20 ) ,
407
- "shard_throughput_limit ({:? }) must be within 1mb and 20mb" ,
422
+ "shard_throughput_limit ({}) must be within 1mb and 20mb" ,
408
423
self . shard_throughput_limit
409
424
) ;
425
+ // The newline delimited format is persisted as something a bit larger
426
+ // (lines prefixed with their length)
427
+ let estimated_persist_size = ByteSize :: b ( 3 * self . content_length_limit . as_u64 ( ) / 2 ) ;
428
+ ensure ! (
429
+ self . shard_burst_limit >= estimated_persist_size,
430
+ "shard_burst_limit ({}) must be at least 1.5*content_length_limit ({})" ,
431
+ self . shard_burst_limit,
432
+ estimated_persist_size,
433
+ ) ;
434
+ ensure ! (
435
+ self . shard_scale_up_factor > 1.0 ,
436
+ "shard_scale_up_factor ({}) must be greater than 1" ,
437
+ self . shard_scale_up_factor,
438
+ ) ;
410
439
Ok ( ( ) )
411
440
}
412
441
}
413
442
414
- #[ derive( Clone , Debug , Eq , PartialEq , Serialize , Deserialize ) ]
443
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
415
444
#[ serde( deny_unknown_fields) ]
416
445
pub struct JaegerConfig {
417
446
/// Enables the gRPC endpoint that allows the Jaeger Query Service to connect and retrieve
0 commit comments