forked from fecgov/openFEC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
manage.py
executable file
·147 lines (115 loc) · 3.92 KB
/
manage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
import os
import glob
import subprocess
import urllib.parse
import multiprocessing
from flask import url_for
from flask.ext.script import Server
from flask.ext.script import Manager
from sqlalchemy import text as sqla_text
from webservices.rest import app, db
from webservices.common.util import get_full_path
def get_cycle_start(year):
"""Round year down to the first year of the two-year election cycle. Used
when filtering original data for election cycle.
"""
return year if year % 2 == 1 else year - 1
SQL_CONFIG = {
'START_YEAR': get_cycle_start(1980),
}
manager = Manager(app)
# The Flask app server should only be used for local testing, so we default to
# using debug mode and auto-reload. To disable debug mode locally, pass the
# --no-debug flag to `runserver`.
manager.add_command('runserver', Server(use_debugger=True, use_reloader=True))
def execute_sql_file(path):
# This helper is typically used within a multiprocessing pool; create a new database
# engine for each job.
db.engine.dispose()
print(('Running {}'.format(path)))
with open(path) as fp:
cmd = '\n'.join([
line for line in fp.readlines()
if not line.startswith('--')
])
db.engine.execute(sqla_text(cmd), **SQL_CONFIG)
def execute_sql_folder(path, processes):
sql_dir = get_full_path(path)
paths = glob.glob(sql_dir + '*.sql')
pool = multiprocessing.Pool(processes=processes)
pool.map(execute_sql_file, paths)
@manager.command
def load_pacronyms():
count = db.engine.execute(
"select count(*) from pg_tables where tablename = 'pacronyms'"
).fetchone()[0]
if count:
db.engine.execute(
'delete from pacronyms'
)
cmd = ' | '.join([
'in2csv data/pacronyms.xlsx',
'csvsql --insert --db {dest} --table pacronyms'
]).format(dest=db.engine.url)
if count:
cmd += ' --no-create'
subprocess.call(cmd, shell=True)
@manager.command
def update_schemas(processes=2):
print("Starting DB refresh...")
processes = int(processes)
load_pacronyms()
execute_sql_folder('data/functions/', processes=processes)
execute_sql_folder('data/sql_updates/', processes=processes)
execute_sql_file('data/rename_temporary_views.sql')
print("Finished DB refresh.")
@manager.command
def list_routes():
output = []
for rule in app.url_map.iter_rules():
options = {}
for arg in rule.arguments:
options[arg] = "[{0}]".format(arg)
methods = ','.join(rule.methods)
url = url_for(rule.endpoint, **options)
line = urllib.parse.unquote(
'{:50s} {:20s} {}'.format(rule.endpoint, methods, url)
)
output.append(line)
for line in sorted(output):
print(line)
@manager.command
def refresh_materialized():
"""Refresh materialized views."""
print('Refreshing materialized views...')
execute_sql_file('data/refresh_materialized_views.sql')
print('Finished refreshing materialized views.')
@manager.command
def stop_beat():
"""Kill all celery beat workers.
Note: In the future, it would be more elegant to use a process manager like
supervisor or forever.
"""
return subprocess.Popen(
"ps aux | grep 'cron.py' | awk '{print $2}' | xargs kill -9",
shell=True,
)
@manager.command
def start_beat():
"""Start celery beat workers in the background using subprocess.
"""
# Stop beat workers synchronously
stop_beat().wait()
return subprocess.Popen(['python', 'cron.py'])
@manager.command
def cf_startup():
"""Start celery beat and schema migration on `cf-push`. Services are only
started if running on 0th instance.
"""
instance_id = os.getenv('CF_INSTANCE_INDEX')
if instance_id == '0':
start_beat()
subprocess.Popen(['python', 'manage.py', 'update_schemas'])
if __name__ == "__main__":
manager.run()