fix(reader): the Takeout import holds up under abuse, races and a run it cannot see
- Uploads: one at a time per user and ten an hour, each refused only after its body arrived; the history read an entry at a time (32 MiB cap), a Watch later list capped at YouTube's 5000, a user's kept videos at 200k; any unreadable shape is a 422, not a 500. - Quota: Watch later lookups stop at the backfill reserve and at a per-user daily share; what is not asked about waits, known videos still go in, and the shorts job retries the rest. - Staging and settling share one per-user advisory lock (no deadlock); a run settles only the rows it read, so a row staged meanwhile is never called gone. - A failed run's notice names a translated failure, never the upstream's text. - The status says when an import is queued; the page watches it to its end even when left, then reads the feed, its counts and the playlists again. - Settings: one live region, the zone kept (unavailable) while a run goes, focus handed back, a missed drop kept from the browser, an oversize file refused before it is sent. - Scheduler and run lists show Takeout runs by the importing user.
This commit is contained in:
@@ -164,12 +164,26 @@ export interface TakeoutUpload {
|
||||
other: number;
|
||||
malformed: number;
|
||||
}
|
||||
export type TakeoutKind = "watched" | "watch_later";
|
||||
// A kept video's outcome (`reader.models.TakeoutOutcome`), or "waiting" while the catalog does not
|
||||
// know it yet: watched / kept (the user's own state here stood) / short for the history; added /
|
||||
// present / missing for Watch later.
|
||||
export type TakeoutCounts = Partial<Record<string, number>>;
|
||||
// The two files (`reader.models.TakeoutKind`) and a kept video's outcome (`TakeoutOutcome`): watched
|
||||
// / kept (the user's own state here stood) / short for the history; added / present / missing for
|
||||
// Watch later. backendIds.contract.test holds both lists to the backend's enums.
|
||||
export const TAKEOUT_KINDS = ["watched", "watch_later"] as const;
|
||||
export const TAKEOUT_OUTCOMES = [
|
||||
"watched",
|
||||
"kept",
|
||||
"short",
|
||||
"added",
|
||||
"present",
|
||||
"missing",
|
||||
] as const;
|
||||
export type TakeoutKind = (typeof TAKEOUT_KINDS)[number];
|
||||
// Each outcome's count, and "waiting" for the videos the import could not settle yet.
|
||||
export type TakeoutCounts = Partial<Record<(typeof TAKEOUT_OUTCOMES)[number] | "waiting", number>>;
|
||||
export interface TakeoutStatus {
|
||||
/** An import is queued and its run not started: `run` is still the one before it. */
|
||||
queued: boolean;
|
||||
/** The largest file the upload takes. */
|
||||
max_bytes: number;
|
||||
run: {
|
||||
status: RunStatus;
|
||||
started_at: string | null;
|
||||
|
||||
Reference in New Issue
Block a user