Create upload pending state

pull/155/head
Mike Lang 5 years ago
parent 4b04f70b6f
commit c580671da2

@ -40,6 +40,9 @@ finalizing the upload to make it official. If a cutter dies and leaves an event
it is indeterminate whether the upload actually occurred - in this unlikely scenario, an operator it is indeterminate whether the upload actually occurred - in this unlikely scenario, an operator
should manually inspect things and decide on further action. should manually inspect things and decide on further action.
* `MANUAL_UPLOAD`: A hack because youtube APIs aren't usable. An event for which a video has been
created but not uploaded. It must be uploaded manually, at which point it will be moved to transcoding.
* `TRANSCODING`: An event which has been succesfully uploaded, but is not yet ready for public consumption. * `TRANSCODING`: An event which has been succesfully uploaded, but is not yet ready for public consumption.
The upload is no longer cancellable. If further re-edits need to be applied, The upload is no longer cancellable. If further re-edits need to be applied,
an operator should manually delete or unlist the video then set the state back to `UNEDITED`. an operator should manually delete or unlist the video then set the state back to `UNEDITED`.
@ -76,16 +79,23 @@ we are certain the upload didn't actually go through, and the cut can be immedia
* `FINALIZING -> UNEDITED`: When the finalization failed with an unknown error, * `FINALIZING -> UNEDITED`: When the finalization failed with an unknown error,
we are certain the upload didn't actually go through, and operator intervention is required. we are certain the upload didn't actually go through, and operator intervention is required.
* `FINALIZING -> UPLOAD_PENDING`: When you cannot use the youtube API, and need to designate
the video for manual uploading, or to be uploaded later.
* `FINALIZING -> TRANSCODING`: When the cutter has successfully finalized the upload, * `FINALIZING -> TRANSCODING`: When the cutter has successfully finalized the upload,
but the upload location requires further processing before the video is done. but the upload location requires further processing before the video is done.
* `FINALIZING -> DONE`: When the cutter has successfully finalized the upload, * `FINALIZING -> DONE`: When the cutter has successfully finalized the upload,
and the upload location requires no further processing. and the upload location requires no further processing.
* `UPLOAD_PENDING -> TRANSCODING`: When an operator has uploaded the video.
* `TRANSCODING -> DONE`: When any cutter detects that the upload location is finished * `TRANSCODING -> DONE`: When any cutter detects that the upload location is finished
transcoding the video, and it is ready for public consumption. transcoding the video, and it is ready for public consumption.
This is summarised in the below graph: * Missing some states here around rollbacks of upload pending
This is summarised in the below graph: (missing `UPLOAD_PENDING`)
``` ```
retry retry

@ -19,7 +19,7 @@ from common.database import DBManager, query
from common.segments import get_best_segments, fast_cut_segments, full_cut_segments, ContainsHoles from common.segments import get_best_segments, fast_cut_segments, full_cut_segments, ContainsHoles
from common.stats import timed from common.stats import timed
from .upload_backends import Youtube, Local, UploadError from .upload_backends import Youtube, Local, Manual, UploadError
videos_uploaded = prom.Counter( videos_uploaded = prom.Counter(
@ -443,12 +443,17 @@ class Cutter(object):
gevent.sleep(self.RETRYABLE_UPLOAD_ERROR_WAIT_INTERVAL) gevent.sleep(self.RETRYABLE_UPLOAD_ERROR_WAIT_INTERVAL)
return return
# Success! Set TRANSCODING or DONE and clear any previous error. # Success! Set UPLOAD_PENDING, TRANSCODING or DONE and clear any previous error.
success_state = 'TRANSCODING' if upload_backend.needs_transcode else 'DONE' if upload_backend.needs_manual_upload:
success_state = 'UPLOAD_PENDING'
elif upload_backend.needs_transcode:
success_state = 'TRANSCODING'
else:
success_state = 'DONE'
maybe_upload_time = {"upload_time": datetime.datetime.utcnow()} if success_state == 'DONE' else {} maybe_upload_time = {"upload_time": datetime.datetime.utcnow()} if success_state == 'DONE' else {}
set_row(state=success_state, video_id=video_id, video_link=video_link, error=None, **maybe_upload_time) set_row(state=success_state, video_id=video_id, video_link=video_link, error=None, **maybe_upload_time)
self.logger.info("Successfully cut and uploaded job {} as {}".format(format_job(job), video_link)) self.logger.info("Successfully cut and put into {} job {} as {}".format(success_state, format_job(job), video_link))
videos_uploaded.labels(video_channel=job.video_channel, videos_uploaded.labels(video_channel=job.video_channel,
video_quality=job.video_quality, video_quality=job.video_quality,
upload_location=job.upload_location).inc() upload_location=job.upload_location).inc()
@ -640,6 +645,8 @@ def main(
backend_type = Youtube backend_type = Youtube
elif backend_type == 'local': elif backend_type == 'local':
backend_type = Local backend_type = Local
elif backend_type == 'manual':
backend_type = Manual
else: else:
raise ValueError("Unknown upload backend type: {!r}".format(backend_type)) raise ValueError("Unknown upload backend type: {!r}".format(backend_type))
backend = backend_type(credentials, **backend_config) backend = backend_type(credentials, **backend_config)

@ -62,6 +62,10 @@ class UploadBackend(object):
If it does, it should also have a method check_status(ids) which takes a If it does, it should also have a method check_status(ids) which takes a
list of video ids and returns a list of the ones who have finished processing. list of video ids and returns a list of the ones who have finished processing.
If the upload backend cannot actually upload the file but needs to leave it
in a state for further manual processing, it should set needs_manual_upload.
This will put the video into the UPLOAD_PENDING state.
The upload backend also determines the encoding settings for the cutting The upload backend also determines the encoding settings for the cutting
process, this is given as a list of ffmpeg args process, this is given as a list of ffmpeg args
under the 'encoding_settings' attribute. under the 'encoding_settings' attribute.
@ -73,6 +77,7 @@ class UploadBackend(object):
""" """
needs_transcode = False needs_transcode = False
needs_manual_upload = False
# reasonable default if settings don't otherwise matter: # reasonable default if settings don't otherwise matter:
# high-quality mpegts, without wasting too much cpu on encoding # high-quality mpegts, without wasting too much cpu on encoding
@ -250,3 +255,7 @@ class Local(UploadBackend):
else: else:
url = 'file://{}'.format(filepath) url = 'file://{}'.format(filepath)
return video_id, url return video_id, url
class Manual(Local):
needs_manual_upload = True

@ -42,6 +42,7 @@ CREATE TYPE event_state as ENUM (
'EDITED', 'EDITED',
'CLAIMED', 'CLAIMED',
'FINALIZING', 'FINALIZING',
'UPLOAD_PENDING',
'TRANSCODING', 'TRANSCODING',
'DONE' 'DONE'
); );

Loading…
Cancel
Save