@@ -38,9 +38,9 @@ use tokio_stream::{
3838use tracing:: trace;
3939use tracing_subscriber:: { fmt:: format:: FmtSpan , layer:: SubscriberExt , util:: SubscriberInitExt } ;
4040use types:: {
41- AccessTokenInfo , BasinConfig , Operation , PermittedOperationGroups , ResourceSet ,
42- RetentionPolicy , S2BasinAndMaybeStreamUri , S2BasinAndStreamUri , S2BasinUri , StorageClass ,
43- StreamConfig , TimestampingConfig , TimestampingMode ,
41+ AccessTokenInfo , BasinConfig , DeleteOnEmptyConfig , Operation , PermittedOperationGroups ,
42+ ResourceSet , RetentionPolicy , S2BasinAndMaybeStreamUri , S2BasinAndStreamUri , S2BasinUri ,
43+ StorageClass , StreamConfig , TimestampingConfig , TimestampingMode ,
4444} ;
4545
4646mod account;
@@ -161,6 +161,14 @@ enum Commands {
161161 /// Name of the basin to reconfigure.
162162 basin : S2BasinUri ,
163163
164+ /// Create stream on append with basin defaults if it doesn't exist.
165+ #[ arg( long) ]
166+ create_stream_on_append : Option < bool > ,
167+
168+ /// Create stream on read with basin defaults if it doesn't exist.
169+ #[ arg( long) ]
170+ create_stream_on_read : Option < bool > ,
171+
164172 /// Storage class for the default stream config.
165173 #[ arg( long) ]
166174 storage_class : Option < StorageClass > ,
@@ -177,13 +185,9 @@ enum Commands {
177185 #[ arg( long) ]
178186 timestamping_uncapped : Option < bool > ,
179187
180- /// Create stream on append with basin defaults if it doesn't exist.
181- #[ arg( long) ]
182- create_stream_on_append : Option < bool > ,
183-
184- /// Create stream on read with basin defaults if it doesn't exist.
188+ /// Delete-on-empty minimum age threshold for the default stream config.
185189 #[ arg( long) ]
186- create_stream_on_read : Option < bool > ,
190+ delete_on_empty_min_age : Option < humantime :: Duration > ,
187191 } ,
188192
189193 /// Issue an access token.
@@ -322,6 +326,10 @@ enum Commands {
322326 /// Uncapped timestamps for the stream.
323327 #[ arg( long) ]
324328 timestamping_uncapped : Option < bool > ,
329+
330+ /// Delete-on-empty minimum age threshold for the stream.
331+ #[ arg( long) ]
332+ delete_on_empty_min_age : Option < humantime:: Duration > ,
325333 } ,
326334
327335 /// Get the next sequence number that will be assigned by a stream.
@@ -645,12 +653,14 @@ fn build_basin_reconfig(
645653 timestamping_uncapped : Option < & bool > ,
646654 create_stream_on_append : Option < & bool > ,
647655 create_stream_on_read : Option < & bool > ,
656+ delete_on_empty_min_age : Option < & humantime:: Duration > ,
648657) -> ( StreamConfig , Vec < String > ) {
649658 let mut mask = Vec :: new ( ) ;
650659 let has_stream_args = storage_class. is_some ( )
651660 || retention_policy. is_some ( )
652661 || timestamping_mode. is_some ( )
653- || timestamping_uncapped. is_some ( ) ;
662+ || timestamping_uncapped. is_some ( )
663+ || delete_on_empty_min_age. is_some ( ) ;
654664
655665 let default_stream_config = if has_stream_args {
656666 let timestamping = if timestamping_mode. is_some ( ) || timestamping_uncapped. is_some ( ) {
@@ -662,15 +672,26 @@ fn build_basin_reconfig(
662672 None
663673 } ;
664674
675+ let delete_on_empty = delete_on_empty_min_age. map ( |d| DeleteOnEmptyConfig {
676+ delete_on_empty_min_age : ( * d) . into ( ) ,
677+ } ) ;
678+
665679 StreamConfig {
666680 storage_class : storage_class. cloned ( ) ,
667681 retention_policy : retention_policy. cloned ( ) ,
668682 timestamping,
683+ delete_on_empty,
669684 }
670685 } else {
671686 Default :: default ( )
672687 } ;
673688
689+ if create_stream_on_append. is_some ( ) {
690+ mask. push ( "create_stream_on_append" . to_owned ( ) ) ;
691+ }
692+ if create_stream_on_read. is_some ( ) {
693+ mask. push ( "create_stream_on_read" . to_owned ( ) ) ;
694+ }
674695 if storage_class. is_some ( ) {
675696 mask. push ( "default_stream_config.storage_class" . to_owned ( ) ) ;
676697 }
@@ -683,11 +704,8 @@ fn build_basin_reconfig(
683704 if timestamping_uncapped. is_some ( ) {
684705 mask. push ( "default_stream_config.timestamping.uncapped" . to_owned ( ) ) ;
685706 }
686- if create_stream_on_append. is_some ( ) {
687- mask. push ( "create_stream_on_append" . to_owned ( ) ) ;
688- }
689- if create_stream_on_read. is_some ( ) {
690- mask. push ( "create_stream_on_read" . to_owned ( ) ) ;
707+ if delete_on_empty_min_age. is_some ( ) {
708+ mask. push ( "default_stream_config.delete_on_empty.min_age_secs" . to_owned ( ) ) ;
691709 }
692710
693711 ( default_stream_config, mask)
@@ -698,6 +716,7 @@ fn build_stream_reconfig(
698716 retention_policy : Option < & RetentionPolicy > ,
699717 timestamping_mode : Option < & TimestampingMode > ,
700718 timestamping_uncapped : Option < & bool > ,
719+ delete_on_empty_min_age : Option < & humantime:: Duration > ,
701720) -> ( StreamConfig , Vec < String > ) {
702721 let mut mask = Vec :: new ( ) ;
703722
@@ -710,10 +729,15 @@ fn build_stream_reconfig(
710729 None
711730 } ;
712731
732+ let delete_on_empty = delete_on_empty_min_age. map ( |d| DeleteOnEmptyConfig {
733+ delete_on_empty_min_age : ( * d) . into ( ) ,
734+ } ) ;
735+
713736 let stream_config = StreamConfig {
714737 storage_class : storage_class. cloned ( ) ,
715738 retention_policy : retention_policy. cloned ( ) ,
716739 timestamping,
740+ delete_on_empty,
717741 } ;
718742
719743 if storage_class. is_some ( ) {
@@ -728,6 +752,9 @@ fn build_stream_reconfig(
728752 if timestamping_uncapped. is_some ( ) {
729753 mask. push ( "timestamping.uncapped" . to_string ( ) ) ;
730754 }
755+ if delete_on_empty_min_age. is_some ( ) {
756+ mask. push ( "delete_on_empty.min_age_secs" . to_string ( ) ) ;
757+ }
731758
732759 ( stream_config, mask)
733760}
@@ -987,6 +1014,7 @@ async fn run() -> Result<(), S2CliError> {
9871014 timestamping_uncapped,
9881015 create_stream_on_append,
9891016 create_stream_on_read,
1017+ delete_on_empty_min_age,
9901018 } => {
9911019 let cfg = config:: load_config ( & config_path) ?;
9921020 let client_config = client_config ( cfg. access_token ) ?;
@@ -999,6 +1027,7 @@ async fn run() -> Result<(), S2CliError> {
9991027 timestamping_uncapped. as_ref ( ) ,
10001028 create_stream_on_append. as_ref ( ) ,
10011029 create_stream_on_read. as_ref ( ) ,
1030+ delete_on_empty_min_age. as_ref ( ) ,
10021031 ) ;
10031032
10041033 let basin_config = BasinConfig {
@@ -1070,6 +1099,7 @@ async fn run() -> Result<(), S2CliError> {
10701099 retention_policy,
10711100 timestamping_mode,
10721101 timestamping_uncapped,
1102+ delete_on_empty_min_age,
10731103 } => {
10741104 let S2BasinAndStreamUri { basin, stream } = uri. uri ;
10751105 let cfg = config:: load_config ( & config_path) ?;
@@ -1081,6 +1111,7 @@ async fn run() -> Result<(), S2CliError> {
10811111 retention_policy. as_ref ( ) ,
10821112 timestamping_mode. as_ref ( ) ,
10831113 timestamping_uncapped. as_ref ( ) ,
1114+ delete_on_empty_min_age. as_ref ( ) ,
10841115 ) ;
10851116
10861117 let config: StreamConfig = BasinService :: new ( basin_client)
0 commit comments