@@ -47,8 +47,8 @@ def cli(ctx):
47
47
@click .pass_context
48
48
def start (ctx , disable_collection , development , pidfile , port ):
49
49
"""Start Augur's backend server."""
50
- with open (pidfile , "w" ) as pidfile :
51
- pidfile .write (str (os .getpid ()))
50
+ with open (pidfile , "w" ) as pidfile_io :
51
+ pidfile_io .write (str (os .getpid ()))
52
52
53
53
try :
54
54
if os .environ .get ('AUGUR_DOCKER_DEPLOY' ) != "1" :
@@ -63,6 +63,8 @@ def start(ctx, disable_collection, development, pidfile, port):
63
63
if development :
64
64
os .environ ["AUGUR_DEV" ] = "1"
65
65
logger .info ("Starting in development mode" )
66
+
67
+ os .environ ["AUGUR_PIDFILE" ] = pidfile
66
68
67
69
try :
68
70
gunicorn_location = os .getcwd () + "/augur/api/gunicorn_conf.py"
@@ -74,6 +76,11 @@ def start(ctx, disable_collection, development, pidfile, port):
74
76
if not port :
75
77
port = get_value ("Server" , "port" )
76
78
79
+ os .environ ["AUGUR_PORT" ] = str (port )
80
+
81
+ if disable_collection :
82
+ os .environ ["AUGUR_DISABLE_COLLECTION" ] = "1"
83
+
77
84
worker_vmem_cap = get_value ("Celery" , 'worker_process_vmem_cap' )
78
85
79
86
gunicorn_command = f"gunicorn -c { gunicorn_location } -b { host } :{ port } augur.api.server:app --log-file gunicorn.log"
@@ -128,7 +135,7 @@ def start(ctx, disable_collection, development, pidfile, port):
128
135
augur_collection_monitor .si ().apply_async ()
129
136
130
137
else :
131
- logger .info ("Collection disabled" )
138
+ logger .info ("Collection disabled" )
132
139
133
140
try :
134
141
server .wait ()
@@ -153,6 +160,8 @@ def start(ctx, disable_collection, development, pidfile, port):
153
160
cleanup_after_collection_halt (logger , ctx .obj .engine )
154
161
except RedisConnectionError :
155
162
pass
163
+
164
+ os .unlink (pidfile )
156
165
157
166
def start_celery_worker_processes (vmem_cap_ratio , disable_collection = False ):
158
167
@@ -224,6 +233,54 @@ def stop(ctx):
224
233
225
234
augur_stop (signal .SIGTERM , logger , ctx .obj .engine )
226
235
236
+ @cli .command ('stop-collection-blocking' )
237
+ @test_connection
238
+ @test_db_connection
239
+ @with_database
240
+ @click .pass_context
241
+ def stop_collection (ctx ):
242
+ """
243
+ Stop collection tasks if they are running, block until complete
244
+ """
245
+ processes = get_augur_processes ()
246
+
247
+ stopped = []
248
+
249
+ p : psutil .Process
250
+ for p in processes :
251
+ if p .name () == "celery" :
252
+ stopped .append (p )
253
+ p .terminate ()
254
+
255
+ if not len (stopped ):
256
+ logger .info ("No collection processes found" )
257
+ return
258
+
259
+ _ , alive = psutil .wait_procs (stopped , 5 ,
260
+ lambda p : logger .info (f"STOPPED: { p .pid } " ))
261
+
262
+ killed = []
263
+ while True :
264
+ for i in range (len (alive )):
265
+ if alive [i ].status () == psutil .STATUS_ZOMBIE :
266
+ logger .info (f"KILLING ZOMBIE: { alive [i ].pid } " )
267
+ alive [i ].kill ()
268
+ killed .append (i )
269
+ elif not alive [i ].is_running ():
270
+ logger .info (f"STOPPED: { p .pid } " )
271
+ killed .append (i )
272
+
273
+ for i in reversed (killed ):
274
+ alive .pop (i )
275
+
276
+ if not len (alive ):
277
+ break
278
+
279
+ logger .info (f"Waiting on [{ ', ' .join (str (p .pid for p in alive ))} ]" )
280
+ time .sleep (0.5 )
281
+
282
+ cleanup_after_collection_halt (logger , ctx .obj .engine )
283
+
227
284
@cli .command ('kill' )
228
285
@test_connection
229
286
@test_db_connection
@@ -388,7 +445,7 @@ def processes():
388
445
Outputs the name/PID of all Augur server & worker processes"""
389
446
augur_processes = get_augur_processes ()
390
447
for process in augur_processes :
391
- logger .info (f"Found process { process .pid } " )
448
+ logger .info (f"Found process { process .pid } [ { process . name () } ] -> Parent: { process . parent (). pid } " )
392
449
393
450
def get_augur_processes ():
394
451
augur_processes = []
0 commit comments