6
6
//!
7
7
//! Specific pieces of configuration must implement the `TryUpdateKey` trait which
8
8
//! defines how to update internal fields based on key-value pairs.
9
- #[ cfg( feature = "cloud" ) ]
10
- use :: object_store:: RetryConfig ;
9
+
11
10
use object_store:: { path:: Path , prefix:: PrefixStore , ObjectStore } ;
12
11
use std:: collections:: HashMap ;
12
+ use std:: sync:: Arc ;
13
13
14
+ use super :: storage:: file_cache:: { self , FileCacheConfig } ;
14
15
use super :: storage:: LimitConfig ;
15
16
use super :: { storage:: runtime:: RuntimeConfig , IORuntime } ;
16
17
use crate :: { DeltaResult , DeltaTableError } ;
@@ -103,6 +104,11 @@ pub struct StorageConfig {
103
104
/// Configuration to limit the number of concurrent requests to the object store.
104
105
pub limit : Option < LimitConfig > ,
105
106
107
+ /// File cache configuration.
108
+ ///
109
+ /// Configuration to enable file cache for the Delta Log Store.
110
+ pub file_cache : Option < FileCacheConfig > ,
111
+
106
112
/// Properties that are not recognized by the storage configuration.
107
113
///
108
114
/// These properties are ignored by the storage configuration and can be used for custom purposes.
@@ -121,12 +127,27 @@ impl StorageConfig {
121
127
/// Depending on the configuration, the following layers may be added:
122
128
/// - Retry layer: Adds retry logic to the object store.
123
129
/// - Limit layer: Limits the number of concurrent requests to the object store.
130
+ /// - File cache layer: Adds a file cache to the object store.
124
131
pub fn decorate_store < T : ObjectStore + Clone > (
125
132
& self ,
126
133
store : T ,
127
134
table_root : & url:: Url ,
128
135
) -> DeltaResult < Box < dyn ObjectStore > > {
129
- let inner = Self :: decorate_prefix ( store, table_root) ?;
136
+ let inner = self . decorate_root_store ( store) ?;
137
+ let inner = Self :: decorate_prefix ( inner, table_root) ?;
138
+ Ok ( inner)
139
+ }
140
+
141
+ /// Wraps an object store with additional layers of functionality without prefix.
142
+ pub ( crate ) fn decorate_root_store < T : ObjectStore > (
143
+ & self ,
144
+ store : T ,
145
+ ) -> DeltaResult < Box < dyn ObjectStore > > {
146
+ let inner = if let Some ( file_cache) = self . file_cache . as_ref ( ) {
147
+ file_cache:: decorate_store ( Arc :: new ( store) , file_cache) ?
148
+ } else {
149
+ Box :: new ( store)
150
+ } ;
130
151
Ok ( inner)
131
152
}
132
153
@@ -169,7 +190,7 @@ where
169
190
170
191
#[ cfg( feature = "cloud" ) ]
171
192
let remainder = {
172
- let result = ParseResult :: < RetryConfig > :: from_iter ( remainder) ;
193
+ let result = ParseResult :: < object_store :: RetryConfig > :: from_iter ( remainder) ;
173
194
config. retry = result. config ;
174
195
result. unparsed
175
196
} ;
@@ -225,6 +246,11 @@ impl StorageConfig {
225
246
remainder
226
247
} ;
227
248
249
+ let result = ParseResult :: < FileCacheConfig > :: from_iter ( remainder) ;
250
+ result. raise_errors ( ) ?;
251
+ props. file_cache = ( !result. is_default ) . then_some ( result. config ) ;
252
+ let remainder = result. unparsed ;
253
+
228
254
props. unknown_properties = remainder;
229
255
Ok ( props)
230
256
}
@@ -403,4 +429,36 @@ mod tests {
403
429
StorageConfig :: default ( ) . with_io_runtime ( IORuntime :: Config ( RuntimeConfig :: default ( ) ) ) ;
404
430
assert ! ( config. runtime. is_some( ) ) ;
405
431
}
432
+
433
+ #[ test]
434
+ fn test_file_cache_config_from_options ( ) {
435
+ let options = hashmap ! {
436
+ "file_cache_path" . to_string( ) => "/tmp/file_cache" . to_string( ) ,
437
+ } ;
438
+
439
+ let ( file_cache_config, remainder) : ( FileCacheConfig , _ ) =
440
+ super :: try_parse_impl ( options) . unwrap ( ) ;
441
+ assert ! ( remainder. is_empty( ) ) ;
442
+
443
+ assert_eq ! ( file_cache_config. path, "/tmp/file_cache" ) ;
444
+ assert ! ( file_cache_config. last_checkpoint_valid_duration. is_none( ) ) ;
445
+ }
446
+
447
+ #[ test]
448
+ fn test_file_cache_config_from_options_with_last_checkpoint_valid_duration ( ) {
449
+ let options = hashmap ! {
450
+ "file_cache_path" . to_string( ) => "/tmp/file_cache" . to_string( ) ,
451
+ "file_cache_last_checkpoint_valid_duration" . to_string( ) => "1h" . to_string( ) ,
452
+ } ;
453
+
454
+ let ( file_cache_config, remainder) : ( FileCacheConfig , _ ) =
455
+ super :: try_parse_impl ( options) . unwrap ( ) ;
456
+ assert ! ( remainder. is_empty( ) ) ;
457
+
458
+ assert_eq ! ( file_cache_config. path, "/tmp/file_cache" ) ;
459
+ assert_eq ! (
460
+ file_cache_config. last_checkpoint_valid_duration,
461
+ Some ( Duration :: from_secs( 3600 ) )
462
+ ) ;
463
+ }
406
464
}
0 commit comments