77use std:: {
88 collections:: { HashMap , HashSet } ,
99 sync:: Arc ,
10+ time:: Duration ,
1011} ;
1112
1213use async_trait:: async_trait;
@@ -27,6 +28,8 @@ struct CasOperation {
2728 expected : Option < Vec < u8 > > ,
2829 /// New value to set if condition is met.
2930 new_value : Vec < u8 > ,
31+ /// Optional TTL for the new value.
32+ ttl : Option < Duration > ,
3033}
3134
3235/// Transaction for atomic operations on the Ledger backend.
@@ -120,6 +123,9 @@ pub struct LedgerTransaction {
120123 /// Pending delete operations: hex-encoded keys.
121124 pending_deletes : HashSet < String > ,
122125
126+ /// Pending TTLs for set operations: hex-encoded key -> duration.
127+ pending_ttls : HashMap < String , Duration > ,
128+
123129 /// Pending compare-and-set operations.
124130 pending_cas : Vec < CasOperation > ,
125131}
@@ -151,6 +157,7 @@ impl LedgerTransaction {
151157 read_consistency,
152158 pending_sets : HashMap :: new ( ) ,
153159 pending_deletes : HashSet :: new ( ) ,
160+ pending_ttls : HashMap :: new ( ) ,
154161 pending_cas : Vec :: new ( ) ,
155162 }
156163 }
@@ -199,6 +206,9 @@ impl Transaction for LedgerTransaction {
199206 // Remove from pending deletes if it was marked for deletion
200207 self . pending_deletes . remove ( & encoded_key) ;
201208
209+ // Clear any pending TTL — a plain set produces a non-expiring key
210+ self . pending_ttls . remove ( & encoded_key) ;
211+
202212 // Add to pending sets
203213 self . pending_sets . insert ( encoded_key, value) ;
204214 }
@@ -207,6 +217,9 @@ impl Transaction for LedgerTransaction {
207217 fn delete ( & mut self , key : Vec < u8 > ) {
208218 let encoded_key = encode_key ( & key) ;
209219
220+ // Clear any pending TTL
221+ self . pending_ttls . remove ( & encoded_key) ;
222+
210223 // Remove from pending sets if it was set in this transaction
211224 self . pending_sets . remove ( & encoded_key) ;
212225
@@ -224,7 +237,40 @@ impl Transaction for LedgerTransaction {
224237 let encoded_key = encode_key ( & key) ;
225238
226239 // Buffer the CAS operation - it will be applied at commit time
227- self . pending_cas . push ( CasOperation { key : encoded_key, expected, new_value } ) ;
240+ self . pending_cas . push ( CasOperation { key : encoded_key, expected, new_value, ttl : None } ) ;
241+ Ok ( ( ) )
242+ }
243+
244+ /// Buffers a set operation with TTL for atomic commit.
245+ fn set_with_ttl ( & mut self , key : Vec < u8 > , value : Vec < u8 > , ttl : Duration ) {
246+ let encoded_key = encode_key ( & key) ;
247+
248+ // Remove from pending deletes if it was marked for deletion
249+ self . pending_deletes . remove ( & encoded_key) ;
250+
251+ // Track the TTL for this key
252+ self . pending_ttls . insert ( encoded_key. clone ( ) , ttl) ;
253+
254+ // Add to pending sets
255+ self . pending_sets . insert ( encoded_key, value) ;
256+ }
257+
258+ /// Buffers a compare-and-set operation with TTL for atomic commit.
259+ fn compare_and_set_with_ttl (
260+ & mut self ,
261+ key : Vec < u8 > ,
262+ expected : Option < Vec < u8 > > ,
263+ new_value : Vec < u8 > ,
264+ ttl : Duration ,
265+ ) -> StorageResult < ( ) > {
266+ let encoded_key = encode_key ( & key) ;
267+
268+ self . pending_cas . push ( CasOperation {
269+ key : encoded_key,
270+ expected,
271+ new_value,
272+ ttl : Some ( ttl) ,
273+ } ) ;
228274 Ok ( ( ) )
229275 }
230276
@@ -253,12 +299,24 @@ impl Transaction for LedgerTransaction {
253299 None => SetCondition :: NotExists ,
254300 Some ( expected_value) => SetCondition :: ValueEquals ( expected_value) ,
255301 } ;
256- operations. push ( Operation :: set_entity_if ( cas. key , cas. new_value , condition) ) ;
302+ let expires_at =
303+ cas. ttl . map ( crate :: LedgerBackend :: compute_expiration_timestamp) . transpose ( ) ?;
304+ operations. push ( Operation :: SetEntity {
305+ key : cas. key ,
306+ value : cas. new_value ,
307+ expires_at,
308+ condition : Some ( condition) ,
309+ } ) ;
257310 }
258311
259312 // Add regular set operations
260313 for ( key, value) in self . pending_sets {
261- operations. push ( Operation :: set_entity ( key, value) ) ;
314+ if let Some ( ttl) = self . pending_ttls . get ( & key) {
315+ let expires_at = crate :: LedgerBackend :: compute_expiration_timestamp ( * ttl) ?;
316+ operations. push ( Operation :: set_entity_with_expiry ( key, value, expires_at) ) ;
317+ } else {
318+ operations. push ( Operation :: set_entity ( key, value) ) ;
319+ }
262320 }
263321
264322 // Add delete operations
0 commit comments