mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-25 18:49:38 +00:00
356 lines
16 KiB
SQL
356 lines
16 KiB
SQL
-- noinspection SqlDialectInspectionForFile
|
|
-- noinspection SqlNoDataSourceInspectionForFile
|
|
-- noinspection SqlResolveForFile
|
|
|
|
CREATE TABLE generic_inference_jobs (
|
|
|
|
-- Not used for anything except replication.
|
|
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
|
|
|
-- Effective "primary key" (PUBLIC)
|
|
-- This is so the in-progress results can be looked up by the UI.
|
|
token VARCHAR(32) NOT NULL,
|
|
|
|
-- Idempotency token from client
|
|
-- This is so the frontend client doesn't submit duplicate jobs.
|
|
uuid_idempotency_token VARCHAR(36) NOT NULL,
|
|
|
|
-- ========== INFERENCE DETAILS ==========
|
|
|
|
-- There is an index on this column.
|
|
-- The new enum for the type of job, which will eventually replace `inference_category` and `maybe_model_type`.
|
|
-- This isn't fully supported yet in the inference-job, but we'll start populating it and adding logic around it.
|
|
-- We'll start this out as nullable, then migrate the old rows with a default column value.
|
|
--
|
|
-- Fal jobs have the type `fal_queue`.
|
|
job_type VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- There is an index on this column.
|
|
-- This is a user-facing and analytics-facing column that describes what product area the job
|
|
-- is attributed to. For example, this will help us separate "video style transfer" from
|
|
-- "storyteller studio" and also separate "live portrait" from "webcam live portrait".
|
|
product_category VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- There is an index on this column.
|
|
-- NB: This is becoming a problematic field and is becoming conflated with `maybe_model_type`.
|
|
-- We're using this to handle job dispatching, but the latter is being used to load container
|
|
-- dependencies at startup (even if it isn't a real model type or a polymorphic foreign key).
|
|
-- This is pretty gross and horrible.
|
|
--
|
|
-- Broad category of inference
|
|
-- Examples (may not be up to date):
|
|
-- * text_to_speech
|
|
-- * voice_conversion
|
|
-- * image_generation
|
|
-- * video_generation
|
|
-- * background_removal
|
|
inference_category VARCHAR(32) NOT NULL,
|
|
|
|
-- Enum: InferenceJobExternalThirdParty
|
|
-- If the job is externally enqueued, this is the third-party service
|
|
-- responsible for the job. Typically, we won't run an inference job for
|
|
-- jobs being run on a third party.
|
|
maybe_external_third_party VARCHAR(16) DEFAULT NULL,
|
|
|
|
-- If the job is externally enqueued, this is the ID the third-party
|
|
-- service uses.
|
|
maybe_external_third_party_id VARCHAR(64) DEFAULT NULL,
|
|
|
|
-- What the third-party service charges us for the job, in the service's
|
|
-- own credit denomination (if it bills in credits).
|
|
maybe_external_third_party_cost_credits INT(10) UNSIGNED DEFAULT NULL,
|
|
|
|
-- What the third-party service charges us for the job, in USD cents.
|
|
maybe_external_third_party_cost_usd_cents INT(10) UNSIGNED DEFAULT NULL,
|
|
|
|
-- What we charge the user for the job, in our own credits.
|
|
maybe_system_cost_credits INT(10) UNSIGNED DEFAULT NULL,
|
|
|
|
-- What we charge the user for the job, in USD cents.
|
|
maybe_system_cost_usd_cents INT(10) UNSIGNED DEFAULT NULL,
|
|
|
|
-- There is an index on this column.
|
|
-- NB: See notes on inference_category. This is becoming a problematic field. We're using
|
|
-- this to load the container spin-up arguments and dependencies, but the former is being
|
|
-- used to dispatch the job. `inference_category` is the one that should probably go away,
|
|
-- and this column should be renamed to `inference_job_type`.
|
|
--
|
|
-- Potential part of the composite foreign key to the primary model being used, if any.
|
|
-- This will normally live in `maybe_inference_args`, but in this case, it's useful for
|
|
-- running easy database analytical queries.
|
|
--
|
|
-- Examples (may not be up to date):
|
|
-- * rvc_v2
|
|
-- * so_vits_svc
|
|
-- * tacotron2
|
|
-- * vits
|
|
maybe_model_type VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- There is an index on this column.
|
|
-- Potential part of the composite foreign key to the primary model being used, if any.
|
|
-- This will normally live in `maybe_inference_args`, but in this case, it's useful for
|
|
-- running easy database analytical queries.
|
|
maybe_model_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- If the inference job takes some other kind of entity, this will be the token
|
|
-- Not all inference jobs have record-like input sources.
|
|
maybe_input_source_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- If the inference job takes some other kind of entity, this will be the type of the
|
|
-- token. For now, this is just `media_upload`.
|
|
-- Not all inference jobs have record-like input sources.
|
|
maybe_input_source_token_type VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- Polymorphic arguments payload that depends on the type of inference job.
|
|
-- TEXT = 65,535 bytes (64 KiB), ~= 4 bytes per UTF-8 character, ~ 16383 characters.
|
|
maybe_inference_args TEXT DEFAULT NULL,
|
|
|
|
-- For text-based workloads, the raw, unprocessed user input.
|
|
-- TEXT = 65,535 bytes (64 KiB), ~= 4 bytes per UTF-8 character, ~ 16383 characters.
|
|
maybe_raw_inference_text TEXT DEFAULT NULL,
|
|
|
|
-- For download-related jobs, this is the URL
|
|
-- This is nullable because not all inference jobs have a download URL.
|
|
-- The length of 1024 is arbitrary, but we shouldn't need anything longer.
|
|
maybe_download_url VARCHAR(1024) DEFAULT NULL,
|
|
|
|
-- For download-related jobs, this is the cover image to set.
|
|
-- This is nullable because not all inference jobs have a download URL.
|
|
-- And furthermore, not all download URLs have a cover image.
|
|
maybe_cover_image_media_file_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- If we pre-constructed a prompt, this will be copied to the resultant media generated.
|
|
-- This is especially important for Fal-related jobs and endpoints. We need this for keeping
|
|
-- track of all the prompt details, context images, etc.
|
|
maybe_prompt_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- A migration flag we can control from the backend API service which will tell
|
|
-- the worker where to store the results. If false, GCP. If true, AWS.
|
|
store_in_aws BOOLEAN NOT NULL DEFAULT FALSE,
|
|
|
|
-- ========== SUCCESS CASE ==========
|
|
|
|
-- The type of the object will vary based on the type of the upload,
|
|
-- and we may include heuristics that auto-detect types in the future
|
|
on_success_result_entity_type VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- If the job completes successfully, this is the result token.
|
|
-- This is only populated on a successful result.
|
|
on_success_result_entity_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- If the job completes successfully, this is the batch token (ie. when
|
|
-- several results are created).
|
|
-- Only populated if there are actual batches generated.
|
|
on_success_result_batch_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- ========== CREATOR DETAILS AND PREFERENCES ==========
|
|
|
|
-- Foreign key to user
|
|
maybe_creator_user_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- Based on a cookie sent by the frontend.
|
|
-- We'll save this even if the user is logged in.
|
|
maybe_creator_anonymous_visitor_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- For abuse tracking.
|
|
-- Wide enough for IPv4/6
|
|
creator_ip_address VARCHAR(40) NOT NULL,
|
|
|
|
-- The creator can set a desired visibility for their data.
|
|
-- This does not always apply to every upload type.
|
|
-- Additionally, some upload types may require moderator approval prior
|
|
-- to being publicly listed, and this field has no bearing on that.
|
|
-- NB: DO NOT CHANGE THE ORDER OF THE ENUM VALUES DURING SCHEMA MIGRATIONS.
|
|
creator_set_visibility ENUM(
|
|
'public',
|
|
'hidden',
|
|
'private'
|
|
) NOT NULL DEFAULT 'public',
|
|
|
|
-- ========== PREMIUM FEATURES METADATA ==========
|
|
|
|
-- The maximum duration for generated audio or video in seconds.
|
|
-- Zero is implied to be the default value, which is typically 12 seconds.
|
|
-- A negative value implies "unlimited".
|
|
max_duration_seconds INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- ========== WORKLOAD SOURCE AND PRIORITY ==========
|
|
|
|
-- Priority *increases*, so a level of 2 will be higher than 1.
|
|
-- These are the level semantics currently:
|
|
-- - All jobs from anonymous FakeYou users have level 0.
|
|
-- - All jobs from logged in FakeYou users have level 1.
|
|
-- - All jobs from Twitch TTS (unpaid) have level 10 (ten).
|
|
-- - (There will be future levels for paid Twitch and social FakeYou rewards.)
|
|
priority_level SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
|
|
|
-- For non-premium workloads (or some other workloads), we may require that the
|
|
-- user remains on the website. This will help us kill jobs if the user leaves.
|
|
-- The state for this keepalive signal will be job-type dependent and may live
|
|
-- in Redis or some other system. Typically the frontend job status polling will
|
|
-- populate this keepalive signal (eg. in a Redis key with TTL).
|
|
is_keepalive_required BOOLEAN NOT NULL DEFAULT FALSE,
|
|
|
|
-- TODO: add is_for_storyteller_product
|
|
is_from_premium_user BOOLEAN NOT NULL DEFAULT FALSE,
|
|
is_from_api_user BOOLEAN NOT NULL DEFAULT FALSE,
|
|
is_for_twitch BOOLEAN NOT NULL DEFAULT FALSE,
|
|
|
|
-- If credits were spent for this job, this references the corresponding wallet ledger entry.
|
|
maybe_wallet_ledger_entry_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- ========== DEVELOPMENT AND DEBUGGING METADATA ==========
|
|
|
|
-- If true, the request gets a "debug" flag, which may do different
|
|
-- things depending on the type of work. This doesn't really have any
|
|
-- specific meaning -- it can be used to flag for anything -- but should
|
|
-- typically be used for one-off debugging and not a part of the normal
|
|
-- product surface area. Contrast this with `maybe_routing_tag`, which
|
|
-- forces the job onto a specific physical server: this might be a flag
|
|
-- deployed to handle debugging across the entire fleet.
|
|
is_debug_request BOOLEAN NOT NULL DEFAULT FALSE,
|
|
|
|
-- If set, the request gets processed by a special "tagged" worker
|
|
-- that matches this tag. The ordinary workers will ignore this work.
|
|
-- The tag is typically added via a special HTTP header when the work
|
|
-- is enqueued. In practice, this means we can canary deploy or cordon
|
|
-- off special workers to handle certain jobs.
|
|
maybe_routing_tag VARCHAR(64) DEFAULT NULL,
|
|
|
|
-- Foreign key to the debug_logs table (event_token column).
|
|
-- Multiple debug_logs rows can share the same event token.
|
|
maybe_debug_log_event_token VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- The platform the enqueuing request came from ('web', 'desktop_app',
|
|
-- 'curl', 'python_requests', 'postman'),
|
|
-- inferred from the request's User-Agent header.
|
|
platform_type VARCHAR(16) DEFAULT NULL,
|
|
|
|
-- ========== JOB SYSTEM DETAILS ==========
|
|
|
|
-- Jobs begin as "pending", then transition to other states.
|
|
--
|
|
-- * Pending = job is ready to go
|
|
-- * Started = job is running
|
|
-- * Complete_Success = job is done (success)
|
|
-- * Complete_Failure = job is done (permanent failure, eg. a Face Animator job without a face)
|
|
-- * Attempt_Failed = job failed but may retry.
|
|
-- * Dead = job failed permanently (ie. exhausted retries)
|
|
-- * Cancelled_By_User = the user canceled their own job
|
|
-- * Cancelled_By_System = the system terminated the job (ie. load shedding, user account deletion, etc.)
|
|
--
|
|
-- Pending -> Started -> Complete_Success
|
|
-- |-> Complete_Failure
|
|
-- \-> Attempt_Failed -> Started -> { Complete, Failed, Dead }
|
|
status ENUM(
|
|
'pending',
|
|
'started',
|
|
'complete_success',
|
|
'complete_failure',
|
|
'attempt_failed',
|
|
'dead',
|
|
'cancelled_by_user',
|
|
'cancelled_by_system'
|
|
) NOT NULL DEFAULT 'pending',
|
|
|
|
-- We can track this against a "max_attempt_count"
|
|
attempt_count SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
|
|
|
-- If the user chooses to no longer display or poll the job, we mark this flag true.
|
|
-- This should only be set for terminal state (completed or failed) jobs.
|
|
-- We use this flag to remove the job from the user's view.
|
|
is_dismissed_by_user BOOLEAN NOT NULL DEFAULT FALSE,
|
|
|
|
-- If there is a failure, tell the user why.
|
|
-- This isn't localized or very friendly to present to the user.
|
|
failure_reason VARCHAR(512) DEFAULT NULL,
|
|
|
|
-- Optional internal-only debugging information in the case of failure.
|
|
internal_debugging_failure_reason VARCHAR(512) DEFAULT NULL,
|
|
|
|
-- An enum-like key to present the frontend with a failure class in an
|
|
-- i18n-friendly way. The javascript/frontend can use these as indices
|
|
-- into descriptive, broadly-localized error messages.
|
|
--
|
|
-- * 'face_not_detected' for images or videos that do not have a detectable
|
|
-- face (SadTalker, Wav2Lip, etc.)
|
|
--
|
|
-- * 'keep_alive_elapsed' when users walk away from their inference job and
|
|
-- the workload class expects for them to remain
|
|
--
|
|
-- * 'not_yet_implemented' error for developers during feature development
|
|
-- and prototyping. Should ideally never happen in
|
|
-- production
|
|
--
|
|
-- * 'retryable_worker_error' for generic worker errors (full filesystem,
|
|
-- etc.) that can be retried. (We don't need to
|
|
-- tell the user why the job failed.)
|
|
--
|
|
frontend_failure_category VARCHAR(32) DEFAULT NULL,
|
|
|
|
-- On success, we populate how long the job execution took in milliseconds.
|
|
-- We have this because 1) the job system timestamps are second-resolution,
|
|
-- and 2) the structure of the jobs executor may change, potentially changing
|
|
-- derived execution time analytics with it.
|
|
success_execution_millis INT(10) UNSIGNED DEFAULT NULL,
|
|
|
|
-- This is only the inference portion and does not include downloads, uploads,
|
|
-- or any subsequent processing.
|
|
success_inference_execution_millis INT(10) UNSIGNED DEFAULT NULL,
|
|
|
|
-- TODO: Remove once `assigned_worker` column is added
|
|
-- and existing queries for this column are removed.
|
|
-- The last worker (hostname or pod name) to touch the job, either in the case of success or failure.
|
|
last_assigned_worker VARCHAR(255) DEFAULT NULL,
|
|
|
|
-- Worker hostname (linux hostname, k8s pod name)
|
|
-- Assigned when a worker picks up the job
|
|
-- Reassigned if the job fails and gets picked up again
|
|
assigned_worker VARCHAR(128) DEFAULT NULL,
|
|
|
|
-- Cluster name (k8s)
|
|
-- Assigned when a worker picks up the job
|
|
-- Reassigned if the job fails and gets picked up again
|
|
assigned_cluster VARCHAR(128) DEFAULT NULL,
|
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
-- Failed jobs will set a next attempt time.
|
|
-- Subsequent tries can increase the timeout.
|
|
-- Failures because of permissions require human intervention => [retry_at=null].
|
|
-- Failures because of invalid files are dead => [status=dead].
|
|
retry_at TIMESTAMP NULL,
|
|
|
|
-- Set when the job first starts executing
|
|
first_started_at TIMESTAMP NULL,
|
|
|
|
-- Set when the job is successfully completed
|
|
successfully_completed_at TIMESTAMP NULL,
|
|
|
|
-- INDICES --
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY (token),
|
|
UNIQUE KEY (uuid_idempotency_token),
|
|
UNIQUE KEY (maybe_external_third_party, maybe_external_third_party_id),
|
|
KEY index_job_type (job_type),
|
|
KEY index_product_category (product_category),
|
|
KEY index_inference_category (inference_category),
|
|
KEY index_maybe_model_type_and_maybe_model_token (maybe_model_type, maybe_model_token),
|
|
KEY index_maybe_model_type (maybe_model_type),
|
|
KEY index_maybe_external_third_party_id (maybe_external_third_party_id),
|
|
KEY fk_maybe_model_token (maybe_model_token),
|
|
KEY fk_maybe_input_source_token (maybe_input_source_token),
|
|
KEY fk_maybe_input_source_token_and_type (maybe_input_source_token, maybe_input_source_token_type),
|
|
KEY fk_on_success_result_entity_token (on_success_result_entity_token),
|
|
KEY fk_maybe_creator_user_token (maybe_creator_user_token),
|
|
KEY index_maybe_creator_anonymous_visitor_token (maybe_creator_anonymous_visitor_token),
|
|
KEY index_creator_ip_address (creator_ip_address),
|
|
KEY index_priority_level (priority_level),
|
|
KEY index_is_debug_request (is_debug_request),
|
|
KEY index_maybe_routing_tag (maybe_routing_tag),
|
|
KEY index_status (status),
|
|
KEY index_generic_inference_jobs_created_at (created_at)
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|