@@ -26,6 +26,7 @@ use once_cell::sync::OnceCell;
2626use std:: io;
2727
2828use crate :: {
29+ metadata:: error:: stream_info:: MetadataError ,
2930 option:: { Mode , CONFIG , JOIN_COMMUNITY } ,
3031 rbac:: { role:: model:: DefaultPrivilege , user:: User } ,
3132 storage:: ObjectStorageError ,
@@ -55,6 +56,7 @@ pub struct StorageMetadata {
5556 pub deployment_id : uid:: Uid ,
5657 pub users : Vec < User > ,
5758 pub streams : Vec < String > ,
59+ pub server_mode : String ,
5860 #[ serde( default ) ]
5961 pub roles : HashMap < String , Vec < DefaultPrivilege > > ,
6062 #[ serde( default ) ]
@@ -69,6 +71,7 @@ impl StorageMetadata {
6971 staging : CONFIG . staging_dir ( ) . to_path_buf ( ) ,
7072 storage : CONFIG . storage ( ) . get_endpoint ( ) ,
7173 deployment_id : uid:: gen ( ) ,
74+ server_mode : CONFIG . parseable . mode . to_string ( ) ,
7275 users : Vec :: new ( ) ,
7376 streams : Vec :: new ( ) ,
7477 roles : HashMap :: default ( ) ,
@@ -100,18 +103,8 @@ pub async fn resolve_parseable_metadata() -> Result<StorageMetadata, ObjectStora
100103 let storage = CONFIG . storage ( ) . get_object_store ( ) ;
101104 let remote_metadata = storage. get_metadata ( ) . await ?;
102105
103- let check = match ( staging_metadata, remote_metadata) {
104- ( Some ( staging) , Some ( remote) ) => {
105- if staging. deployment_id == remote. deployment_id {
106- EnvChange :: None ( remote)
107- } else {
108- EnvChange :: NewRemote
109- }
110- }
111- ( None , Some ( remote) ) => EnvChange :: NewStaging ( remote) ,
112- ( Some ( _) , None ) => EnvChange :: NewRemote ,
113- ( None , None ) => EnvChange :: CreateBoth ,
114- } ;
106+ // Env Change needs to be updated
107+ let check = determine_environment ( staging_metadata, remote_metadata) ;
115108
116109 // flags for if metadata needs to be synced
117110 let mut overwrite_staging = false ;
@@ -121,6 +114,12 @@ pub async fn resolve_parseable_metadata() -> Result<StorageMetadata, ObjectStora
121114 EnvChange :: None ( metadata) => {
122115 // overwrite staging anyways so that it matches remote in case of any divergence
123116 overwrite_staging = true ;
117+ if CONFIG . parseable . mode == Mode :: All {
118+ standalone_when_distributed ( Mode :: from_string ( & metadata. server_mode ) . expect ( "mode should be valid at here" ) )
119+ . map_err ( |err| {
120+ ObjectStorageError :: Custom ( err. to_string ( ) )
121+ } ) ?;
122+ }
124123 Ok ( metadata)
125124 } ,
126125 EnvChange :: NewRemote => {
@@ -134,8 +133,22 @@ pub async fn resolve_parseable_metadata() -> Result<StorageMetadata, ObjectStora
134133 // overwrite remote in all and query mode
135134 // because staging dir has changed.
136135 match CONFIG . parseable . mode {
137- Mode :: All | Mode :: Query => overwrite_remote = true ,
138- _ => {
136+ Mode :: All => {
137+ standalone_when_distributed ( Mode :: from_string ( & metadata. server_mode ) . expect ( "mode should be valid at here" ) )
138+ . map_err ( |err| {
139+ ObjectStorageError :: Custom ( err. to_string ( ) )
140+ } ) ?;
141+ overwrite_remote = true ;
142+ } ,
143+ Mode :: Query => {
144+ overwrite_remote = true ;
145+ metadata. server_mode = CONFIG . parseable . mode . to_string ( ) ;
146+ metadata. staging = CONFIG . staging_dir ( ) . to_path_buf ( ) ;
147+ } ,
148+ Mode :: Ingest => {
149+ // if ingest server is started fetch the metadata from remote
150+ // update the server mode for local metadata
151+ metadata. server_mode = CONFIG . parseable . mode . to_string ( ) ;
139152 metadata. staging = CONFIG . staging_dir ( ) . to_path_buf ( ) ;
140153 } ,
141154 }
@@ -173,6 +186,32 @@ pub async fn resolve_parseable_metadata() -> Result<StorageMetadata, ObjectStora
173186 Ok ( metadata)
174187}
175188
189+ fn determine_environment (
190+ staging_metadata : Option < StorageMetadata > ,
191+ remote_metadata : Option < StorageMetadata > ,
192+ ) -> EnvChange {
193+ match ( staging_metadata, remote_metadata) {
194+ ( Some ( staging) , Some ( remote) ) => {
195+ // if both staging and remote have same deployment id
196+ if staging. deployment_id == remote. deployment_id {
197+ EnvChange :: None ( remote)
198+ } else if Mode :: from_string ( & remote. server_mode ) . unwrap ( ) == Mode :: All
199+ && ( CONFIG . parseable . mode == Mode :: Query || CONFIG . parseable . mode == Mode :: Ingest )
200+ {
201+ // if you are switching to distributed mode from standalone mode
202+ // it will create a new staging rather than a new remote
203+ EnvChange :: NewStaging ( remote)
204+ } else {
205+ // it is a new remote
206+ EnvChange :: NewRemote
207+ }
208+ }
209+ ( None , Some ( remote) ) => EnvChange :: NewStaging ( remote) ,
210+ ( Some ( _) , None ) => EnvChange :: NewRemote ,
211+ ( None , None ) => EnvChange :: CreateBoth ,
212+ }
213+ }
214+
176215// variant contain remote metadata
177216#[ derive( Debug , Clone , PartialEq , Eq ) ]
178217pub enum EnvChange {
@@ -187,6 +226,16 @@ pub enum EnvChange {
187226 CreateBoth ,
188227}
189228
229+ fn standalone_when_distributed ( remote_server_mode : Mode ) -> Result < ( ) , MetadataError > {
230+ // mode::all -> mode::query | mode::ingest allowed
231+ // but mode::query | mode::ingest -> mode::all not allowed
232+ if remote_server_mode == Mode :: Query {
233+ return Err ( MetadataError :: StandaloneWithDistributed ( "Starting Standalone Mode is not permitted when Distributed Mode is enabled. Please restart the server with Distributed Mode enabled." . to_string ( ) ) ) ;
234+ }
235+
236+ Ok ( ( ) )
237+ }
238+
190239pub fn get_staging_metadata ( ) -> io:: Result < Option < StorageMetadata > > {
191240 let path = CONFIG . staging_dir ( ) . join ( PARSEABLE_METADATA_FILE_NAME ) ;
192241 let bytes = match fs:: read ( path) {
0 commit comments