11import json
2- import multiprocessing
32import os
43import platform
5- import signal
64import socket
75import subprocess
86import sys
2018
2119from .mkcert import MkcertManager
2220from .process import ProcessManager
23- from .services import ServicesProcess
2421from .utils import has_pyproject_toml
2522
2623ENTRYPOINT_GROUP = "plain.dev"
@@ -132,7 +129,6 @@ def _port_available(self, port):
132129
133130 def run (self ):
134131 self .write_pidfile ()
135- click .secho (f"PID: { self .pid_value } " , dim = True )
136132 mkcert_manager = MkcertManager ()
137133 mkcert_manager .setup_mkcert (install_path = Path .home () / ".plain" / "dev" )
138134 self .ssl_cert_path , self .ssl_key_path = mkcert_manager .generate_certs (
@@ -143,49 +139,39 @@ def run(self):
143139 self .symlink_plain_src ()
144140 self .modify_hosts_file ()
145141 self .set_allowed_hosts ()
142+
143+ click .secho ("→ Running preflight checks... " , dim = True , nl = False )
146144 self .run_preflight ()
147145
148- # If we start services ourselves, we should manage the pidfile
149- services_proc = None
150-
151- # Services start first (or are already running from a separate command)
152- if running_pid := ServicesProcess ().running_pid ():
153- click .secho (f"Services already running (pid={ running_pid } )" , fg = "yellow" )
154- elif services := ServicesProcess .get_services (APP_PATH .parent ):
155- click .secho ("\n Starting services..." , italic = True , dim = True )
156- services_proc = ServicesProcess ()
157- services_proc .write_pidfile ()
158-
159- for name , data in services .items ():
160- env = {
161- ** os .environ ,
162- "PYTHONUNBUFFERED" : "true" ,
163- ** data .get ("env" , {}),
164- }
165- self .poncho .add_process (name , data ["cmd" ], env = env )
166-
167- # If plain.models is installed (common) then we
168- # will do a couple extra things before starting all of the app-related
169- # processes (this way they don't all have to db-wait or anything)
170- process = None
171- if find_spec ("plain.models" ) is not None :
172- # Use a custom signal to tell the main thread to add
173- # the app processes once the db is ready
174- signal .signal (signal .SIGUSR1 , self .start_app )
175-
176- process = multiprocessing .Process (
177- target = _process_task , args = (self .plain_env ,)
146+ # if ServicesProcess.running_pid():
147+ # self.poncho.add_process(
148+ # "services",
149+ # f"{sys.executable} -m plain dev logs --services --follow",
150+ # )
151+
152+ if find_spec ("plain.models" ):
153+ click .secho ("→ Waiting for database... " , dim = True , nl = False )
154+ subprocess .run (
155+ [sys .executable , "-m" , "plain" , "models" , "db-wait" ],
156+ env = self .plain_env ,
157+ check = True ,
158+ )
159+ click .secho ("→ Running migrations..." , dim = True )
160+ subprocess .run (
161+ [sys .executable , "-m" , "plain" , "migrate" , "--backup" ],
162+ env = self .plain_env ,
163+ check = True ,
178164 )
179- process .start ()
180165
181- # If there are no poncho processes, then let this process finish before
182- # continuing (vs running in parallel)
183- if self .poncho .num_processes () == 0 :
184- # Wait for the process to finish
185- process .join ()
186- else :
187- # Start the app processes immediately
188- self .start_app (None , None )
166+ click .secho ("\n → Starting app..." , dim = True )
167+
168+ # Manually start the status bar now so it isn't bungled by
169+ # another thread checking db stuff...
170+ self .console_status .start ()
171+
172+ self .add_gunicorn ()
173+ self .add_entrypoints ()
174+ self .add_pyproject_run ()
189175
190176 try :
191177 # Start processes we know about and block the main thread
@@ -195,35 +181,10 @@ def run(self):
195181 self .console_status .stop ()
196182 finally :
197183 self .rm_pidfile ()
198- # Make sure the services pid gets removed if we set it
199- if services_proc :
200- services_proc .rm_pidfile ()
201-
202184 self .close ()
203185
204- # Make sure the process is terminated if it is still running
205- if process and process .is_alive ():
206- os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
207- process .join (timeout = 3 )
208- if process .is_alive ():
209- os .killpg (os .getpgid (process .pid ), signal .SIGKILL )
210- process .join ()
211-
212186 return self .poncho .returncode
213187
214- def start_app (self , signum , frame ):
215- # This runs in the main thread when SIGUSR1 is received
216- # (or called directly if no thread).
217- click .secho ("\n Starting app..." , italic = True , dim = True )
218-
219- # Manually start the status bar now so it isn't bungled by
220- # another thread checking db stuff...
221- self .console_status .start ()
222-
223- self .add_gunicorn ()
224- self .add_entrypoints ()
225- self .add_pyproject_run ()
226-
227188 def symlink_plain_src (self ):
228189 """Symlink the plain package into .plain so we can look at it easily"""
229190 plain_path = Path (find_spec ("plain.runtime" ).origin ).parent .parent
@@ -316,7 +277,6 @@ def set_allowed_hosts(self):
316277 )
317278
318279 def run_preflight (self ):
319- click .echo ()
320280 if subprocess .run (["plain" , "preflight" ], env = self .plain_env ).returncode :
321281 click .secho ("Preflight check failed!" , fg = "red" )
322282 sys .exit (1 )
@@ -386,16 +346,3 @@ def add_pyproject_run(self):
386346 ** data .get ("env" , {}),
387347 }
388348 self .poncho .add_process (name , data ["cmd" ], env = env )
389-
390-
391- def _process_task (env ):
392- # Make this process the leader of a new group which can be killed together if it doesn't finish
393- os .setsid ()
394-
395- subprocess .run (["plain" , "models" , "db-wait" ], env = env , check = True )
396- subprocess .run (["plain" , "migrate" , "--backup" ], env = env , check = True )
397-
398- # preflight with db?
399-
400- # Send SIGUSR1 to the parent process so the parent's handler is invoked
401- os .kill (os .getppid (), signal .SIGUSR1 )
0 commit comments