forked from FAForever/server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
executable file
·146 lines (118 loc) · 3.9 KB
/
server.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
#!/usr/bin/env python3
"""
Usage:
server.py [--nodb | --db TYPE]
Options:
--nodb Don't use a database (Use a mock.Mock). Caution: Will break things.
--db TYPE Use TYPE database driver [default: QMYSQL]
"""
import asyncio
import logging
import os
import signal
import socket
import sys
from datetime import datetime
from docopt import docopt
import server
from server.api.api_accessor import ApiAccessor
from server.config import config
from server.core import create_services
from server.ice_servers.nts import TwilioNTS
from server.profiler import Profiler
async def main():
loop = asyncio.get_running_loop()
done = asyncio.Future()
def signal_handler(sig: int, _frame):
logger.info(
"Received signal %s, shutting down",
signal.Signals(sig)
)
if not done.done():
done.set_result(0)
# Make sure we can shutdown gracefully
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
database = server.db.FAFDatabase(loop)
await database.connect(
host=config.DB_SERVER,
port=int(config.DB_PORT),
user=config.DB_LOGIN,
password=config.DB_PASSWORD,
maxsize=10,
db=config.DB_NAME,
)
# Set up services
twilio_nts = None
if config.TWILIO_ACCOUNT_SID:
twilio_nts = TwilioNTS()
else:
logger.warning(
"Twilio is not set up. You must set TWILIO_ACCOUNT_SID and TWILIO_TOKEN to use the Twilio ICE servers."
)
api_accessor = ApiAccessor()
services = create_services({
"api_accessor": api_accessor,
"database": database,
"loop": loop,
})
await asyncio.gather(*[
service.initialize() for service in services.values()
])
profiler = Profiler(services["player_service"])
profiler.refresh()
config.register_callback("PROFILING_COUNT", profiler.refresh)
config.register_callback("PROFILING_DURATION", profiler.refresh)
config.register_callback("PROFILING_INTERVAL", profiler.refresh)
ctrl_server = await server.run_control_server(
services["player_service"],
services["game_service"]
)
async def restart_control_server():
nonlocal ctrl_server
nonlocal services
await ctrl_server.shutdown()
ctrl_server = await server.run_control_server(
services["player_service"],
services["game_service"]
)
config.register_callback("CONTROL_SERVER_PORT", restart_control_server)
lobby_server = await server.run_lobby_server(
address=('', 8001),
database=database,
geoip_service=services["geo_ip_service"],
player_service=services["player_service"],
game_service=services["game_service"],
nts_client=twilio_nts,
ladder_service=services["ladder_service"],
loop=loop
)
for sock in lobby_server.sockets:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
server.metrics.info.info({
"version": os.environ.get("VERSION") or "dev",
"python_version": ".".join(map(str, sys.version_info[:3])),
"start_time": datetime.utcnow().strftime("%m-%d %H:%M"),
"game_uid": str(services["game_service"].game_id_counter)
})
await done
# Cleanup
await asyncio.gather(*[
service.shutdown() for service in services.values()
])
await ctrl_server.shutdown()
# Close DB connections
await database.close()
if __name__ == '__main__':
args = docopt(__doc__, version='FAF Server')
logger = logging.getLogger()
stderr_handler = logging.StreamHandler()
stderr_handler.setFormatter(
logging.Formatter(
fmt='%(levelname)-8s %(asctime)s %(name)-30s %(message)s',
datefmt='%b %d %H:%M:%S'
)
)
logger.addHandler(stderr_handler)
logger.setLevel(config.LOG_LEVEL)
asyncio.run(main())