@@ -34,6 +34,8 @@ pub struct Config {
3434 pub port : u16 ,
3535 pub storage_mode : StorageMode ,
3636 pub data_dir : String ,
37+ pub require_volume : bool ,
38+ pub volume_available : bool ,
3739 pub durability : RedCoreDurability ,
3840 pub snapshot_interval_writes : u64 ,
3941 pub strict_acid : bool ,
@@ -71,15 +73,31 @@ impl Config {
7173 let storage_mode = env_first ( & [ "RUSTY_RED_MODE" , "THG_PRODUCT_STORE" ] )
7274 . map ( |value| StorageMode :: parse ( & value) )
7375 . unwrap_or ( StorageMode :: Embedded ) ;
76+ let railway_volume_mount_path = env:: var ( "RAILWAY_VOLUME_MOUNT_PATH" )
77+ . ok ( )
78+ . filter ( |value| !value. trim ( ) . is_empty ( ) ) ;
7479 let data_dir = env_first ( & [ "RUSTY_RED_DATA_DIR" , "THG_PRODUCT_DATA_DIR" ] )
75- . or_else ( |_| env:: var ( "RAILWAY_VOLUME_MOUNT_PATH" ) )
80+ . or_else ( |_| {
81+ railway_volume_mount_path
82+ . clone ( )
83+ . ok_or ( env:: VarError :: NotPresent )
84+ } )
7685 . unwrap_or_else ( |_| {
7786 if railway_port. is_some ( ) {
7887 "/app/data/rusty-red" . to_string ( )
7988 } else {
8089 "data/rusty-red" . to_string ( )
8190 }
8291 } ) ;
92+ let require_volume = env_bool (
93+ & [ "RUSTY_RED_REQUIRE_VOLUME" , "THG_PRODUCT_REQUIRE_VOLUME" ] ,
94+ railway_port. is_some ( ) ,
95+ ) ;
96+ let volume_available = railway_volume_mount_path. is_some ( )
97+ || env_bool (
98+ & [ "RUSTY_RED_VOLUME_MOUNTED" , "THG_PRODUCT_VOLUME_MOUNTED" ] ,
99+ false ,
100+ ) ;
83101 let durability = env_first ( & [ "RUSTY_RED_DURABILITY" , "THG_PRODUCT_DURABILITY" ] )
84102 . map ( |value| RedCoreDurability :: parse ( & value) )
85103 . unwrap_or ( RedCoreDurability :: AofEverysec ) ;
@@ -139,6 +157,8 @@ impl Config {
139157 port,
140158 storage_mode,
141159 data_dir,
160+ require_volume,
161+ volume_available,
142162 durability,
143163 snapshot_interval_writes,
144164 strict_acid,
@@ -164,6 +184,15 @@ impl Config {
164184 }
165185
166186 pub fn validate ( & self ) -> Result < ( ) , String > {
187+ if self . storage_mode == StorageMode :: Embedded
188+ && self . require_volume
189+ && !self . volume_available
190+ {
191+ return Err (
192+ "RUSTY_RED_REQUIRE_VOLUME=true requires RAILWAY_VOLUME_MOUNT_PATH or RUSTY_RED_VOLUME_MOUNTED=true"
193+ . to_string ( ) ,
194+ ) ;
195+ }
167196 if !self . strict_acid {
168197 return Ok ( ( ) ) ;
169198 }
@@ -228,6 +257,8 @@ mod tests {
228257 port : 8380 ,
229258 storage_mode : StorageMode :: Embedded ,
230259 data_dir : "data/rusty-red" . to_string ( ) ,
260+ require_volume : false ,
261+ volume_available : false ,
231262 durability : RedCoreDurability :: AofAlways ,
232263 snapshot_interval_writes : 1_000 ,
233264 strict_acid : true ,
@@ -260,4 +291,22 @@ mod tests {
260291 fn strict_acid_config_accepts_single_writer_serializable_embedded ( ) {
261292 assert_eq ! ( base_config( ) . validate( ) , Ok ( ( ) ) ) ;
262293 }
294+
295+ #[ test]
296+ fn embedded_config_rejects_missing_required_volume ( ) {
297+ let mut config = base_config ( ) ;
298+ config. require_volume = true ;
299+ config. volume_available = false ;
300+
301+ assert ! ( config. validate( ) . unwrap_err( ) . contains( "REQUIRE_VOLUME" ) ) ;
302+ }
303+
304+ #[ test]
305+ fn embedded_config_accepts_required_available_volume ( ) {
306+ let mut config = base_config ( ) ;
307+ config. require_volume = true ;
308+ config. volume_available = true ;
309+
310+ assert_eq ! ( config. validate( ) , Ok ( ( ) ) ) ;
311+ }
263312}
0 commit comments