good old threading ruining my day part 100

This commit is contained in:
cmyui 2019-02-16 13:23:12 -05:00
parent e0c6feefde
commit 3d0fa3ac43
3 changed files with 105 additions and 23 deletions

View File

@ -15,8 +15,10 @@ class handler(requestsManager.asyncRequestHandler):
@tornado.gen.engine
@sentry.captureTornado
def asyncGet(self, replayID):
fullReplay = replayHelper.buildFullReplay(scoreID=replayID, relax=0 if replayID > 500000000 else 1)
try:
fullReplay = replayHelper.buildFullReplay(scoreID=replayID)
except (exceptions.fileNotFoundException, exceptions.scoreNotFoundError):
fullReplay = replayHelper.rxbuildFullReplay(scoreID=replayID)
self.write(fullReplay)
self.add_header("Content-type", "application/octet-stream")

View File

@ -137,7 +137,7 @@ class handler(requestsManager.asyncRequestHandler):
log.debug("Beatmap is not submitted/outdated/unknown. Score submission aborted.")
return
# Increment user playtime
# increment user playtime
length = 0
if s.passed:
try:
@ -283,24 +283,40 @@ class handler(requestsManager.asyncRequestHandler):
# Send to cono ALL passed replays, even non high-scores
if glob.conf.config["cono"]["enable"]:
if isRelaxing:
threading.Thread(target=lambda: glob.redis.publish(
"cono:analyze", json.dumps({
"score_id": s.scoreID,
"beatmap_id": beatmapInfo.beatmapID,
"user_id": s.playerUserID,
"game_mode": s.gameMode,
"pp": s.pp,
"replay_data": base64.b64encode(
replayHelper.rxbuildFullReplay(
s.scoreID,
rawReplay=self.request.files["score"][0]["body"]
)
).decode(),
})
)).start()
else:
# We run this in a separate thread to avoid slowing down scores submission,
# as cono needs a full replay
threading.Thread(target=lambda: glob.redis.publish(
"cono:analyze", json.dumps({
"score_id": s.scoreID,
"beatmap_id": beatmapInfo.beatmapID,
"user_id": s.playerUserID,
"game_mode": s.gameMode,
"pp": s.pp,
"replay_data": base64.b64encode(
replayHelper.buildFullReplay(
s.scoreID,
rawReplay=self.request.files["score"][0]["body"],
relax=1 if isRelaxing else 0
)
).decode(),
})
)).start()
threading.Thread(target=lambda: glob.redis.publish(
"cono:analyze", json.dumps({
"score_id": s.scoreID,
"beatmap_id": beatmapInfo.beatmapID,
"user_id": s.playerUserID,
"game_mode": s.gameMode,
"pp": s.pp,
"replay_data": base64.b64encode(
replayHelper.buildFullReplay(
s.scoreID,
rawReplay=self.request.files["score"][0]["body"]
)
).decode(),
})
)).start()
else:
# Restrict if no replay was provided
if not restricted:

View File

@ -5,16 +5,80 @@ from constants import exceptions, dataTypes
from helpers import binaryHelper
from objects import glob
def buildFullReplay(scoreID=None, scoreData=None, rawReplay=None, relax=3):
def rxbuildFullReplay(scoreID=None, scoreData=None, rawReplay=None):
if all(v is None for v in (scoreID, scoreData)) or all(v is not None for v in (scoreID, scoreData)):
raise AttributeError("Either scoreID or scoreData must be provided, not neither or both")
if relax == 3:
raise AttributeError("Not specified whether the replay is relax or regular. WILL NOT BUILD REPLAY!")
if scoreData is None:
scoreData = glob.db.fetch(
"SELECT scores_relax.*, users.username FROM scores_relax LEFT JOIN users ON scores_relax.userid = users.id "
"WHERE scores_relax.id = %s",
[scoreID]
)
else:
scoreID = scoreData["id"]
if scoreData is None or scoreID is None:
raise exceptions.scoreNotFoundError()
if rawReplay is None:
# Make sure raw replay exists
fileName = ".data/replays/replay_{}.osr".format(scoreID)
if not os.path.isfile(fileName):
raise FileNotFoundError()
# Read raw replay
with open(fileName, "rb") as f:
rawReplay = f.read()
# Calculate missing replay data
rank = generalUtils.getRank(int(scoreData["play_mode"]), int(scoreData["mods"]), int(scoreData["accuracy"]),
int(scoreData["300_count"]), int(scoreData["100_count"]), int(scoreData["50_count"]),
int(scoreData["misses_count"]))
magicHash = generalUtils.stringMd5(
"{}p{}o{}o{}t{}a{}r{}e{}y{}o{}u{}{}{}".format(int(scoreData["100_count"]) + int(scoreData["300_count"]),
scoreData["50_count"], scoreData["gekis_count"],
scoreData["katus_count"], scoreData["misses_count"],
scoreData["beatmap_md5"], scoreData["max_combo"],
"True" if int(scoreData["full_combo"]) == 1 else "False",
scoreData["username"], scoreData["score"], rank,
scoreData["mods"], "True"))
# Add headers (convert to full replay)
fullReplay = binaryHelper.binaryWrite([
[scoreData["play_mode"], dataTypes.byte],
[20150414, dataTypes.uInt32],
[scoreData["beatmap_md5"], dataTypes.string],
[scoreData["username"], dataTypes.string],
[magicHash, dataTypes.string],
[scoreData["300_count"], dataTypes.uInt16],
[scoreData["100_count"], dataTypes.uInt16],
[scoreData["50_count"], dataTypes.uInt16],
[scoreData["gekis_count"], dataTypes.uInt16],
[scoreData["katus_count"], dataTypes.uInt16],
[scoreData["misses_count"], dataTypes.uInt16],
[scoreData["score"], dataTypes.uInt32],
[scoreData["max_combo"], dataTypes.uInt16],
[scoreData["full_combo"], dataTypes.byte],
[scoreData["mods"], dataTypes.uInt32],
[0, dataTypes.byte],
[0, dataTypes.uInt64],
[rawReplay, dataTypes.rawReplay],
[0, dataTypes.uInt32],
[0, dataTypes.uInt32],
])
# Return full replay
return fullReplay
def buildFullReplay(scoreID=None, scoreData=None, rawReplay=None):
if all(v is None for v in (scoreID, scoreData)) or all(v is not None for v in (scoreID, scoreData)):
raise AttributeError("Either scoreID or scoreData must be provided, not neither or both")
if scoreData is None:
scoreData = glob.db.fetch(
"SELECT scores{relax}.*, users.username FROM scores LEFT JOIN users ON scores{relax}.userid = users.id WHERE scores{relax}.id = {scoreID}".format(scoreID=scoreID, relax="_relax" if relax == 1 else ""))
"SELECT scores.*, users.username FROM scores LEFT JOIN users ON scores.userid = users.id "
"WHERE scores.id = %s",
[scoreID]
)
else:
scoreID = scoreData["id"]
if scoreData is None or scoreID is None: