optimize tracker, using more RAM, less CPU
This commit is contained in:
parent
36db420120
commit
dacecc4637
17
WebHost.py
17
WebHost.py
|
@ -5,25 +5,28 @@ import logging
|
||||||
from WebHost import app
|
from WebHost import app
|
||||||
from waitress import serve
|
from waitress import serve
|
||||||
|
|
||||||
from WebHost.models import db
|
from WebHost.models import db, Room, db_session, select
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
port = 80
|
port = 80
|
||||||
|
|
||||||
|
|
||||||
def autohost(config: dict):
|
def autohost(config: dict):
|
||||||
from WebHost.models import *
|
return
|
||||||
|
# not implemented yet. https://github.com/ponyorm/pony/issues/527
|
||||||
import time
|
import time
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
def keep_running():
|
def keep_running():
|
||||||
db.bind(**config["pony"])
|
# db.bind(**config["PONY"])
|
||||||
db.generate_mapping(check_tables=False)
|
# db.generate_mapping(check_tables=False)
|
||||||
while 1:
|
while 1:
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
with db_session:
|
with db_session:
|
||||||
select(
|
rooms = select(
|
||||||
room for room in Room if (datetime.utcnow() - room.last_activity) < timedelta(hours=room.timeout))
|
room for room in Room if
|
||||||
|
room.last_activity >= datetime.utcnow() - timedelta(hours=room.timeout))
|
||||||
|
logging.info(rooms)
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
threading.Thread(target=keep_running).start()
|
threading.Thread(target=keep_running).start()
|
||||||
|
@ -45,7 +48,7 @@ if __name__ == "__main__":
|
||||||
db.bind(**app.config["PONY"])
|
db.bind(**app.config["PONY"])
|
||||||
db.generate_mapping(create_tables=True)
|
db.generate_mapping(create_tables=True)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
autohost(config)
|
autohost(app.config)
|
||||||
app.run(debug=True, port=port)
|
app.run(debug=True, port=port)
|
||||||
else:
|
else:
|
||||||
serve(app, port=port, threads=app.config["WAITRESS_THREADS"])
|
serve(app, port=port, threads=app.config["WAITRESS_THREADS"])
|
||||||
|
|
|
@ -8,7 +8,7 @@ db = Database()
|
||||||
class Patch(db.Entity):
|
class Patch(db.Entity):
|
||||||
id = PrimaryKey(int, auto=True)
|
id = PrimaryKey(int, auto=True)
|
||||||
player = Required(int)
|
player = Required(int)
|
||||||
data = Required(buffer)
|
data = Required(buffer, lazy=True)
|
||||||
seed = Optional('Seed')
|
seed = Optional('Seed')
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class Room(db.Entity):
|
||||||
owner = Required(UUID, index=True)
|
owner = Required(UUID, index=True)
|
||||||
commands = Set('Command')
|
commands = Set('Command')
|
||||||
seed = Required('Seed', index=True)
|
seed = Required('Seed', index=True)
|
||||||
multisave = Optional(Json)
|
multisave = Optional(Json, lazy=True)
|
||||||
show_spoiler = Required(int, default=0) # 0 -> never, 1 -> after completion, -> 2 always
|
show_spoiler = Required(int, default=0) # 0 -> never, 1 -> after completion, -> 2 always
|
||||||
timeout = Required(int, default=lambda: 6)
|
timeout = Required(int, default=lambda: 6)
|
||||||
tracker = Optional(UUID, index=True)
|
tracker = Optional(UUID, index=True)
|
||||||
|
@ -29,11 +29,11 @@ class Room(db.Entity):
|
||||||
class Seed(db.Entity):
|
class Seed(db.Entity):
|
||||||
id = PrimaryKey(UUID, default=uuid4)
|
id = PrimaryKey(UUID, default=uuid4)
|
||||||
rooms = Set(Room)
|
rooms = Set(Room)
|
||||||
multidata = Optional(Json)
|
multidata = Optional(Json, lazy=True)
|
||||||
owner = Required(UUID, index=True)
|
owner = Required(UUID, index=True)
|
||||||
creation_time = Required(datetime, default=lambda: datetime.utcnow())
|
creation_time = Required(datetime, default=lambda: datetime.utcnow())
|
||||||
patches = Set(Patch)
|
patches = Set(Patch)
|
||||||
spoiler = Optional(str)
|
spoiler = Optional(str, lazy=True)
|
||||||
|
|
||||||
|
|
||||||
class Command(db.Entity):
|
class Command(db.Entity):
|
||||||
|
|
|
@ -9,4 +9,8 @@ table.dataTable.table-sm > thead > tr > th :not(.sorting_disabled) {
|
||||||
|
|
||||||
th {
|
th {
|
||||||
padding: 1px !important;
|
padding: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100% !important;
|
||||||
}
|
}
|
|
@ -192,21 +192,35 @@ def render_timedelta(delta: datetime.timedelta):
|
||||||
return f"{hours}:{minutes}"
|
return f"{hours}:{minutes}"
|
||||||
|
|
||||||
|
|
||||||
|
_multidata_cache = {}
|
||||||
|
|
||||||
|
|
||||||
|
def get_static_room_data(room: Room):
|
||||||
|
result = _multidata_cache.get(room.seed.id, None)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
multidata = room.seed.multidata
|
||||||
|
# in > 100 players this can take a bit of time and is the main reason for the cache
|
||||||
|
locations = {tuple(k): tuple(v) for k, v in multidata['locations']}
|
||||||
|
names = multidata["names"]
|
||||||
|
_multidata_cache[room.seed.id] = locations, names
|
||||||
|
return locations, names
|
||||||
|
|
||||||
|
|
||||||
@app.route('/tracker/<uuid:tracker>')
|
@app.route('/tracker/<uuid:tracker>')
|
||||||
@cache.memoize(timeout=30) # update every 30 seconds
|
@cache.memoize(timeout=30) # update every 30 seconds
|
||||||
def get_tracker(tracker: UUID):
|
def get_tracker(tracker: UUID):
|
||||||
room = Room.get(tracker=tracker)
|
room = Room.get(tracker=tracker)
|
||||||
if not room:
|
if not room:
|
||||||
abort(404)
|
abort(404)
|
||||||
multidata = room.seed.multidata
|
locations, names = get_static_room_data(room)
|
||||||
locations = {tuple(k): tuple(v) for k, v in multidata['locations']}
|
|
||||||
|
|
||||||
inventory = {teamnumber: {playernumber: collections.Counter() for playernumber in range(1, len(team) + 1)}
|
inventory = {teamnumber: {playernumber: collections.Counter() for playernumber in range(1, len(team) + 1)}
|
||||||
for teamnumber, team in enumerate(multidata["names"])}
|
for teamnumber, team in enumerate(names)}
|
||||||
|
|
||||||
checks_done = {teamnumber: {playernumber: {loc_name: 0 for loc_name in default_locations}
|
checks_done = {teamnumber: {playernumber: {loc_name: 0 for loc_name in default_locations}
|
||||||
for playernumber in range(1, len(team) + 1)}
|
for playernumber in range(1, len(team) + 1)}
|
||||||
for teamnumber, team in enumerate(multidata["names"])}
|
for teamnumber, team in enumerate(names)}
|
||||||
precollected_items = room.seed.multidata.get("precollected_items", None)
|
precollected_items = room.seed.multidata.get("precollected_items", None)
|
||||||
|
|
||||||
for (team, player), locations_checked in room.multisave.get("location_checks", {}):
|
for (team, player), locations_checked in room.multisave.get("location_checks", {}):
|
||||||
|
@ -230,7 +244,7 @@ def get_tracker(tracker: UUID):
|
||||||
activity_timers[team, player] = now - datetime.datetime.utcfromtimestamp(timestamp)
|
activity_timers[team, player] = now - datetime.datetime.utcfromtimestamp(timestamp)
|
||||||
|
|
||||||
player_names = {}
|
player_names = {}
|
||||||
for team, names in enumerate(multidata['names']):
|
for team, names in enumerate(names):
|
||||||
for player, name in enumerate(names, 1):
|
for player, name in enumerate(names, 1):
|
||||||
player_names[(team, player)] = name
|
player_names[(team, player)] = name
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue