Merge pull request #101 from ekimekim/mike/cutter/set-error-on-holes

cutter: Set an error message to warn humans when it discards a candidate due to holes
pull/102/head
Mike Lang 5 years ago committed by GitHub
commit 2194e47ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -130,19 +130,9 @@ class Cutter(object):
# Shuffle the list so that (most of the time) we don't try to claim the same one as other nodes # Shuffle the list so that (most of the time) we don't try to claim the same one as other nodes
random.shuffle(candidates) random.shuffle(candidates)
for candidate in candidates: for candidate in candidates:
try:
segments = self.check_candidate(candidate) def set_error(error):
except ContainsHoles: """Common code for the two paths below, for setting an error on the row for humans to see"""
# TODO metric
self.logger.info("Ignoring candidate {} due to holes".format(format_job(candidate)))
continue # bad candidate, let someone else take it or just try again later
except Exception as e:
# Unknown error. This is either a problem with us, or a problem with the candidate
# (or most likely a problem with us that is only triggered by this candidate).
# In this case we would rather stay running so other jobs can continue to work if possible.
# But to give at least some feedback, we set the error message on the job
# if it isn't already.
self.logger.exception("Failed to check candidate {}, setting error on row".format(format_job(candidate)))
try: try:
# Since this error message is just for humans, we don't go to too large # Since this error message is just for humans, we don't go to too large
# a length to prevent it being put on the row if the row has changed. # a length to prevent it being put on the row if the row has changed.
@ -152,7 +142,7 @@ class Cutter(object):
UPDATE events UPDATE events
SET error = %s SET error = %s
WHERE id = %s AND state = 'EDITED' AND error IS NULL WHERE id = %s AND state = 'EDITED' AND error IS NULL
""", id=candidate.id, error='{}: Error while checking candidate: {}'.format(self.name, e)) """, id=candidate.id, error=error)
except Exception: except Exception:
self.logger.exception("Failed to set error for candidate {}, ignoring".format(format_job(candidate))) self.logger.exception("Failed to set error for candidate {}, ignoring".format(format_job(candidate)))
self.refresh_conn() self.refresh_conn()
@ -160,12 +150,37 @@ class Cutter(object):
if result.rowcount > 0: if result.rowcount > 0:
assert result.rowcount == 1 assert result.rowcount == 1
self.logger.info("Set error for candidate {}".format(format_job(candidate))) self.logger.info("Set error for candidate {}".format(format_job(candidate)))
try:
segments = self.check_candidate(candidate)
except ContainsHoles:
# TODO metric
self.logger.info("Ignoring candidate {} due to holes".format(format_job(candidate)))
set_error(
"Node {} does not have all the video needed to cut this row. "
"This may just be because it's too recent and the video hasn't been downloaded yet. "
"However, it might also mean that there is a 'hole' of missing video, perhaps "
"because the stream went down or due to downloader issues. If you know why this "
"is happening and want to cut the video anyway, re-edit with the 'Allow Holes' option set."
.format(self.name))
continue # bad candidate, let someone else take it or just try again later
except Exception as e:
# Unknown error. This is either a problem with us, or a problem with the candidate
# (or most likely a problem with us that is only triggered by this candidate).
# In this case we would rather stay running so other jobs can continue to work if possible.
# But to give at least some feedback, we set the error message on the job
# if it isn't already.
self.logger.exception("Failed to check candidate {}, setting error on row".format(format_job(candidate)))
set_error('{}: Error while checking candidate: {}'.format(self.name, e))
self.wait(self.ERROR_RETRY_INTERVAL) self.wait(self.ERROR_RETRY_INTERVAL)
continue continue
if all(segment is None for segment in segments): if all(segment is None for segment in segments):
self.logger.info("Ignoring candidate {} as we have no segments".format(format_job(candidate))) self.logger.info("Ignoring candidate {} as we have no segments".format(format_job(candidate)))
continue continue
return CutJob(segments=segments, **candidate._asdict()) return CutJob(segments=segments, **candidate._asdict())
# No candidates # No candidates
self.wait(self.NO_CANDIDATES_RETRY_INTERVAL) self.wait(self.NO_CANDIDATES_RETRY_INTERVAL)

Loading…
Cancel
Save