@@ -33,7 +33,7 @@ use arrow_schema::{Field, Schema};
3333use bytes:: Bytes ;
3434use chrono:: Utc ;
3535use clap:: { Parser , error:: ErrorKind } ;
36- use once_cell:: sync:: Lazy ;
36+ use once_cell:: sync:: { Lazy , OnceCell } ;
3737use relative_path:: RelativePathBuf ;
3838pub use staging:: StagingError ;
3939use streams:: StreamRef ;
@@ -99,6 +99,9 @@ pub const JOIN_COMMUNITY: &str =
9999 "Join us on Parseable Slack community for questions : https://logg.ing/community" ;
100100pub const STREAM_EXISTS : & str = "Stream exists" ;
101101
102+ /// OnceCell to return metastore
103+ pub static METASTORE : OnceCell < Arc < dyn Metastore > > = OnceCell :: new ( ) ;
104+
102105/// For OTel log sources the telemetry_type is fully determined by the log_source.
103106/// When the user explicitly sets x-p-telemetry-type and it disagrees with the
104107/// implied type for an otel-* source, reject the request. When they don't set it,
@@ -134,6 +137,34 @@ fn resolve_telemetry_type(
134137
135138/// Shared state of the Parseable server.
136139pub static PARSEABLE : Lazy < Parseable > = Lazy :: new ( || {
140+ let metastore = METASTORE . get_or_init ( || {
141+ // Prompt user for missing env vars before clap validates them.
142+ // Values are set in env but NOT saved to disk yet.
143+ let collected_envs = crate :: interactive:: prompt_missing_envs ( ) ;
144+
145+ // Use try_parse so we can avoid persisting bad values on failure.
146+ let cli = match Cli :: try_parse ( ) {
147+ Ok ( cli) => {
148+ // Clap accepted all values — safe to persist to .parseable.env
149+ crate :: interactive:: save_collected_envs ( & collected_envs) ;
150+ cli
151+ }
152+ Err ( e) => {
153+ // Clap rejected something — don't save, just show the error and exit.
154+ e. exit ( ) ;
155+ }
156+ } ;
157+ let storage = match & cli. storage {
158+ StorageOptions :: Local ( args) => args. storage . construct_client ( ) ,
159+ StorageOptions :: S3 ( args) => args. storage . construct_client ( ) ,
160+ StorageOptions :: Blob ( args) => args. storage . construct_client ( ) ,
161+ StorageOptions :: Gcs ( args) => args. storage . construct_client ( ) ,
162+ } ;
163+ tracing:: warn!( "creating objectstoremetastore" ) ;
164+ let metastore = ObjectStoreMetastore { storage } ;
165+ Arc :: new ( metastore)
166+ } ) ;
167+
137168 // Prompt user for missing env vars before clap validates them.
138169 // Values are set in env but NOT saved to disk yet.
139170 let collected_envs = crate :: interactive:: prompt_missing_envs ( ) ;
@@ -150,7 +181,6 @@ pub static PARSEABLE: Lazy<Parseable> = Lazy::new(|| {
150181 e. exit ( ) ;
151182 }
152183 } ;
153-
154184 match cli. storage {
155185 StorageOptions :: Local ( args) => {
156186 if args. options . staging_dir ( ) == & args. storage . root {
@@ -169,62 +199,46 @@ pub static PARSEABLE: Lazy<Parseable> = Lazy::new(|| {
169199 . exit ( ) ;
170200 }
171201
172- // for now create a metastore without using a CLI arg
173- let metastore = ObjectStoreMetastore {
174- storage : args. storage . construct_client ( ) ,
175- } ;
176202 let hottier_connection_pool = args. storage . construct_client ( ) ;
177203 Parseable :: new (
178204 args. options ,
179205 #[ cfg( feature = "kafka" ) ]
180206 args. kafka ,
181207 Arc :: new ( args. storage ) ,
182- Arc :: new ( metastore) ,
208+ metastore. clone ( ) ,
183209 hottier_connection_pool,
184210 )
185211 }
186212 StorageOptions :: S3 ( args) => {
187- // for now create a metastore without using a CLI arg
188- let metastore = ObjectStoreMetastore {
189- storage : args. storage . construct_client ( ) ,
190- } ;
191213 let hottier_connection_pool = args. storage . construct_client ( ) ;
192214 Parseable :: new (
193215 args. options ,
194216 #[ cfg( feature = "kafka" ) ]
195217 args. kafka ,
196218 Arc :: new ( args. storage ) ,
197- Arc :: new ( metastore) ,
219+ metastore. clone ( ) ,
198220 hottier_connection_pool,
199221 )
200222 }
201223 StorageOptions :: Blob ( args) => {
202- // for now create a metastore without using a CLI arg
203- let metastore = ObjectStoreMetastore {
204- storage : args. storage . construct_client ( ) ,
205- } ;
206224 let hottier_connection_pool = args. storage . construct_client ( ) ;
207225 Parseable :: new (
208226 args. options ,
209227 #[ cfg( feature = "kafka" ) ]
210228 args. kafka ,
211229 Arc :: new ( args. storage ) ,
212- Arc :: new ( metastore) ,
230+ metastore. clone ( ) ,
213231 hottier_connection_pool,
214232 )
215233 }
216234 StorageOptions :: Gcs ( args) => {
217- // for now create a metastore without using a CLI arg
218- let metastore = ObjectStoreMetastore {
219- storage : args. storage . construct_client ( ) ,
220- } ;
221235 let hottier_connection_pool = args. storage . construct_client ( ) ;
222236 Parseable :: new (
223237 args. options ,
224238 #[ cfg( feature = "kafka" ) ]
225239 args. kafka ,
226240 Arc :: new ( args. storage ) ,
227- Arc :: new ( metastore) ,
241+ metastore. clone ( ) ,
228242 hottier_connection_pool,
229243 )
230244 }
0 commit comments