From 4bad338270c872bcdcb6fdd39ef7f7a6dc046b07 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 4 Dec 2023 04:47:59 -0500 Subject: [PATCH] Moderation panel to kill generic jobs --- packages/components/src/api/ApiConfig.ts | 5 + .../src/api/moderation/queues/KillJobs.ts | 54 +++++ .../fakeyou.com/src/v2/view/PageContainer.tsx | 7 + .../job_control/ModerationJobControlPage.tsx | 205 ++++++++++++++++++ .../moderation_main/ModerationFc.tsx | 11 +- 5 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 packages/components/src/api/moderation/queues/KillJobs.ts create mode 100644 packages/fakeyou.com/src/v2/view/pages/moderation/job_control/ModerationJobControlPage.tsx diff --git a/packages/components/src/api/ApiConfig.ts b/packages/components/src/api/ApiConfig.ts index 34b1f4e544..d548b60bd9 100644 --- a/packages/components/src/api/ApiConfig.ts +++ b/packages/components/src/api/ApiConfig.ts @@ -70,6 +70,7 @@ class ApiConfig { break; case "dev.fakeyou.com:7000": case "dev.fakeyou.com:7001": + case "dev.fakeyou.com:7002": // NB: for dev machines without nginx proxies apiHost = "api.dev.fakeyou.com:12345"; useSsl = false; @@ -390,6 +391,10 @@ class ApiConfig { return `${this.getApiOrigin()}/moderation/jobs/kill_tts_inference_jobs`; } + killJobs(): string { + return `${this.getApiOrigin()}/moderation/jobs/kill_generic`; + } + getW2lInferenceStats(): string { return `${this.getApiOrigin()}/moderation/jobs/w2l_inference_queue_stats`; } diff --git a/packages/components/src/api/moderation/queues/KillJobs.ts b/packages/components/src/api/moderation/queues/KillJobs.ts new file mode 100644 index 0000000000..ed1d44fd0a --- /dev/null +++ b/packages/components/src/api/moderation/queues/KillJobs.ts @@ -0,0 +1,54 @@ + +import { ApiConfig } from "@storyteller/components"; + +export interface KillJobsRequest { + job_statuses: string[], +} + +export interface KillJobsSuccessResponse { + success: boolean, +} + +export interface KillJobsErrorResponse { + success: boolean, +} + +type KillJobsResponse = KillJobsSuccessResponse | KillJobsErrorResponse; + +export function KillJobsIsSuccess(response: KillJobsResponse): response is KillJobsSuccessResponse { + return response?.success === true; +} + +export function KillJobsIsError(response: KillJobsResponse): response is KillJobsErrorResponse { + return response?.success === false; +} + +export async function KillJobs(request: KillJobsRequest) : Promise +{ + const endpoint = new ApiConfig().killJobs(); + + return await fetch(endpoint, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + credentials: 'include', + body: JSON.stringify(request), + }) + .then(res => res.json()) + .then(res => { + if (!res) { + return { success : false }; + } + + if (res && 'success' in res) { + return res; + } else { + return { success : false }; + } + }) + .catch(e => { + return { success : false }; + }); +} diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 2dfba77c17..932214a27b 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -97,6 +97,7 @@ import { PasswordResetEmailPage } from "./pages/password_reset/PasswordResetEmai import { PasswordResetVerificationPage } from "./pages/password_reset/PasswordResetVerificationPage"; import { NewProfilePage } from "./pages/profile/profile_view/NewProfilePage"; import { ProfilePage } from "./pages/profile/profile_view/ProfilePage"; +import { ModerationJobControlPage } from "./pages/moderation/job_control/ModerationJobControlPage"; interface Props { sessionWrapper: SessionWrapper; @@ -530,6 +531,12 @@ class PageContainer extends React.Component< /> + + + + (true); + const [killFailedJobs, setKillFailedJobs] = useState(true); + const [killStartedJobs, setKillStartedJobs] = useState(true); + const [priorityLevel, setPriorityLevel] = useState(0); + const [target, setTarget] = useState('all_jobs'); + + const killJobs= async () => { + let jobStatuses = []; + + if (killPendingJobs) { jobStatuses.push('pending') } + if (killFailedJobs) { jobStatuses.push('failed') } + if (killStartedJobs) { jobStatuses.push('started') } + + // NB: The backend uses parameterized enums, so the request shape here is unusual + let requestTarget: any = 'all_jobs'; + + switch (target) { + case 'all_jobs': + break; + case 'lipsync_animation': + case 'text_to_speech': + case 'voice_conversion': + requestTarget = { 'category': target }; + break; + case 'rvc_v2': + case 'so_vits_svc': + case 'tt2': + requestTarget = { 'model_type': target }; + break; + } + + const request = { + job_statuses: jobStatuses, + target: requestTarget, + maybe_priority_or_lower: priorityLevel, + }; + + await KillJobs(request); + }; + + const checkboxEventStatus = ( + ev: React.FormEvent + ) : boolean => { + return (ev.target as HTMLInputElement).checked; + } + + const handlePriorityChange = (ev: React.FormEvent) => { + const level = (ev.target as HTMLInputElement).value; + let numericLevel = parseInt(level.trim()); + if (isNaN(numericLevel)) { + numericLevel = 0; + } else if (numericLevel < 0) { + numericLevel = 0; + } + setPriorityLevel(numericLevel); + }; + + const handleTargetChange = (ev: React.FormEvent) => { + const value = (ev.target as HTMLSelectElement).value; + setTarget(value); + }; + + if (!props.sessionWrapper.canBanUsers()) { + return

Unauthorized

; + } + + return ( +
+
+

Job Stats

+
+ +
+
+ +
+
+

Kill Jobs (Danger Zone)

+
(Only do this in emergencies!)
+ +
Job Types / Categories
+ +
+ + +
+ +
+
+
+ +
Job Statuses
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
Job Priorities
+ +
+ +
+ +
+
+
eg. setting this to "3" will kill all priorities 3 and below (3, 2, 1, and 0).
+
+
    +
  • Level 0 = logged out
  • +
  • Level 1 = free account
  • +
  • Level 2+ = premium or loyalty user
  • +
+
+
Try not to kill premium user workloads unless things get bad.
+
+ +
+
+ + +
+
+
+
+ +
+ +
+
+ ); +} + +export { ModerationJobControlPage }; diff --git a/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationFc.tsx b/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationFc.tsx index 46ce673e69..1c7acdd949 100644 --- a/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationFc.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/moderation/moderation_main/ModerationFc.tsx @@ -38,12 +38,21 @@ function ModerationFc(props: Props) { IP Bans + + + + Job Control (New) + + - Job Stats + Job Stats (Old TTS + W2L)