mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-27 04:00:10 -04:00
Compare commits
340
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6430f63702 | ||
|
|
9752f39736 | ||
|
|
a11779e3aa | ||
|
|
523c02326b | ||
|
|
37eef276a0 | ||
|
|
f5cbedb230 | ||
|
|
6994a9c2ce | ||
|
|
213742ff29 | ||
|
|
df4f1e6a6c | ||
|
|
64fa281bc1 | ||
|
|
bd386aa70b | ||
|
|
28875c9272 | ||
|
|
a79bfc7a24 | ||
|
|
ecca8ff17c | ||
|
|
a3cabf6779 | ||
|
|
dd35a7cca9 | ||
|
|
f876cac4cf | ||
|
|
d2b840cb13 | ||
|
|
85bac00194 | ||
|
|
367a516f89 | ||
|
|
5fe85072a2 | ||
|
|
5867d2356c | ||
|
|
275333c1ed | ||
|
|
5ec2cde68f | ||
|
|
daf5a63f86 | ||
|
|
2fe3d5dc99 | ||
|
|
44df952bd1 | ||
|
|
5bf98f70d9 | ||
|
|
af685b37cf | ||
|
|
0f7ff50cf6 | ||
|
|
1ae8d8d615 | ||
|
|
63c0124267 | ||
|
|
17e8c1942e | ||
|
|
cf24a07bba | ||
|
|
9ece30722f | ||
|
|
9ab977d016 | ||
|
|
ebd3f52717 | ||
|
|
35a75e144a | ||
|
|
4b145a7419 | ||
|
|
eb539e9142 | ||
|
|
37604cdd7b | ||
|
|
f724031aa3 | ||
|
|
b8b10f6fc1 | ||
|
|
bd4bcab2c2 | ||
|
|
caa3e3ae53 | ||
|
|
7cd8099ab5 | ||
|
|
6ec39b9c68 | ||
|
|
c8b4b7daa0 | ||
|
|
a294549d02 | ||
|
|
33ff75274f | ||
|
|
945e5226c5 | ||
|
|
85a52cd26e | ||
|
|
32ee4209da | ||
|
|
f94cdac47d | ||
|
|
a2ea870ac7 | ||
|
|
a2c48d7469 | ||
|
|
fe3dd7d66b | ||
|
|
88fae4ba89 | ||
|
|
6505e67bf2 | ||
|
|
3453fe0e3b | ||
|
|
8b36d870d1 | ||
|
|
9555ac51fe | ||
|
|
f00b4011b5 | ||
|
|
d1d208d714 | ||
|
|
a5ce9a3cc4 | ||
|
|
6ad2468e59 | ||
|
|
c59695343f | ||
|
|
52a83609b6 | ||
|
|
f710b68a3e | ||
|
|
3d63e34ca1 | ||
|
|
4a1f1441bf | ||
|
|
ee90f03436 | ||
|
|
1858aea619 | ||
|
|
592ba627be | ||
|
|
f754c6e41f | ||
|
|
54af3d301c | ||
|
|
22eeacf355 | ||
|
|
630aa497f3 | ||
|
|
6e9c05c596 | ||
|
|
3f781ad98f | ||
|
|
5d038fdf8f | ||
|
|
a09acf7c53 | ||
|
|
3ba64618c3 | ||
|
|
73e583c7ed | ||
|
|
1d7a54f640 | ||
|
|
552fae54a7 | ||
|
|
4d2ae85fd9 | ||
|
|
76775dec60 | ||
|
|
22bc8d54a0 | ||
|
|
878bff867a | ||
|
|
05d5bfc1a7 | ||
|
|
3acdd0b5e2 | ||
|
|
1a7a74ee8a | ||
|
|
820f4ebc32 | ||
|
|
423fb369db | ||
|
|
2a58079289 | ||
|
|
b2df674178 | ||
|
|
1fd33e76b4 | ||
|
|
824683b974 | ||
|
|
4bed11d21d | ||
|
|
13bdcbdda6 | ||
|
|
f49c724303 | ||
|
|
a9502c183b | ||
|
|
b469a237ce | ||
|
|
0df93c48c3 | ||
|
|
070c192633 | ||
|
|
75a68c7e0f | ||
|
|
b2db079cf5 | ||
|
|
6658281a1c | ||
|
|
8cb04f1dcb | ||
|
|
58f6ee68df | ||
|
|
d0cef7bec9 | ||
|
|
8eed406fbd | ||
|
|
44586c4cee | ||
|
|
02f5aacb8e | ||
|
|
001ff86ed3 | ||
|
|
94b406eca2 | ||
|
|
f8bdea1b3b | ||
|
|
8a37a7240c | ||
|
|
a4c1abfe9c | ||
|
|
6bb7a18676 | ||
|
|
a8173226ea | ||
|
|
692c3f64b6 | ||
|
|
4842b9bbc1 | ||
|
|
a507f8bc38 | ||
|
|
24f2c07199 | ||
|
|
e871dde078 | ||
|
|
47ff379018 | ||
|
|
cdb0f37889 | ||
|
|
6d7c3c6e5f | ||
|
|
7b72d51bd3 | ||
|
|
11a9e1249c | ||
|
|
f3a6ddb70a | ||
|
|
d2aa07228b | ||
|
|
a2c3668beb | ||
|
|
15d66a4530 | ||
|
|
75523811e4 | ||
|
|
4672102da4 | ||
|
|
ca59189dd9 | ||
|
|
3564c1b459 | ||
|
|
78263e3c49 | ||
|
|
e36fb66e05 | ||
|
|
1540d87018 | ||
|
|
61f0869359 | ||
|
|
d23c7abfeb | ||
|
|
2d59891dee | ||
|
|
2f86bc75ac | ||
|
|
8c5fb0bee2 | ||
|
|
b9f0d7749d | ||
|
|
b2caa3758a | ||
|
|
de656d4d74 | ||
|
|
c803232a52 | ||
|
|
cd9b0080dd | ||
|
|
6885eb5fc9 | ||
|
|
100ad0da35 | ||
|
|
7010d56bc3 | ||
|
|
b34371eef0 | ||
|
|
e6542438b5 | ||
|
|
287e3e5f0c | ||
|
|
8fcb908af9 | ||
|
|
56e84f434f | ||
|
|
925f2d78ae | ||
|
|
90219594bb | ||
|
|
08e8560499 | ||
|
|
9e38b9a2fc | ||
|
|
e9a6320eab | ||
|
|
da05885d7d | ||
|
|
ba9f716ff8 | ||
|
|
2633c5f0ef | ||
|
|
da805b4f1d | ||
|
|
9eb75c7eba | ||
|
|
75607b3c12 | ||
|
|
ce69b1b055 | ||
|
|
9ee7fdbac5 | ||
|
|
67e3ecebc1 | ||
|
|
52db0b7796 | ||
|
|
15fa5a2bee | ||
|
|
32babc99f0 | ||
|
|
bdac796e51 | ||
|
|
18c50af218 | ||
|
|
62cbde94bc | ||
|
|
b2f9b44e96 | ||
|
|
6a48a5372c | ||
|
|
1b0368664a | ||
|
|
6a83524fd9 | ||
|
|
233247f3c0 | ||
|
|
60045a01d0 | ||
|
|
dc5dfd9831 | ||
|
|
7b36fc0b98 | ||
|
|
92e1d10809 | ||
|
|
4a486cedd2 | ||
|
|
004cde84a7 | ||
|
|
61b74500d8 | ||
|
|
8285826ed0 | ||
|
|
03d0110ee6 | ||
|
|
34517fbaff | ||
|
|
839f7885fb | ||
|
|
cee3ffb217 | ||
|
|
90198252b8 | ||
|
|
165130321f | ||
|
|
061c2c7b07 | ||
|
|
413960b6cf | ||
|
|
cc4b7deaa9 | ||
|
|
8229a3cfb3 | ||
|
|
b461c7e8e7 | ||
|
|
c58f23c117 | ||
|
|
048cc26b6b | ||
|
|
9b5508d8c0 | ||
|
|
a81428913d | ||
|
|
756c8e09ae | ||
|
|
5b97360724 | ||
|
|
79ad78bdde | ||
|
|
311299105b | ||
|
|
9dad3a153c | ||
|
|
93157b50c8 | ||
|
|
47fbc1704d | ||
|
|
efba106d3c | ||
|
|
e340eee250 | ||
|
|
73be1bbf05 | ||
|
|
81306d1a56 | ||
|
|
8e341f7a83 | ||
|
|
1978e5e653 | ||
|
|
8eaaad9b55 | ||
|
|
082c284add | ||
|
|
a83e5ff224 | ||
|
|
abaaaf2fdb | ||
|
|
3409689566 | ||
|
|
84c0e42964 | ||
|
|
b848c2b549 | ||
|
|
85abbd8587 | ||
|
|
b844191db7 | ||
|
|
0267a4799d | ||
|
|
c50060b161 | ||
|
|
a508a843bd | ||
|
|
d0bad0c8fb | ||
|
|
d2c99a7bad | ||
|
|
681d923ae0 | ||
|
|
9e563a0640 | ||
|
|
db30096cb9 | ||
|
|
76f9f5a850 | ||
|
|
3a0eafee11 | ||
|
|
9fbecd5568 | ||
|
|
b3dedfc5a8 | ||
|
|
8ded313e7b | ||
|
|
e305928b45 | ||
|
|
db48ee0fd8 | ||
|
|
5beedcb5e3 | ||
|
|
e43feeb700 | ||
|
|
38dc835ff4 | ||
|
|
62b19b2b0e | ||
|
|
b7b92f4419 | ||
|
|
7ee7ff3875 | ||
|
|
29237d3ead | ||
|
|
5afbfc0ec4 | ||
|
|
6e5a2d1789 | ||
|
|
13281ea3b1 | ||
|
|
98f80a68de | ||
|
|
075fcfb81e | ||
|
|
a8c45cfac2 | ||
|
|
f0a4f0a4f7 | ||
|
|
3b78853d7c | ||
|
|
98b6bb34a7 | ||
|
|
4d759719f6 | ||
|
|
ac28ff8a39 | ||
|
|
43a33a00ee | ||
|
|
8bbc490b61 | ||
|
|
168a476b72 | ||
|
|
2cebfbb3fc | ||
|
|
d57e070c8c | ||
|
|
bde6b4d562 | ||
|
|
9cde097d38 | ||
|
|
1d7d1ba194 | ||
|
|
632cf5a710 | ||
|
|
c2e287f6f4 | ||
|
|
844799e30e | ||
|
|
c1bd8ed611 | ||
|
|
1466bca4d7 | ||
|
|
12fdf24028 | ||
|
|
cefb770340 | ||
|
|
e971ea98dc | ||
|
|
9ab8b366e9 | ||
|
|
96563fa345 | ||
|
|
67ab94664c | ||
|
|
99f1226115 | ||
|
|
9c45a17b8d | ||
|
|
2cf5a6f942 | ||
|
|
071928d7bf | ||
|
|
b8442b54ee | ||
|
|
530d891ce9 | ||
|
|
972f119468 | ||
|
|
9004432620 | ||
|
|
81a3bc270b | ||
|
|
84fe5a5762 | ||
|
|
a02934ca4e | ||
|
|
4ddcd43e33 | ||
|
|
37be0174af | ||
|
|
f2e314d168 | ||
|
|
3bd216f00d | ||
|
|
dc5885114d | ||
|
|
47873497b8 | ||
|
|
554766bd2a | ||
|
|
86382bf219 | ||
|
|
59b1e28a14 | ||
|
|
3f88a741c9 | ||
|
|
2efcba5da6 | ||
|
|
b4718a2f13 | ||
|
|
efbb0000f3 | ||
|
|
0280e6b706 | ||
|
|
79d568ee14 | ||
|
|
85630390a0 | ||
|
|
215b727bc1 | ||
|
|
e29c0b4c68 | ||
|
|
c81e6af507 | ||
|
|
98d30917e5 | ||
|
|
e62e409857 | ||
|
|
417137a9a8 | ||
|
|
0da1994f0c | ||
|
|
36d016c3c7 | ||
|
|
b22e978e54 | ||
|
|
c387f47c97 | ||
|
|
1a09676327 | ||
|
|
e516f85e5f | ||
|
|
e16b86d36e | ||
|
|
003a86cd31 | ||
|
|
ebf48e20be | ||
|
|
df2444ddc0 | ||
|
|
6b6a2ceeba | ||
|
|
80da0d9649 | ||
|
|
b8fd0486c7 | ||
|
|
12ffb2ded1 | ||
|
|
f810256b9c | ||
|
|
461030b681 | ||
|
|
a33ff3f060 | ||
|
|
98736324dc | ||
|
|
89a6f36f1a | ||
|
|
ac5bcbdd16 | ||
|
|
7566c0d71c | ||
|
|
0ca007b6e7 | ||
|
|
cbe07e2b3e | ||
|
|
495c01c38c |
@@ -14,10 +14,14 @@ MIGRATION_DIRECTORY=_sql/migrations/
|
||||
# See https://github.com/launchbadge/sqlx/tree/master/sqlx-cli#readme
|
||||
#SQLX_OFFLINE=true
|
||||
|
||||
# We can't serve HTTPS locally without self-signed certificate nonsense.
|
||||
COOKIE_SECURE=false
|
||||
COOKIE_DOMAIN=.jungle.horse
|
||||
WEBSITE_HOMEPAGE_REDIRECT=http://jungle.horse
|
||||
# NB(bt, 2023-03-20):
|
||||
# These are used in storyteller-web, image-generation-service, and websocket-gateway.
|
||||
# I'm moving them to env configs that live under storyteller-web/.env.
|
||||
# This will break the other services for now.
|
||||
# # We can't serve HTTPS locally without self-signed certificate nonsense.
|
||||
# COOKIE_SECURE=false
|
||||
# COOKIE_DOMAIN=.jungle.horse
|
||||
# WEBSITE_HOMEPAGE_REDIRECT=http://jungle.horse
|
||||
|
||||
# Bucket config (non-secret)
|
||||
REGION_NAME=us-east1
|
||||
@@ -71,14 +75,3 @@ TTS_HIFIGAN_SUPERRES_VOCODER_MODEL_FILENAME=hifigan_superres_twilight_33000.pt
|
||||
|
||||
# Development key. Permissible to check in.
|
||||
NEWRELIC_API_KEY=c402be1c4c4216ec83d0cfc0851520cfFFFFNRAL
|
||||
|
||||
# Stripe configs
|
||||
# All secrets are development and okay to check in
|
||||
STRIPE_CHECKOUT_SUCCESS_URL_PATH=/checkout_success
|
||||
STRIPE_CHECKOUT_CANCEL_URL_PATH=/checkout_cancel
|
||||
STRIPE_PORTAL_RETURN_URL_PATH=/portal_success
|
||||
STRIPE_PORTAL_DEFAULT_CONFIG_ID=bpc_1LyPPREU5se17MekYiViZF12
|
||||
# STRIPE_PORTAL_DEFAULT_CONFIG_ID=bpc_1M4jc3EU5se17MekmgdS4dDJ # Production (not a secret)
|
||||
STRIPE_PUBLISHABLE_KEY=pk_test_51KZvWXEU5se17Mekx6e0gw32ovDF78k2eeaGctLIs8oQVxN6DerEp1BDqh6gLMYKli4VsTZoVGHoxq5RmwKMlxtP00r59UEEad
|
||||
STRIPE_SECRET_KEY=sk_test_51KZvWXEU5se17Mek11ZdnWr4frnyw7tWOPuvl3pRzL290zvkT6KqcbGUl3fcvc3hA8oH6lWXz2kGWXXUlNcCuDxB003uVT9JX0
|
||||
STRIPE_SECRET_WEBHOOK_SIGNING_KEY=whsec_40b60bd75768052532b63dbeefa7a1b163e182c3e657fb27fa906ef49a2cd59f
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# Environmental configurations specific to `download-job`.
|
||||
# These are defaulted for dev and are easy to overwrite in production with K8s environment variables.
|
||||
# !! DOES *NOT* CONTAIN SECRETS !!
|
||||
|
||||
WEB_DOWNLOADER_COMMAND=./download_internet_file.py
|
||||
WEB_DOWNLOADER_MAYBE_VENV_SCRIPT=./python/bin/activate
|
||||
WEB_DOWNLOADER_MAYBE_DOCKER_IMAGE=d73f28ce3ff6
|
||||
|
||||
SOFTVC_MODEL_CHECK_ROOT_DIRECTORY=/
|
||||
SOFTVC_MODEL_CHECK_MAYBE_VENV_COMMAND="source python/bin/activate"
|
||||
SOFTVC_MODEL_CHECK_MAYBE_DOCKER_IMAGE=a79106991ce3
|
||||
|
||||
TACOTRON_MODEL_CHECK_ROOT_DIRECTORY=/models/tts
|
||||
TACOTRON_MODEL_CHECK_MAYBE_VENV_COMMAND="source python/bin/activate"
|
||||
TACOTRON_MODEL_CHECK_COMMAND=./vocodes_model_check_tacotron.py
|
||||
TACOTRON_MODEL_CHECK_MAYBE_DOCKER_IMAGE=5642d0fd7fc1
|
||||
|
||||
HIFIGAN_SOFTVC_MODEL_CHECK_ROOT_DIRECTORY=/
|
||||
HIFIGAN_SOFTVC_MODEL_CHECK_MAYBE_VENV_COMMAND="source python/bin/activate"
|
||||
HIFIGAN_SOFTVC_MODEL_CHECK_MAYBE_DOCKER_IMAGE=a79106991ce3
|
||||
|
||||
HIFIGAN_MODEL_CHECK_ROOT_DIRECTORY=/models/tts
|
||||
HIFIGAN_MODEL_CHECK_MAYBE_VENV_COMMAND="source python/bin/activate"
|
||||
HIFIGAN_MODEL_CHECK_COMMAND=./vocodes_model_check_hifigan.py
|
||||
HIFIGAN_MODEL_CHECK_MAYBE_DOCKER_IMAGE=5642d0fd7fc1
|
||||
@@ -2,7 +2,7 @@
|
||||
# https://github.com/actions/starter-workflows/ci/docker-publish.yml
|
||||
# If using base images, don't forget to add READ access, eg. from a package settings page like:
|
||||
# https://github.com/orgs/storytold/packages/container/docker-base-images-rust-ssl/settings/actions_access
|
||||
name: Publish Docker Container to GHCR
|
||||
name: "[CPU] Build GHCR Docker artifact"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -64,6 +64,7 @@ jobs:
|
||||
username: ${{ github.actor }} # username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
image_name: storytold/storyteller-rust
|
||||
dockerfile: service_cpu.Dockerfile
|
||||
# NB: The `git_push_tag: true` option does not work as expected, so we put the sha in `image_tag`:
|
||||
# https://github.com/whoan/docker-build-with-cache-action/issues/72
|
||||
image_tag: latest,${{ github.sha }},${{ steps.vars.outputs.sha_short }}
|
||||
@@ -0,0 +1,113 @@
|
||||
# Adapted from
|
||||
# https://github.com/actions/starter-workflows/ci/docker-publish.yml
|
||||
# If using base images, don't forget to add READ access, eg. from a package settings page like:
|
||||
# https://github.com/orgs/storytold/packages/container/docker-base-images-rust-ssl/settings/actions_access
|
||||
name: "[GPU] Build GHCR Docker artifact"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
# NB: Default-branch doesn't work, despite Github's documentation.
|
||||
#- $default-branch
|
||||
- master
|
||||
env:
|
||||
IMAGE_NAME: storyteller-rust-gpu
|
||||
|
||||
jobs:
|
||||
# Push image to GitHub Packages.
|
||||
# See also https://docs.docker.com/docker-hub/builds/
|
||||
# See also https://depot.dev/blog/docker-layer-caching-in-github-actions
|
||||
# See also https://evilmartians.com/chronicles/build-images-on-github-actions-with-docker-layer-caching
|
||||
build-docker-image:
|
||||
name: "Build Docker Image"
|
||||
runs-on: ubuntu-22.04 # runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# - uses: docker/setup-buildx-action@v1
|
||||
# name: Set up Docker Buildx
|
||||
|
||||
- uses: docker/login-action@v1
|
||||
name: Login to GitHub Container Registry
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }} # username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Calculate short SHA
|
||||
id: vars
|
||||
# echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
echo "sha_short=$(echo ${{ github.sha }} | cut -c1-12)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Emit short SHA
|
||||
run: |
|
||||
echo "Full SHA: ${{ github.sha }}"
|
||||
echo "Short SHA: ${{ steps.vars.outputs.sha_short }}"
|
||||
|
||||
#- uses: actions/cache@v2
|
||||
# name: Cache Docker layers
|
||||
# with:
|
||||
# path: /tmp/.buildx-cache
|
||||
# key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-buildx-
|
||||
|
||||
# Docs for this action are at https://github.com/marketplace/actions/build-docker-images-using-cache
|
||||
- uses: whoan/docker-build-with-cache-action@v6
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }} # username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
image_name: storytold/storyteller-rust-gpu
|
||||
dockerfile: service_gpu.Dockerfile
|
||||
# NB: The `git_push_tag: true` option does not work as expected, so we put the sha in `image_tag`:
|
||||
# https://github.com/whoan/docker-build-with-cache-action/issues/72
|
||||
image_tag: latest,${{ github.sha }},${{ steps.vars.outputs.sha_short }}
|
||||
# NB: Inject the Git SHA into the container so the servers can emit their own version:
|
||||
build_extra_args: "--build-arg=GIT_SHA=${{ github.sha }}"
|
||||
|
||||
# - name: Build image
|
||||
# run: |
|
||||
# SHORT_SHA=$(echo ${GITHUB_SHA} | cut -c1-12)
|
||||
# docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}" --build-arg GIT_SHA=${SHORT_SHA}
|
||||
|
||||
# - name: Push image to GitHub Container Registry
|
||||
# run: |
|
||||
# IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
|
||||
|
||||
# # Change all uppercase to lowercase
|
||||
# IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
|
||||
|
||||
# # Strip git ref prefix from version
|
||||
# VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
||||
|
||||
# # Strip "v" prefix from tag name
|
||||
# [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
||||
|
||||
# # Use Docker `latest` tag convention
|
||||
# [ "$VERSION" == "$default-branch" ] && VERSION=latest
|
||||
|
||||
# echo IMAGE_ID=$IMAGE_ID
|
||||
# echo VERSION=$VERSION
|
||||
|
||||
# docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
|
||||
# docker push $IMAGE_ID:$VERSION
|
||||
|
||||
# SHORT_SHA=$(echo ${GITHUB_SHA} | cut -c1-12)
|
||||
|
||||
# docker tag $IMAGE_NAME $IMAGE_ID:$SHORT_SHA
|
||||
# docker push $IMAGE_ID:$SHORT_SHA
|
||||
|
||||
- name: Cleanup / Debug
|
||||
# This job will run even on failures to help with debugging.
|
||||
if: always()
|
||||
run: |
|
||||
echo "Report at final github action step:"
|
||||
echo "Disk usage:"
|
||||
pwd
|
||||
du -hsc * | sort -hr
|
||||
@@ -13,6 +13,10 @@ secrets.yaml
|
||||
_develop/tools/.secrets
|
||||
_develop/tools/db_secrets.toml
|
||||
twitch_secrets.toml
|
||||
crates/service/web/storyteller_web/config/storyteller-web.development-secrets.env
|
||||
|
||||
# New env secrets (per-app)
|
||||
*-secrets.env
|
||||
|
||||
# Rust build directory
|
||||
target/
|
||||
@@ -49,3 +53,7 @@ models/tacotron2/python/
|
||||
# Stuff I want to keep around, but not commit
|
||||
scraps/
|
||||
|
||||
# Windows build files
|
||||
# These should be built by the platform
|
||||
windows/sqlite/sqlite3.exp
|
||||
windows/sqlite/sqlite3.lib
|
||||
|
||||
Generated
+7
@@ -8,6 +8,7 @@
|
||||
<w>crockford</w>
|
||||
<w>culted</w>
|
||||
<w>dalle</w>
|
||||
<w>demuxer</w>
|
||||
<w>downvote</w>
|
||||
<w>fakeyou</w>
|
||||
<w>ffprobe</w>
|
||||
@@ -16,16 +17,22 @@
|
||||
<w>greenlit</w>
|
||||
<w>hanashi</w>
|
||||
<w>hifigan</w>
|
||||
<w>hparams</w>
|
||||
<w>huggingface</w>
|
||||
<w>pathbuf</w>
|
||||
<w>replayable</w>
|
||||
<w>retryably</w>
|
||||
<w>scrollback</w>
|
||||
<w>softvc</w>
|
||||
<w>sql's</w>
|
||||
<w>symphonia</w>
|
||||
<w>tacotron</w>
|
||||
<w>techcrunch</w>
|
||||
<w>transcoded</w>
|
||||
<w>transcodings</w>
|
||||
<w>unpermitted</w>
|
||||
<w>upserting</w>
|
||||
<w>vits</w>
|
||||
<w>vocoded</w>
|
||||
<w>vocoder</w>
|
||||
<w>vocoders</w>
|
||||
|
||||
Generated
+2653
-239
File diff suppressed because it is too large
Load Diff
+17
-11
@@ -1,4 +1,5 @@
|
||||
[workspace]
|
||||
resolver="2"
|
||||
|
||||
members = [
|
||||
# Types: common strongly-typed tokens, ids, payloads, etc.
|
||||
@@ -15,26 +16,30 @@ members = [
|
||||
|
||||
# Shared libraries
|
||||
"crates/lib/actix_helpers",
|
||||
"crates/lib/api_clients/cloud_storage",
|
||||
"crates/lib/api_clients/fakeyou_client",
|
||||
"crates/lib/api_clients/google_drive_common",
|
||||
"crates/lib/api_clients/twitch_common",
|
||||
"crates/lib/bootstrap",
|
||||
"crates/lib/caching/memory_caching",
|
||||
"crates/lib/caching/redis_caching",
|
||||
"crates/lib/clients/cloud_storage",
|
||||
"crates/lib/clients/fakeyou_client",
|
||||
"crates/lib/clients/google_drive_common",
|
||||
"crates/lib/clients/twitch_common",
|
||||
"crates/lib/concurrency",
|
||||
"crates/lib/config", # TODO(bt, 2023-02-13): Deprecate or repurpose
|
||||
"crates/lib/container_common", # TODO(bt, 2023-02-13): Pull apart and rehome pieces
|
||||
"crates/lib/crockford",
|
||||
"crates/lib/database_queries", # TODO(bt2, 2023-02-13): Rename "mysql_queries", though this will not live beyond a single DB
|
||||
"crates/lib/datetimes",
|
||||
"crates/lib/deprecated/config", # TODO(bt, 2023-02-13): Deprecate or repurpose
|
||||
"crates/lib/deprecated/container_common", # TODO(bt, 2023-02-13): Pull apart and rehome pieces
|
||||
"crates/lib/deprecated/http_server_common", # TODO(bt, 2023-03-20): Move useful pieces to actix_helpers
|
||||
"crates/lib/envvar",
|
||||
"crates/lib/errors",
|
||||
"crates/lib/files",
|
||||
"crates/lib/hashing",
|
||||
"crates/lib/http_server_common",
|
||||
"crates/lib/files/filesys",
|
||||
"crates/lib/files/hashing",
|
||||
"crates/lib/files/media",
|
||||
"crates/lib/files/mimetypes",
|
||||
"crates/lib/idempotency",
|
||||
"crates/lib/jobs_common",
|
||||
"crates/lib/media",
|
||||
"crates/lib/mysql_queries",
|
||||
"crates/lib/redis_common",
|
||||
"crates/lib/server_environment",
|
||||
"crates/lib/sqlite_queries",
|
||||
"crates/lib/sqlx_mysql_helpers",
|
||||
"crates/lib/subprocess_common",
|
||||
@@ -45,6 +50,7 @@ members = [
|
||||
|
||||
# Programs: Desktop apps
|
||||
"crates/programs/aichatbot-sidecar",
|
||||
"crates/programs/bevy-experiments",
|
||||
|
||||
# Services: API servers, jobs, workers, etc.
|
||||
"crates/service/job/analytics_job",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Secrets
|
||||
db_secrets.toml
|
||||
|
||||
# Python Virtual Env
|
||||
python/
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# FIXME: Needs packages 'toml' and 'mysql-connector-python'. Put in requirements.txt.
|
||||
|
||||
import time
|
||||
import toml
|
||||
import mysql.connector
|
||||
|
||||
DB_SECRETS_FILE = 'db_secrets.toml'
|
||||
|
||||
# TODO: Share db-related setup when more scripts are added.
|
||||
|
||||
def read_database_secrets(secrets_file = DB_SECRETS_FILE):
|
||||
secrets = None
|
||||
with open(secrets_file, "r") as f:
|
||||
secrets = toml.load(f)
|
||||
|
||||
required_keys = ['database', 'hostname', 'port', 'password', 'username']
|
||||
for key in required_keys:
|
||||
if key not in secrets:
|
||||
raise Exception(f"Required key '#{key}' not present")
|
||||
|
||||
return secrets
|
||||
|
||||
def connect_to_mysql():
|
||||
secrets = read_database_secrets()
|
||||
connection = mysql.connector.connect(
|
||||
host = secrets['hostname'],
|
||||
port = secrets['port'],
|
||||
user = secrets['username'],
|
||||
password = secrets['password'],
|
||||
database = secrets['database'],
|
||||
)
|
||||
return connection
|
||||
|
||||
connection = connect_to_mysql()
|
||||
cursor = connection.cursor()
|
||||
|
||||
SAFE_ID = 76000000 # Reasonably completed on 2022-06-24
|
||||
LIMIT = 100000
|
||||
|
||||
#def get_record_count():
|
||||
# query = f"SELECT COUNT(*) FROM tts_inference_jobs"
|
||||
# cursor.execute(query)
|
||||
# result = cursor.fetchall()
|
||||
# print(result)
|
||||
# return result[0]
|
||||
#
|
||||
##total_count = get_record_count()
|
||||
|
||||
#total_count = 75082057
|
||||
total_count = 21925602
|
||||
|
||||
def get_user_tokens(cursor):
|
||||
query = f"""
|
||||
SELECT
|
||||
r.maybe_creator_user_token, r.creator_ip_address
|
||||
FROM
|
||||
tts_results as r
|
||||
LEFT OUTER JOIN
|
||||
users as u
|
||||
ON
|
||||
r.maybe_creator_user_token = u.token
|
||||
WHERE
|
||||
r.raw_inference_text LIKE '%spidermant%'
|
||||
AND r.created_at > ( CURDATE() - INTERVAL 1 HOUR )
|
||||
"""
|
||||
cursor.execute(query)
|
||||
results = cursor.fetchall()
|
||||
|
||||
user_tokens = [row[0] for row in results]
|
||||
user_tokens = [token for token in user_tokens if token is not None]
|
||||
user_tokens = set(user_tokens)
|
||||
|
||||
ip_addresses = [row[1] for row in results]
|
||||
ip_addresses = [ip for ip in ip_addresses if ip is not None]
|
||||
ip_addresses = set(ip_addresses)
|
||||
|
||||
return (user_tokens, ip_addresses)
|
||||
|
||||
(user_tokens, ip_addresses) = get_user_tokens(cursor)
|
||||
|
||||
print(user_tokens)
|
||||
print(len(user_tokens))
|
||||
print(len(ip_addresses))
|
||||
|
||||
with open('101_user_tokens.txt', 'w') as f:
|
||||
for user_token in user_tokens:
|
||||
f.write(user_token)
|
||||
f.write("\n")
|
||||
|
||||
with open('101_ip_addresses.txt', 'w') as f:
|
||||
for ip in ip_addresses:
|
||||
f.write(ip)
|
||||
f.write("\n")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
mysql-connector-python==8.0.32
|
||||
protobuf==3.20.3
|
||||
toml==0.10.2
|
||||
@@ -0,0 +1,9 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Kill routed jobs
|
||||
update generic_inference_jobs set status = 'dead' where maybe_routing_tag IS NOT NULL limit 100;
|
||||
|
||||
-- Get pending jobs
|
||||
select count(*) from generic_inference_jobs where status = 'pending';
|
||||
@@ -0,0 +1,24 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Kill pending jobs
|
||||
update tts_inference_jobs set status = 'dead' where status = 'pending';
|
||||
|
||||
-- Kill all low priority pending, waiting, and in-progress jobs
|
||||
update tts_inference_jobs
|
||||
set status = 'dead'
|
||||
where status IN ('pending', 'started', 'attempt_failed')
|
||||
and priority_level IN (0, 1);
|
||||
|
||||
-- Kill all pending jobs
|
||||
update tts_inference_jobs
|
||||
set status = 'dead'
|
||||
where status = 'pending';
|
||||
|
||||
-- Kill all waiting and in-progress jobs
|
||||
update tts_inference_jobs
|
||||
set status = 'dead'
|
||||
where status IN ('pending', 'started', 'attempt_failed');
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Delete TTS results for a single model
|
||||
-- Do this in short batches so a lock isn't held for prohibitively long.
|
||||
update tts_results
|
||||
set mod_deleted_at = NOW()
|
||||
where model_token = 'TM:ztt5s1be5tq6'
|
||||
and mod_deleted_at IS NULL
|
||||
limit 5000;
|
||||
@@ -0,0 +1,35 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Upgrade top TTS model uploaders to a loyalty plan
|
||||
update users
|
||||
set maybe_loyalty_program_key = 'fakeyou_contributor'
|
||||
where token IN (
|
||||
select creator_user_token from
|
||||
(
|
||||
select count(*) as upload_count,
|
||||
creator_user_token
|
||||
from tts_models
|
||||
group by creator_user_token
|
||||
having upload_count >= 10
|
||||
order by upload_count desc
|
||||
) as t
|
||||
);
|
||||
|
||||
-- Upgrade top VC model uploaders to a loyalty plan
|
||||
update users
|
||||
set maybe_loyalty_program_key = 'fakeyou_contributor'
|
||||
where token IN (
|
||||
select creator_user_token from
|
||||
(
|
||||
select count(*) as upload_count,
|
||||
creator_user_token
|
||||
from voice_conversion_models
|
||||
group by creator_user_token
|
||||
having upload_count >= 10
|
||||
order by upload_count desc
|
||||
) as t
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Remove temporary test models
|
||||
update voice_conversion_models
|
||||
set
|
||||
mod_deleted_at = NOW(),
|
||||
maybe_mod_comments = 'temporary test model'
|
||||
where token IN (
|
||||
'vcm_jt9mdz9xjjcb',
|
||||
'vcm_4xzkzdhs4kk5',
|
||||
'vcm_502wkt2pca3y'
|
||||
);
|
||||
|
||||
-- Remove broken models
|
||||
update voice_conversion_models
|
||||
set
|
||||
mod_deleted_at = NOW(),
|
||||
maybe_mod_comments = 'broken model'
|
||||
where token IN (
|
||||
'vcm_982y9g6v3jrg',
|
||||
'vcm_16rpyehf7f0a',
|
||||
'vcm_8vjtz3dbnw17',
|
||||
'vcm_tc9mwr60cjth',
|
||||
'vcm_bshsyp01w9vg',
|
||||
'vcm_31whj8apmqj7',
|
||||
'vcm_84qa0an44p8p',
|
||||
'vcm_9xx4v5qz5fbg',
|
||||
'vcm_7zp2b2hs2at2',
|
||||
'vcm_zhvk0mnnb7zp',
|
||||
'vcm_1vc4scq9qp6m',
|
||||
'vcm_sr1b54mwy0ym',
|
||||
'vcm_qx96y8aasydk'
|
||||
);
|
||||
|
||||
-- Remove duplicate models
|
||||
update voice_conversion_models
|
||||
set
|
||||
mod_deleted_at = NOW(),
|
||||
maybe_mod_comments = 'duplicate model'
|
||||
where token IN (
|
||||
'vcm_6w21em1bs7q3',
|
||||
'vcm_sbhvyj7926w4',
|
||||
'vcm_anv469g89adz',
|
||||
'vcm_xsx5yx585c7x',
|
||||
'vcm_dpahzjjpkf18',
|
||||
'vcm_y09dqe6zgwyk',
|
||||
'vcm_xrp96dwgppv2'
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Kill pending jobs
|
||||
update w2l_inference_jobs set status='dead' where status IN ('pending', 'started', 'attempt_failed');
|
||||
|
||||
-- Unstick old jobs that might be stuck as "started"
|
||||
update w2l_template_upload_jobs
|
||||
set status='dead'
|
||||
where status='started'
|
||||
and created_at < ( CURDATE() - INTERVAL 1 DAY );
|
||||
|
||||
-- Kill pending jobs with tiktok URLs:
|
||||
-- These need to be blocked in the server and job directly.
|
||||
update w2l_template_upload_jobs
|
||||
set status='dead'
|
||||
where status='pending'
|
||||
and download_url LIKE '%tiktok%';
|
||||
@@ -0,0 +1,80 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- See how long recent jobs are taking
|
||||
select
|
||||
id,
|
||||
maybe_input_source_token,
|
||||
assigned_worker,
|
||||
assigned_cluster,
|
||||
success_execution_millis / 1000 / 60 as minutes
|
||||
from generic_inference_jobs
|
||||
where status != 'pending'
|
||||
and success_execution_millis IS NOT NULL
|
||||
order by id desc
|
||||
limit 50;
|
||||
|
||||
|
||||
-- Detailed report on most recent jobs, ordered by worst performing.
|
||||
-- TODO: Determine if the problem is in downloading models. Make sure the job timer doesn't include
|
||||
-- sections where models / files get downloaded.
|
||||
select *
|
||||
from (
|
||||
select
|
||||
jobs.created_at,
|
||||
jobs.first_started_at,
|
||||
jobs.id,
|
||||
jobs.status,
|
||||
jobs.attempt_count as attempts,
|
||||
trim(replace(replace(jobs.internal_debugging_failure_reason, "\n", ""), "\r", ""))
|
||||
as i_failure_reason,
|
||||
-- u.username,
|
||||
jobs.assigned_worker,
|
||||
jobs.assigned_cluster,
|
||||
jobs.maybe_input_source_token,
|
||||
jobs.maybe_model_token,
|
||||
m.media_source,
|
||||
m.maybe_original_mime_type as mime_type,
|
||||
TRUNCATE(jobs.success_execution_millis / 1000 / 60, 2) as execution_mins,
|
||||
TRUNCATE(jobs.success_inference_execution_millis / 1000 / 60, 2) as inference_mins,
|
||||
TRUNCATE((jobs.success_execution_millis - jobs.success_inference_execution_millis) / 1000 / 60, 2) as extra_mins,
|
||||
TRUNCATE(m.original_duration_millis / 1000 / 60, 2) as input_mins,
|
||||
jobs.success_execution_millis / m.original_duration_millis as ratio
|
||||
from generic_inference_jobs AS jobs
|
||||
left join users AS u on
|
||||
u.token = jobs.maybe_creator_user_token
|
||||
left join media_uploads AS m on
|
||||
m.token = jobs.maybe_input_source_token
|
||||
where
|
||||
jobs.status != 'pending'
|
||||
AND jobs.created_at > NOW() - INTERVAL 20 MINUTE
|
||||
order by id desc
|
||||
limit 5000
|
||||
) as t
|
||||
order by execution_mins desc;
|
||||
|
||||
order by assigned_worker desc, first_started_at asc;
|
||||
|
||||
order by first_started_at asc;
|
||||
|
||||
order by assigned_worker desc, execution_mins desc;
|
||||
|
||||
|
||||
-- Get pending so-vits-svc jobs
|
||||
select count(*)
|
||||
from generic_inference_jobs
|
||||
where maybe_model_type = 'so_vits_svc'
|
||||
and status='pending';
|
||||
|
||||
|
||||
-- Get jobs that have routing tags
|
||||
select
|
||||
id,
|
||||
maybe_input_source_token,
|
||||
maybe_creator_user_token,
|
||||
maybe_routing_tag,
|
||||
status
|
||||
from generic_inference_jobs
|
||||
where maybe_routing_tag IS NOT NULL
|
||||
limit 10;
|
||||
@@ -0,0 +1,50 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
select
|
||||
mu.id,
|
||||
mu.token,
|
||||
u.username,
|
||||
mu.media_source,
|
||||
maybe_original_filename as filename,
|
||||
original_file_size_bytes as size_bytes,
|
||||
original_duration_millis as duration_millis,
|
||||
maybe_original_mime_type as mime_type
|
||||
from media_uploads as mu
|
||||
left join users AS u
|
||||
on u.token = mu.maybe_creator_user_token
|
||||
order by id desc limit 10;
|
||||
|
||||
-- Analyze all media
|
||||
select
|
||||
mu.id,
|
||||
mu.token,
|
||||
u.username,
|
||||
mu.media_source,
|
||||
maybe_original_filename as filename,
|
||||
original_file_size_bytes as size_bytes,
|
||||
original_duration_millis as duration_millis,
|
||||
maybe_original_mime_type as mime_type
|
||||
from media_uploads as mu
|
||||
left join users AS u
|
||||
on u.token = mu.maybe_creator_user_token
|
||||
order by id desc
|
||||
limit 40;
|
||||
|
||||
-- Analyze broken media (no duration)
|
||||
select
|
||||
mu.id,
|
||||
mu.token,
|
||||
u.username,
|
||||
mu.media_source,
|
||||
maybe_original_filename as filename,
|
||||
original_file_size_bytes as size_bytes,
|
||||
original_duration_millis as duration_millis,
|
||||
maybe_original_mime_type as mime_type
|
||||
from media_uploads as mu
|
||||
left join users AS u
|
||||
on u.token = mu.maybe_creator_user_token
|
||||
where mu.original_duration_millis = 0
|
||||
order by id desc
|
||||
limit 40;
|
||||
@@ -2,9 +2,6 @@
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Kill pending jobs
|
||||
update tts_inference_jobs set status = 'dead' where status = 'pending';
|
||||
|
||||
-- Total pending jobs
|
||||
select count(*)
|
||||
from tts_inference_jobs
|
||||
@@ -32,17 +29,6 @@ group by model_token
|
||||
order by attempts desc
|
||||
limit 50;
|
||||
|
||||
|
||||
-- Kill pending jobs
|
||||
update tts_inference_jobs
|
||||
set status = 'dead'
|
||||
where status = 'pending';
|
||||
|
||||
-- Kill all waiting and in-progress jobs
|
||||
update tts_inference_jobs
|
||||
set status = 'dead'
|
||||
where status IN ('pending', 'started', 'attempt_failed');
|
||||
|
||||
-- Sample the pending inference text
|
||||
select creator_ip_address,
|
||||
model_token,
|
||||
|
||||
@@ -12,9 +12,9 @@ select
|
||||
m.title,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -63,7 +63,41 @@ from (
|
||||
join users as u
|
||||
on u.token = m.creator_user_token
|
||||
order by r.use_count desc
|
||||
limit 25;
|
||||
limit 100;
|
||||
|
||||
|
||||
--
|
||||
-- Top models binned by IP address.
|
||||
-- Should give us a look at demand independent of model quality / repeated use.
|
||||
--
|
||||
select
|
||||
m.token,
|
||||
m.title,
|
||||
m.user_ratings_positive_count / m.user_ratings_total_count as rating,
|
||||
m.text_pipeline_type,
|
||||
m.ietf_language_tag,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from (
|
||||
select model_token, creator_ip_address
|
||||
from tts_results
|
||||
where created_at > (CURDATE() - INTERVAL 12 HOUR)
|
||||
group by model_token, creator_ip_address
|
||||
) as x
|
||||
group by model_token
|
||||
) as r
|
||||
join tts_models as m
|
||||
on m.token = r.model_token
|
||||
join users as u
|
||||
on u.token = m.creator_user_token
|
||||
where m.ietf_language_tag IN ('en', 'en-US', 'en-AU', 'en-CA', 'en-GB')
|
||||
order by r.use_count desc
|
||||
limit 100;
|
||||
|
||||
--
|
||||
-- Top 20 ***NEW*** models to share in #announcements
|
||||
@@ -73,12 +107,13 @@ select
|
||||
m.token,
|
||||
m.text_pipeline_type,
|
||||
m.ietf_language_tag,
|
||||
m.creator_set_visibility,
|
||||
m.title,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -90,7 +125,7 @@ from (
|
||||
join users as u
|
||||
on u.token = m.creator_user_token
|
||||
where m.created_at > ( CURDATE() - INTERVAL 31 DAY )
|
||||
AND u.username IN ( 'vegito1089', 'justinjohn0306')
|
||||
-- AND u.username IN ( 'vegito1089', 'justinjohn0306')
|
||||
order by r.use_count desc
|
||||
limit 100;
|
||||
|
||||
@@ -105,9 +140,9 @@ select
|
||||
m.title,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -138,9 +173,9 @@ select
|
||||
m.ietf_language_tag,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -164,9 +199,9 @@ select
|
||||
m.ietf_language_tag,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -192,9 +227,9 @@ select
|
||||
m.ietf_language_tag,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -224,8 +259,8 @@ select
|
||||
m.ietf_language_tag,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.user_deleted_at,
|
||||
m.created_at
|
||||
m.created_at,
|
||||
m.user_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -256,9 +291,9 @@ select
|
||||
m.ietf_language_tag,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at,
|
||||
m.created_at
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
@@ -300,3 +335,31 @@ where m.mod_deleted_at > ( CURDATE() - INTERVAL 14 DAY )
|
||||
order by r.use_count desc
|
||||
limit 500;
|
||||
|
||||
--
|
||||
-- Non-public models
|
||||
--
|
||||
select
|
||||
m.token,
|
||||
m.title,
|
||||
m.text_pipeline_type,
|
||||
m.ietf_language_tag,
|
||||
m.creator_set_visibility,
|
||||
u.username,
|
||||
r.use_count,
|
||||
m.created_at,
|
||||
m.user_deleted_at,
|
||||
m.mod_deleted_at
|
||||
from (
|
||||
select model_token, count(*) as use_count
|
||||
from tts_results
|
||||
where created_at > ( CURDATE() - INTERVAL 30 DAY )
|
||||
group by model_token
|
||||
) as r
|
||||
left outer join tts_models as m
|
||||
on m.token = r.model_token
|
||||
join users as u
|
||||
on u.token = m.creator_user_token
|
||||
where m.creator_set_visibility != 'public'
|
||||
order by r.use_count desc
|
||||
limit 500;
|
||||
|
||||
|
||||
@@ -64,14 +64,6 @@ ORDER BY created_at DESC
|
||||
|
||||
|
||||
|
||||
-- Delete TTS results for a single model
|
||||
-- Do this in short batches so a lock isn't held for prohibitively long.
|
||||
update tts_results
|
||||
set mod_deleted_at = NOW()
|
||||
where model_token = 'TM:ztt5s1be5tq6'
|
||||
and mod_deleted_at IS NULL
|
||||
limit 5000;
|
||||
|
||||
--- Search for particular text by a particular model
|
||||
SELECT
|
||||
raw_inference_text,
|
||||
@@ -83,6 +75,39 @@ WHERE
|
||||
model_token = 'TM:ztt5s1be5tq6'
|
||||
AND raw_inference_text LIKE '%fakeyou%'
|
||||
|
||||
--- Search for 101soundboards.com using us
|
||||
SELECT
|
||||
r.raw_inference_text,
|
||||
r.maybe_creator_user_token,
|
||||
u.username,
|
||||
u.ip_address_creation,
|
||||
r.creator_ip_address,
|
||||
r.created_at
|
||||
FROM
|
||||
tts_results as r
|
||||
LEFT OUTER JOIN
|
||||
users as u
|
||||
ON
|
||||
r.maybe_creator_user_token = u.token
|
||||
WHERE
|
||||
r.raw_inference_text LIKE '%bananas%'
|
||||
AND r.created_at > ( CURDATE() - INTERVAL 1 HOUR )
|
||||
|
||||
|
||||
--- Search for 101soundboards.com using us
|
||||
SELECT
|
||||
r.maybe_creator_user_token, r.creator_ip_address
|
||||
FROM
|
||||
tts_results as r
|
||||
LEFT OUTER JOIN
|
||||
users as u
|
||||
ON
|
||||
r.maybe_creator_user_token = u.token
|
||||
WHERE
|
||||
r.raw_inference_text LIKE '%pickle%'
|
||||
AND r.created_at > ( CURDATE() - INTERVAL 1 HOUR )
|
||||
|
||||
|
||||
---
|
||||
-- WTF WHY IS THIS SLOW???
|
||||
SELECT
|
||||
|
||||
@@ -13,6 +13,52 @@ select count(*) from user_subscriptions;
|
||||
-- NB: "active" status users are current, treating "past_due" as active too (for now)
|
||||
select count(*) from user_subscriptions where maybe_stripe_subscription_status NOT IN ("canceled", "incomplete", "incomplete_expired");
|
||||
|
||||
-- ==================== TTS + VC + W2L ====================
|
||||
|
||||
-- Make sure the time intervals are the same!
|
||||
SELECT
|
||||
username,
|
||||
count(*) as total_use_count
|
||||
FROM (
|
||||
SELECT
|
||||
u.username as username,
|
||||
j.token as token
|
||||
FROM users AS u
|
||||
JOIN tts_inference_jobs AS j
|
||||
ON u.token = j.maybe_creator_user_token
|
||||
WHERE u.token IN (
|
||||
SELECT DISTINCT user_token
|
||||
FROM user_subscriptions
|
||||
)
|
||||
AND j.created_at > NOW() - INTERVAL 31 DAY
|
||||
UNION
|
||||
SELECT
|
||||
u.username as username,
|
||||
j.token as token
|
||||
FROM users AS u
|
||||
JOIN generic_inference_jobs AS j
|
||||
ON u.token = j.maybe_creator_user_token
|
||||
WHERE u.token IN (
|
||||
SELECT DISTINCT user_token
|
||||
FROM user_subscriptions
|
||||
)
|
||||
AND j.created_at > NOW() - INTERVAL 31 DAY
|
||||
UNION
|
||||
SELECT
|
||||
u.username as username,
|
||||
j.token as token
|
||||
FROM users AS u
|
||||
JOIN w2l_inference_jobs AS j
|
||||
ON u.token = j.maybe_creator_user_token
|
||||
WHERE u.token IN (
|
||||
SELECT DISTINCT user_token
|
||||
FROM user_subscriptions
|
||||
)
|
||||
AND j.created_at > NOW() - INTERVAL 31 DAY
|
||||
) as t
|
||||
GROUP BY username
|
||||
ORDER BY total_use_count desc
|
||||
|
||||
-- ==================== TEXT TO SPEECH====================
|
||||
|
||||
-- All paid subscribers generating results in the last week
|
||||
@@ -23,7 +69,7 @@ on u.token = j.maybe_creator_user_token
|
||||
WHERE u.token IN (
|
||||
select distinct user_token
|
||||
from user_subscriptions
|
||||
where maybe_stripe_subscription_status NOT IN ("canceled", "incomplete", "incomplete_expired")
|
||||
-- where maybe_stripe_subscription_status NOT IN ("canceled", "incomplete", "incomplete_expired")
|
||||
)
|
||||
AND j.created_at > NOW() - interval 7 day
|
||||
GROUP BY u.username
|
||||
|
||||
@@ -25,20 +25,26 @@ on u.token = m.creator_user_token
|
||||
where m.upload_count >= 5;
|
||||
|
||||
|
||||
|
||||
-- Upgrade top TTS model uploaders to a loyalty plan
|
||||
update users
|
||||
set maybe_loyalty_program_key = 'fakeyou_contributor'
|
||||
where token IN (
|
||||
select creator_user_token from
|
||||
(
|
||||
select count(*) as upload_count,
|
||||
creator_user_token
|
||||
from tts_models
|
||||
group by creator_user_token
|
||||
having upload_count >= 10
|
||||
order by upload_count desc
|
||||
) as t
|
||||
);
|
||||
-- Top VC model uploaders
|
||||
select
|
||||
u.id,
|
||||
u.token,
|
||||
u.username,
|
||||
u.created_at,
|
||||
u.maybe_stripe_customer_id,
|
||||
u.maybe_loyalty_program_key,
|
||||
m.upload_count
|
||||
from users as u
|
||||
join
|
||||
(
|
||||
select
|
||||
count(*) as upload_count,
|
||||
creator_user_token
|
||||
from voice_conversion_models
|
||||
group by creator_user_token
|
||||
order by upload_count desc
|
||||
) as m
|
||||
on u.token = m.creator_user_token
|
||||
where m.upload_count >= 5;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Inventory all
|
||||
select
|
||||
vc.id,
|
||||
vc.token,
|
||||
vc.model_type,
|
||||
vc.title,
|
||||
u.username,
|
||||
vc.original_download_url,
|
||||
vc.created_at,
|
||||
vc.updated_at,
|
||||
vc.user_deleted_at,
|
||||
vc.mod_deleted_at,
|
||||
vc.maybe_mod_comments
|
||||
from voice_conversion_models as vc
|
||||
left join users AS u on
|
||||
u.token = vc.creator_user_token;
|
||||
|
||||
-- Inventory non-deleted
|
||||
select
|
||||
vc.id,
|
||||
vc.token,
|
||||
vc.model_type,
|
||||
vc.title,
|
||||
u.username,
|
||||
vc.original_download_url,
|
||||
vc.created_at,
|
||||
vc.updated_at
|
||||
from voice_conversion_models as vc
|
||||
left join users AS u on
|
||||
u.token = vc.creator_user_token
|
||||
where
|
||||
vc.user_deleted_at IS NULL
|
||||
and vc.mod_deleted_at IS NULL;
|
||||
@@ -14,15 +14,3 @@ from w2l_template_upload_jobs
|
||||
where status='started'
|
||||
and created_at < ( CURDATE() - INTERVAL 1 DAY );
|
||||
|
||||
-- Unstick old jobs that might be stuck as "started"
|
||||
update w2l_template_upload_jobs
|
||||
set status='dead'
|
||||
where status='started'
|
||||
and created_at < ( CURDATE() - INTERVAL 1 DAY );
|
||||
|
||||
-- Kill pending jobs with tiktok URLs:
|
||||
-- These need to be blocked in the server and job directly.
|
||||
update w2l_template_upload_jobs
|
||||
set status='dead'
|
||||
where status='pending'
|
||||
and download_url LIKE '%tiktok%';
|
||||
|
||||
@@ -88,7 +88,7 @@ CREATE TABLE generic_inference_jobs (
|
||||
is_from_api_user BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_for_twitch BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- If true, the request gets routed to a special "debug" worker.
|
||||
-- NB: The meaning of this column has changed. See the "squashed" schema for docs/details.
|
||||
is_debug_request BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== JOB SYSTEM DETAILS ==========
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE comments;
|
||||
@@ -0,0 +1,69 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Comments that can be attached to just about anything.
|
||||
-- This is a polymorphic table and can apply to a wide variety of entities.
|
||||
CREATE TABLE comments (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Idempotency token from client
|
||||
-- This is so the frontend client doesn't submit duplicate items.
|
||||
uuid_idempotency_token VARCHAR(36) NOT NULL,
|
||||
|
||||
-- User making the comment
|
||||
user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The type of entity the comment applies to
|
||||
entity_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The token of the entity the comment applies to
|
||||
entity_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The comment in markdown
|
||||
comment_markdown TEXT NOT NULL,
|
||||
|
||||
-- Generated HTML (not user-editable).
|
||||
comment_rendered_html TEXT NOT NULL,
|
||||
|
||||
-- For abuse tracking.
|
||||
-- Wide enough for IPv4/6
|
||||
creator_ip_address VARCHAR(40) NOT NULL,
|
||||
editor_ip_address VARCHAR(40) NOT NULL,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- Technically, this conveys *user* edits, not things that update the record itself.
|
||||
edited_at TIMESTAMP NULL,
|
||||
|
||||
-- If this is removed by a mod.
|
||||
-- It completely disappears from the system.
|
||||
user_deleted_at TIMESTAMP NULL,
|
||||
mod_deleted_at TIMESTAMP NULL,
|
||||
-- The owner of the thing the comment is attached to can delete the comment too.
|
||||
object_owner_deleted_at TIMESTAMP NULL,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (uuid_idempotency_token),
|
||||
KEY index_entity_type_entity_token (entity_type, entity_token),
|
||||
KEY index_user_token (user_token),
|
||||
KEY index_created_at (created_at),
|
||||
KEY index_user_deleted_at (user_deleted_at),
|
||||
KEY index_mod_deleted_at (mod_deleted_at),
|
||||
KEY index_object_owner_deleted_at (object_owner_deleted_at)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN maybe_routing_tag;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN maybe_routing_tag VARCHAR(32) DEFAULT NULL
|
||||
AFTER is_debug_request;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD INDEX index_maybe_routing_tag (maybe_routing_tag);
|
||||
@@ -0,0 +1,23 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- REVERT ADDING 'vits' MODEL TYPE
|
||||
|
||||
ALTER TABLE tts_models
|
||||
MODIFY COLUMN tts_model_type ENUM(
|
||||
'not-set',
|
||||
'tacotron2',
|
||||
'glowtts',
|
||||
'glowtts-vocodes',
|
||||
'talknet'
|
||||
) NOT NULL DEFAULT 'not-set';
|
||||
|
||||
ALTER TABLE tts_model_upload_jobs
|
||||
MODIFY COLUMN tts_model_type ENUM(
|
||||
'not-set',
|
||||
'tacotron2',
|
||||
'glowtts',
|
||||
'glowtts-vocodes',
|
||||
'talknet'
|
||||
) NOT NULL DEFAULT 'not-set';
|
||||
@@ -0,0 +1,28 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Add 'vits' to the tts_model_type.
|
||||
|
||||
ALTER TABLE tts_models
|
||||
MODIFY COLUMN tts_model_type ENUM(
|
||||
'not-set',
|
||||
'tacotron2',
|
||||
'glowtts',
|
||||
'glowtts-vocodes',
|
||||
'talknet',
|
||||
'vits'
|
||||
) NOT NULL DEFAULT 'not-set';
|
||||
|
||||
-- Technically we won't be using the model upload jobs table anymore,
|
||||
-- but add 'vits' for consistency.
|
||||
|
||||
ALTER TABLE tts_model_upload_jobs
|
||||
MODIFY COLUMN tts_model_type ENUM(
|
||||
'not-set',
|
||||
'tacotron2',
|
||||
'glowtts',
|
||||
'glowtts-vocodes',
|
||||
'talknet',
|
||||
'vits'
|
||||
) NOT NULL DEFAULT 'not-set';
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP INDEX `index_tts_model_type` ON `tts_models`;
|
||||
@@ -0,0 +1,6 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE tts_models ADD INDEX index_tts_model_type (tts_model_type);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs RENAME COLUMN inference_category TO inference_type;
|
||||
|
||||
ALTER TABLE generic_inference_jobs RENAME INDEX index_inference_category TO index_inference_type;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs RENAME COLUMN inference_type TO inference_category;
|
||||
|
||||
ALTER TABLE generic_inference_jobs RENAME INDEX index_inference_type TO index_inference_category;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs MODIFY maybe_model_token VARCHAR(32) DEFAULT NULL AFTER maybe_raw_inference_text;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs MODIFY maybe_model_token VARCHAR(32) DEFAULT NULL AFTER inference_category;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP INDEX index_maybe_model_type_and_maybe_model_token ON generic_inference_jobs;
|
||||
DROP INDEX index_maybe_model_type ON generic_inference_jobs;
|
||||
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN maybe_model_type;
|
||||
@@ -0,0 +1,10 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN maybe_model_type VARCHAR(32) DEFAULT NULL
|
||||
AFTER inference_category;
|
||||
|
||||
CREATE INDEX index_maybe_model_type_and_maybe_model_token ON generic_inference_jobs (maybe_model_type, maybe_model_token);
|
||||
CREATE INDEX index_maybe_model_type ON generic_inference_jobs (maybe_model_type);
|
||||
@@ -0,0 +1,26 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN public_bucket_hash;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN bucket_has_wav;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN bucket_has_mp3;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN bucket_has_mp4;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN bucket_has_webm;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN bucket_has_spectrogram;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN public_bucket_directory_full_path VARCHAR(255) NOT NULL
|
||||
AFTER maybe_creator_synthetic_id;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN public_bucket_wav_audio_object_name VARCHAR(255) NOT NULL
|
||||
AFTER public_bucket_directory_full_path;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN public_bucket_spectrogram_object_name VARCHAR(255) NOT NULL
|
||||
AFTER public_bucket_wav_audio_object_name;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN public_bucket_video_object_name VARCHAR(255) NOT NULL
|
||||
AFTER public_bucket_spectrogram_object_name;
|
||||
@@ -0,0 +1,39 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- These columns are no longer useful.
|
||||
-- It's better to store booleans for each type of file we store and calculate the paths.
|
||||
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN public_bucket_directory_full_path;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN public_bucket_wav_audio_object_name;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN public_bucket_spectrogram_object_name;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN public_bucket_video_object_name;
|
||||
|
||||
-- The hash will contain the key information for where files live
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN public_bucket_hash VARCHAR(64) NOT NULL
|
||||
AFTER maybe_creator_synthetic_id;
|
||||
|
||||
-- The boolean flags will tell what we store.
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN bucket_has_wav BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER public_bucket_hash;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN bucket_has_mp3 BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER bucket_has_wav;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN bucket_has_mp4 BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER bucket_has_mp3;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN bucket_has_webm BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER bucket_has_mp4;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN bucket_has_spectrogram BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER bucket_has_webm;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP INDEX `fk_media_token_and_media_token_type` ON `voice_conversion_results`;
|
||||
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN media_token_type;
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN generated_by_cluster;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN maybe_vocoder_token VARCHAR(64) DEFAULT NULL
|
||||
AFTER model_token;
|
||||
|
||||
CREATE INDEX `fk_maybe_vocoder_token`
|
||||
ON `voice_conversion_results` (`maybe_vocoder_token`);
|
||||
@@ -0,0 +1,20 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- There isn't a vocoder, and even if so, it doesn't need to be referenced here.
|
||||
|
||||
DROP INDEX `fk_maybe_vocoder_token` ON `voice_conversion_results`;
|
||||
|
||||
ALTER TABLE voice_conversion_results DROP COLUMN maybe_vocoder_token;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN media_token_type VARCHAR(32) NOT NULL
|
||||
AFTER media_token;
|
||||
|
||||
ALTER TABLE voice_conversion_results
|
||||
ADD COLUMN generated_by_cluster VARCHAR(255) NOT NULL
|
||||
AFTER generated_by_worker;
|
||||
|
||||
CREATE INDEX `fk_media_token_and_media_token_type`
|
||||
ON `voice_conversion_results` (`media_token`, `media_token_type`);
|
||||
@@ -0,0 +1,9 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP INDEX `fk_maybe_input_source_token` ON `generic_inference_jobs`;
|
||||
DROP INDEX `fk_maybe_input_source_token_and_type` ON `generic_inference_jobs`;
|
||||
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN maybe_input_source_token;
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN maybe_input_source_token_type;
|
||||
@@ -0,0 +1,17 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN maybe_input_source_token VARCHAR(32) DEFAULT NULL
|
||||
AFTER maybe_model_token;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN maybe_input_source_token_type VARCHAR(32) DEFAULT NULL
|
||||
AFTER maybe_input_source_token;
|
||||
|
||||
CREATE INDEX `fk_maybe_input_source_token`
|
||||
ON `generic_inference_jobs` (`maybe_input_source_token`);
|
||||
|
||||
CREATE INDEX `fk_maybe_input_source_token_and_type`
|
||||
ON `generic_inference_jobs` (`maybe_input_source_token`, `maybe_input_source_token_type`);
|
||||
@@ -0,0 +1,10 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_uploads
|
||||
ADD COLUMN public_bucket_directory_full_path VARCHAR(255) NOT NULL
|
||||
AFTER public_bucket_directory_hash;
|
||||
|
||||
ALTER TABLE media_uploads
|
||||
RENAME COLUMN maybe_extra_file_modification_info TO extra_file_modification_info ;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_uploads DROP COLUMN public_bucket_directory_full_path;
|
||||
|
||||
ALTER TABLE media_uploads
|
||||
RENAME COLUMN extra_file_modification_info TO maybe_extra_file_modification_info;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_uploads DROP COLUMN media_source;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_uploads
|
||||
ADD COLUMN media_source VARCHAR(16) NOT NULL
|
||||
AFTER media_type;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_download_jobs DROP COLUMN first_started_at;
|
||||
ALTER TABLE generic_download_jobs DROP COLUMN assigned_cluster;
|
||||
ALTER TABLE generic_download_jobs DROP COLUMN assigned_worker;
|
||||
ALTER TABLE generic_download_jobs DROP COLUMN successfully_completed_at;
|
||||
@@ -0,0 +1,19 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_download_jobs
|
||||
ADD COLUMN assigned_worker VARCHAR(128) DEFAULT NULL
|
||||
AFTER failure_reason;
|
||||
|
||||
ALTER TABLE generic_download_jobs
|
||||
ADD COLUMN assigned_cluster VARCHAR(128) DEFAULT NULL
|
||||
AFTER assigned_worker;
|
||||
|
||||
ALTER TABLE generic_download_jobs
|
||||
ADD COLUMN first_started_at TIMESTAMP NULL
|
||||
AFTER retry_at;
|
||||
|
||||
ALTER TABLE generic_download_jobs
|
||||
ADD COLUMN successfully_completed_at TIMESTAMP NULL
|
||||
AFTER first_started_at;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN first_started_at;
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN assigned_cluster;
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN assigned_worker;
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN successfully_completed_at;
|
||||
@@ -0,0 +1,19 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN assigned_worker VARCHAR(128) DEFAULT NULL
|
||||
AFTER last_assigned_worker;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN assigned_cluster VARCHAR(128) DEFAULT NULL
|
||||
AFTER assigned_worker;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN first_started_at TIMESTAMP NULL
|
||||
AFTER retry_at;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN successfully_completed_at TIMESTAMP NULL
|
||||
AFTER first_started_at;
|
||||
@@ -0,0 +1,6 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_download_jobs DROP COLUMN success_execution_millis;
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN success_execution_millis;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_download_jobs
|
||||
ADD COLUMN success_execution_millis INT(10) UNSIGNED DEFAULT NULL
|
||||
AFTER failure_reason;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN success_execution_millis INT(10) UNSIGNED DEFAULT NULL
|
||||
AFTER internal_debugging_failure_reason;
|
||||
@@ -0,0 +1,6 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_download_jobs DROP COLUMN success_inference_execution_millis;
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN success_inference_execution_millis;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_download_jobs
|
||||
ADD COLUMN success_inference_execution_millis INT(10) UNSIGNED DEFAULT NULL
|
||||
AFTER success_execution_millis;
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN success_inference_execution_millis INT(10) UNSIGNED DEFAULT NULL
|
||||
AFTER success_execution_millis;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs DROP COLUMN is_keepalive_required;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE generic_inference_jobs
|
||||
ADD COLUMN is_keepalive_required BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER priority_level;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
drop table password_resets;
|
||||
@@ -0,0 +1,51 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE password_resets (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Password hash "primary key"
|
||||
-- (ie. for the future when we have a support dashboard)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Foreign key to user
|
||||
user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Secret "key" for the password reset
|
||||
-- This will be shared via URL or user text input.
|
||||
secret_key VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Copied from the user record at the time of password reset issuance.
|
||||
-- If the user's password version is greater than this value, then this
|
||||
-- reset is no longer valid.
|
||||
current_password_version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- Username is a lookup key; display_name allows the user to add custom case.
|
||||
is_redeemed BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
-- For abuse tracking.
|
||||
-- Wide enough for IPv4/6
|
||||
ip_address_creation VARCHAR(40) NOT NULL,
|
||||
ip_address_redemption VARCHAR(40) NOT NULL,
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- When the password reset expires
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY fk_user_token (user_token),
|
||||
KEY index_secret_key (secret_key),
|
||||
KEY index_expires_at (expires_at)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,137 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE generic_download_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
|
||||
-- This is so the frontend client doesn't submit duplicate jobs.
|
||||
uuid_idempotency_token VARCHAR(36) NOT NULL,
|
||||
|
||||
-- ========== SUCCESS CASE ==========
|
||||
|
||||
-- If the job completes successfully, this is the result token.
|
||||
-- This is only populated on a successful result.
|
||||
on_success_downloaded_entity_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- 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
|
||||
-- Example types: 'hifigan', 'hifigan_rocket_vc' (codename for softvc), 'tacotron2', ...
|
||||
on_success_downloaded_entity_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- ========== UPLOAD DETAILS ==========
|
||||
|
||||
-- A "well defined" type of upload
|
||||
-- Examples: "hifigan", "tacotron2", etc.
|
||||
download_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Assume the same URL can be uploaded more than once (in case of errors or
|
||||
-- people sharing models)
|
||||
|
||||
download_url VARCHAR(512) NOT NULL,
|
||||
|
||||
-- The user-supplied title of the upload
|
||||
-- This might have different meanings for different upload types
|
||||
-- The "name" of the voice model, which might be complicated.
|
||||
-- If maybe_subject_token (etc.) is set, then it's authoritative instead.
|
||||
title VARCHAR(255) NOT NULL,
|
||||
|
||||
-- ========== CREATOR DETAILS AND PREFERENCES ==========
|
||||
|
||||
-- Foreign key to user
|
||||
creator_user_token VARCHAR(32) NOT 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',
|
||||
|
||||
-- ========== 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 (failure)
|
||||
-- * Attempt_Failed = job failed but may retry.
|
||||
-- * Dead = job failed permanently.
|
||||
--
|
||||
-- Pending -> Started -> Complete_Success
|
||||
-- |-> Complete_Failure
|
||||
-- \-> Attempt_Failed -> Started -> { Complete, Failed, Dead }
|
||||
status ENUM(
|
||||
'pending',
|
||||
'started',
|
||||
'complete_success',
|
||||
'complete_failure',
|
||||
'attempt_failed',
|
||||
'dead') NOT NULL DEFAULT 'pending',
|
||||
|
||||
-- We can track this against a "max_attempt_count"
|
||||
attempt_count INT(3) NOT NULL DEFAULT 0,
|
||||
|
||||
-- If there is a failure, tell the user why.
|
||||
failure_reason VARCHAR(512) 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,
|
||||
|
||||
-- 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),
|
||||
KEY fk_on_download_type (download_type),
|
||||
KEY fk_creator_user_token (creator_user_token),
|
||||
KEY index_status (status),
|
||||
KEY index_creator_ip_address (creator_ip_address)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,215 @@
|
||||
-- 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 ==========
|
||||
|
||||
-- Broad category of inference
|
||||
-- Examples (may not be up to date):
|
||||
-- * text_to_speech
|
||||
-- * voice_conversion
|
||||
inference_category VARCHAR(32) NOT NULL,
|
||||
|
||||
-- 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_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- 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,
|
||||
|
||||
-- ========== 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,
|
||||
|
||||
-- ========== 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,
|
||||
|
||||
-- ========== DEVELOPMENT AND DEBUGGING METADATA ==========
|
||||
|
||||
-- If true, the request gets a "debug" flag, which may do different
|
||||
-- things depending on the type of work.
|
||||
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.
|
||||
maybe_routing_tag VARCHAR(32) 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 (failure)
|
||||
-- * Attempt_Failed = job failed but may retry.
|
||||
-- * Dead = job failed permanently.
|
||||
--
|
||||
-- Pending -> Started -> Complete_Success
|
||||
-- |-> Complete_Failure
|
||||
-- \-> Attempt_Failed -> Started -> { Complete, Failed, Dead }
|
||||
status ENUM(
|
||||
'pending',
|
||||
'started',
|
||||
'complete_success',
|
||||
'complete_failure',
|
||||
'attempt_failed',
|
||||
'dead') NOT NULL DEFAULT 'pending',
|
||||
|
||||
-- We can track this against a "max_attempt_count"
|
||||
attempt_count SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
-- If there is a failure, tell the user why.
|
||||
failure_reason VARCHAR(512) DEFAULT NULL,
|
||||
|
||||
-- Optional internal-only debugging information in the case of failure.
|
||||
internal_debugging_failure_reason VARCHAR(512) 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),
|
||||
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 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_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)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,135 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE media_uploads (
|
||||
|
||||
-- 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,
|
||||
|
||||
-- ========== MEDIA DETAILS ==========
|
||||
|
||||
-- Type of media:
|
||||
-- * 'audio' for wav, mp3, etc.
|
||||
-- * 'image' for png, jpg, etc.
|
||||
-- * 'video' for a variety of video types.
|
||||
media_type VARCHAR(16) NOT NULL,
|
||||
|
||||
-- Where the media originated.
|
||||
-- * 'file' for user file uploads
|
||||
-- * 'device_api' for user device API sessions (eg. browser+microphone)
|
||||
-- * 'unknown' for unknown source
|
||||
media_source VARCHAR(16) NOT NULL,
|
||||
|
||||
-- The original filename of the media
|
||||
maybe_original_filename VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- The original (non-transcoded or truncated) file size
|
||||
original_file_size_bytes INT(10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- The original (non-transcoded or truncated) duration in millis.
|
||||
original_duration_millis INT(10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- The original file's mime type.
|
||||
maybe_original_mime_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Audio encoder details
|
||||
-- Only present if the file was audio or a video that had audio.
|
||||
maybe_original_audio_encoding VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- Video encoder details
|
||||
-- Only present if the file was a video.
|
||||
maybe_original_video_encoding VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- For videos, the original frame width.
|
||||
maybe_original_frame_width INT(5) DEFAULT NULL,
|
||||
|
||||
-- For videos, the original frame height.
|
||||
maybe_original_frame_height INT(5) DEFAULT NULL,
|
||||
|
||||
-- Checksum of the original media
|
||||
-- SHA1 hash [SHA2 = CHAR(64), SHA1 = CHAR(40), MD5 = CHAR(32)]
|
||||
-- checksum_sha1 CHAR(40) NOT NULL,
|
||||
|
||||
-- Checksum of the original media
|
||||
-- SHA2 hash [SHA2 = CHAR(64), SHA1 = CHAR(40), MD5 = CHAR(32)]
|
||||
-- Note that SHA2 is a hash family (SHA-228, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256, ...)
|
||||
-- and produces different lengths output depending on the choice of algorithm.
|
||||
checksum_sha2 CHAR(64) NOT NULL,
|
||||
|
||||
-- ========== UPLOAD, TRANSCODING, AND TRUNCATION DETAILS ==========
|
||||
|
||||
-- The hash for the bucket directory that contains the original upload
|
||||
-- as well as any transcodings, downsamplings, etc.
|
||||
public_bucket_directory_hash VARCHAR(32) NOT NULL,
|
||||
|
||||
-- We'll likely transcode (and potentially truncate) most media given to us.
|
||||
-- This will store a json-encoded struct that details the changes.
|
||||
-- TEXT = 65,535 bytes (64 KiB), ~= 4 bytes per UTF-8 character, ~ 16383 characters.
|
||||
maybe_extra_file_modification_info TEXT 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',
|
||||
|
||||
-- The synthetic id associated with this result.
|
||||
-- These ids are incremented on a per-user basis to help users
|
||||
-- sequence their own work. They serve no other purpose.
|
||||
maybe_creator_synthetic_id BIGINT(20) DEFAULT NULL,
|
||||
|
||||
-- ========== MODERATION DETAILS ==========
|
||||
|
||||
-- The last moderator that made changes last.
|
||||
-- We should also build an audit table to supersede this.
|
||||
maybe_mod_user_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- If this is removed by a mod or the creator.
|
||||
user_deleted_at TIMESTAMP NULL,
|
||||
mod_deleted_at TIMESTAMP NULL,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (uuid_idempotency_token),
|
||||
KEY index_media_type (media_type),
|
||||
KEY index_checksum_sha2 (checksum_sha2),
|
||||
KEY fk_maybe_creator_user_token (maybe_creator_user_token),
|
||||
KEY fk_maybe_mod_user_token (maybe_mod_user_token),
|
||||
KEY index_creator_ip_address (creator_ip_address),
|
||||
KEY index_user_deleted_at (user_deleted_at),
|
||||
KEY index_mod_deleted_at (mod_deleted_at)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -63,6 +63,7 @@ CREATE TABLE tts_inference_jobs (
|
||||
is_for_twitch BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- If true, the request gets routed to a special "debug" worker.
|
||||
-- NB: This has a *DIFFERENT* meaning on the generic_inference_jobs table.
|
||||
is_debug_request BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== PREMIUM FEATURES METADATA ==========
|
||||
|
||||
@@ -37,7 +37,8 @@ CREATE TABLE tts_model_upload_jobs (
|
||||
'tacotron2',
|
||||
'glowtts',
|
||||
'glowtts-vocodes',
|
||||
'talknet'
|
||||
'talknet',
|
||||
'vits'
|
||||
) NOT NULL DEFAULT 'not-set',
|
||||
|
||||
-- Can be linked to a well-known voice
|
||||
|
||||
@@ -19,7 +19,8 @@ CREATE TABLE tts_models (
|
||||
'tacotron2',
|
||||
'glowtts',
|
||||
'glowtts-vocodes',
|
||||
'talknet'
|
||||
'talknet',
|
||||
'vits'
|
||||
) NOT NULL DEFAULT 'not-set',
|
||||
|
||||
-- The name of the type of pipeline to use, eg "legacy_fakeyou", "legacy_vocodes", "english_v1", etc.
|
||||
@@ -225,6 +226,7 @@ CREATE TABLE tts_models (
|
||||
KEY index_private_bucket_hash (private_bucket_hash),
|
||||
KEY index_is_public_listing_approved (is_public_listing_approved),
|
||||
KEY index_is_locked_from_user_modification (is_locked_from_user_modification),
|
||||
KEY index_is_locked_from_use (is_locked_from_use)
|
||||
KEY index_is_locked_from_use (is_locked_from_use),
|
||||
KEY index_tts_model_type (tts_model_type)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE voice_conversion_models (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== MODEL FUNCTIONALITY ==========
|
||||
|
||||
-- The type of voice conversion model
|
||||
-- eg. 'rocket_vc' (codename for 'softvc'), 'diffsvc'
|
||||
model_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- If set, we'll use the vocoder defined.
|
||||
-- If not set, some global default will be used.
|
||||
maybe_vocoder_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- ========== MODEL DESCRIPTION ==========
|
||||
|
||||
-- The "name" of the voice model, which might be complicated.
|
||||
-- If maybe_subject_token (etc.) is set, then it's authoritative instead.
|
||||
title VARCHAR(255) NOT NULL,
|
||||
|
||||
-- The description of the model in markdown.
|
||||
description_markdown TEXT NOT NULL,
|
||||
|
||||
-- Generated HTML (not user-editable).
|
||||
description_rendered_html TEXT NOT NULL,
|
||||
|
||||
-- The full IETF BCP47 language tag (eg. en, en-US, es-419, ja-JP, pt, etc.)
|
||||
-- (Not that it matters apart from categorization, since voice conversion is universal.)
|
||||
ietf_language_tag VARCHAR(64) NOT NULL DEFAULT 'en',
|
||||
|
||||
-- The IETF BCP47 language tag's primary language subtag (eg. "es-419" becomes "es")
|
||||
-- (Not that it matters apart from categorization, since voice conversion is universal.)
|
||||
ietf_primary_language_subtag VARCHAR(12) NOT NULL DEFAULT 'en',
|
||||
|
||||
-- ========== MODEL PLACEMENT ==========
|
||||
|
||||
-- Whether the voice features on the front of FakeYou
|
||||
is_front_page_featured BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== IMMUTABLE PROVENANCE AND METADATA ==========
|
||||
|
||||
-- Where the file was originally downloaded (if it was downloaded)
|
||||
original_download_url VARCHAR(512) DEFAULT NULL,
|
||||
|
||||
-- The filename that was used at upload time (if available)
|
||||
original_filename VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- File characteristics
|
||||
file_size_bytes INT(10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== CREATOR DETAILS ==========
|
||||
|
||||
-- The person that created the template.
|
||||
creator_user_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- For abuse tracking.
|
||||
-- Wide enough for IPv4/6.
|
||||
-- This will pick up moderator IP addresses, but a future audit logs table
|
||||
-- will capture all edits.
|
||||
ip_address_creation VARCHAR(40) NOT NULL,
|
||||
ip_address_last_update VARCHAR(40) NOT NULL,
|
||||
|
||||
-- The last user to edit the model. This could be the creator or a moderator.
|
||||
-- Check the future audit logs table for more info.
|
||||
maybe_last_update_user_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- (THIS MIGHT NOT BE USED)
|
||||
-- NB: DO NOT SORT!
|
||||
-- THIS MUST MATCH THE RESPECTIVE JOBS TABLE.
|
||||
creator_set_visibility ENUM(
|
||||
'public',
|
||||
'hidden',
|
||||
'private'
|
||||
) NOT NULL DEFAULT 'public',
|
||||
|
||||
-- ========== BUCKET STORAGE ==========
|
||||
|
||||
-- The pytorch model
|
||||
-- For now, this will be a hash of the file contents.
|
||||
-- NB: NOT UNIQUE! We can allow duplicate uploads.
|
||||
private_bucket_hash CHAR(64) NOT NULL,
|
||||
|
||||
-- The "full url" version of the path
|
||||
private_bucket_object_name VARCHAR(255) NOT NULL,
|
||||
|
||||
-- ========== RATING AND RANKING ==========
|
||||
|
||||
-- Calculated average, on a scale of 0-100
|
||||
-- Null with zero ratings.
|
||||
-- calculated_average_score INT(3) DEFAULT NULL,
|
||||
|
||||
-- Other metrics
|
||||
-- calculated_total_ratings_submitted_count INT(10) NOT NULL DEFAULT 0,
|
||||
-- calculated_total_uses_count BIGINT(10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== MODERATION DETAILS ==========
|
||||
|
||||
-- Mods may have to approve of vc models for them to show up in a public index.
|
||||
-- Models can be used by the author (or other parties that know the URL) before
|
||||
-- they're approved, but unapproved models won't show up in public indices.
|
||||
-- This is independent of other visibility controls (is_mod_disabled, deleted_at,
|
||||
-- and creator_set_visibility)
|
||||
is_public_listing_approved BOOLEAN DEFAULT NULL,
|
||||
|
||||
-- Extremely popular models may be locked from deletion or modification by users.
|
||||
is_locked_from_user_modification BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- If a moderator has comments.
|
||||
maybe_mod_comments VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- If this is removed by a mod.
|
||||
-- It completely disappears from the system.
|
||||
user_deleted_at TIMESTAMP NULL,
|
||||
mod_deleted_at TIMESTAMP NULL,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY index_model_type (model_type),
|
||||
KEY fk_maybe_vocoder_token (maybe_vocoder_token),
|
||||
KEY fk_creator_user_token (creator_user_token),
|
||||
KEY index_creator_set_visibility (creator_set_visibility),
|
||||
KEY index_private_bucket_hash (private_bucket_hash),
|
||||
KEY index_is_public_listing_approved (is_public_listing_approved),
|
||||
KEY index_is_locked_from_user_modification (is_locked_from_user_modification)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,121 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
CREATE TABLE voice_conversion_results (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== INFERENCE DETAILS ==========
|
||||
|
||||
-- The TTS model that was used
|
||||
model_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Which media token was used as input (can be audio or video), potentially
|
||||
-- from a wide number of tables (eg. media_uploads, tts_results, etc.)
|
||||
media_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- For now we just support the `media_uploads` table, but we may grow to
|
||||
-- support media inputs from other areas of the system (eg. tts, video, etc.)
|
||||
media_token_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== CREATOR DETAILS ==========
|
||||
|
||||
-- The person that created the result
|
||||
-- If the user wasn't logged in, this is null
|
||||
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,
|
||||
|
||||
-- (THIS MIGHT NOT BE USED)
|
||||
-- NB: DO NOT SORT!
|
||||
-- THIS MUST MATCH THE RESPECTIVE JOBS TABLE.
|
||||
creator_set_visibility ENUM(
|
||||
'public',
|
||||
'hidden',
|
||||
'private'
|
||||
) NOT NULL DEFAULT 'public',
|
||||
|
||||
-- The synthetic id associated with this result.
|
||||
-- These ids are incremented on a per-user basis to help users
|
||||
-- sequence their own work. They serve no other purpose.
|
||||
maybe_creator_synthetic_id BIGINT(20) DEFAULT NULL,
|
||||
|
||||
-- ========== BUCKET STORAGE ==========
|
||||
|
||||
-- The hash lets us reconstitute the bucket directory
|
||||
-- location (which stores potentially several files)
|
||||
public_bucket_hash VARCHAR(64) NOT NULL,
|
||||
|
||||
-- Whether we're storing a wav result file.
|
||||
bucket_has_wav BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether we're storing a mp3 result file.
|
||||
bucket_has_mp3 BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether we're storing a mp4 result file.
|
||||
bucket_has_mp4 BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether we're storing a webm result file.
|
||||
bucket_has_webm BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether we're storing a spectrogram json file.
|
||||
bucket_has_spectrogram BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== METADATA ==========
|
||||
|
||||
file_size_bytes INT(10) NOT NULL DEFAULT 0,
|
||||
duration_millis INT(10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== INFERENCE METADATA, DC, ROUTING, DEBUGGING ==========
|
||||
|
||||
-- If true, the request was routed to a special "debug" worker.
|
||||
is_debug_request BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Whether we generated this result from our own data center (vs. cloud).
|
||||
is_generated_on_prem BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Worker hostname (linux hostname, k8s pod name)
|
||||
generated_by_worker VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Cluster name (k8s)
|
||||
generated_by_cluster VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- ========== MODERATION DETAILS ==========
|
||||
|
||||
-- The last user (possibly moderator) that made changes.
|
||||
-- See the future audit logs table for better info and accounting.
|
||||
maybe_last_update_user_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- If this is removed by a mod or the creator.
|
||||
user_deleted_at TIMESTAMP NULL,
|
||||
mod_deleted_at TIMESTAMP NULL,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
KEY fk_model_token (model_token),
|
||||
KEY fk_media_token (media_token),
|
||||
KEY fk_media_token_and_media_token_type (media_token, media_token_type),
|
||||
KEY fk_maybe_creator_user_token (maybe_creator_user_token),
|
||||
KEY fk_maybe_creator_anonymous_visitor_token (maybe_creator_anonymous_visitor_token),
|
||||
KEY index_creator_ip_address (creator_ip_address),
|
||||
KEY index_user_deleted_at(user_deleted_at),
|
||||
KEY index_mod_deleted_at(mod_deleted_at),
|
||||
KEY index_created_at(created_at)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
DROP TABLE voice_survey_answers;
|
||||
@@ -0,0 +1,53 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Voice survey answers
|
||||
CREATE TABLE voice_survey_answers (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- Effective "primary key" (PUBLIC)
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- Idempotency token from client
|
||||
-- This is so the frontend client doesn't submit duplicate items.
|
||||
uuid_idempotency_token VARCHAR(36) NOT NULL,
|
||||
|
||||
-- User making the comment
|
||||
maybe_user_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- The voice that is being requested
|
||||
voice_name VARCHAR(128) NOT NULL,
|
||||
|
||||
-- If the person would pay for FakeYou premium
|
||||
would_pay BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- How much the user would hypothetically pay per month
|
||||
would_pay_amount DOUBLE DEFAULT NULL,
|
||||
|
||||
-- For abuse tracking.
|
||||
-- Wide enough for IPv4/6
|
||||
creator_ip_address VARCHAR(40) NOT NULL,
|
||||
|
||||
-- ========== VECTOR CLOCK ==========
|
||||
|
||||
-- Incremented with every update.
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token),
|
||||
UNIQUE KEY (uuid_idempotency_token),
|
||||
KEY index_maybe_user_token (maybe_user_token),
|
||||
KEY index_voice_name (voice_name),
|
||||
KEY index_would_pay (would_pay),
|
||||
KEY index_would_pay_amount (would_pay_amount),
|
||||
KEY index_created_at (created_at)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
+1
-1
@@ -17,7 +17,7 @@ SQLITE_DATABASE_PATH=./runtime_data/database.db
|
||||
build_shared_mysql_database_library() {
|
||||
# NB: For now, this is our monolithic DB that serves all of our microservices (gross)
|
||||
# It's a single package so that queries can be shared (again, gross)
|
||||
pushd crates/lib/database_queries
|
||||
pushd crates/lib/mysql_queries
|
||||
SQLX_OFFLINE=true cargo sqlx prepare --merged
|
||||
popd
|
||||
}
|
||||
|
||||
@@ -3,3 +3,6 @@
|
||||
|
||||
# Just an example
|
||||
/exact/match/path
|
||||
|
||||
# Broken Python script
|
||||
/tts/job/None
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# This broken Python script has been around since at least the DDoS time
|
||||
# But now it's actively spamming the logs at 100QPS on single nodes!
|
||||
# It's from a single IP address, which we'll block:
|
||||
|
||||
# Unbanning for now as the code fix should resolve the issue.
|
||||
# 104.251.211.22
|
||||
@@ -0,0 +1,46 @@
|
||||
# These IPv6 were blocked within Cloudflare. The blast radius seemed to be too big - it hit Paul and other users.
|
||||
|
||||
# From Cloudflare list I created called "top_attacker_ips":
|
||||
# (These were created around March 9th - March 11th.)
|
||||
# 2400:8500:1302:775::/64
|
||||
# 2a01:4f8:c17:750::/64
|
||||
|
||||
# From Cloudflare list I created called "attacker_ips_v2":
|
||||
# (These were created around March 9th.)
|
||||
# 2001:448a:2061:2fc7::/64
|
||||
# 2001:569:be9b:8c00::/64
|
||||
# 2001:818:ea7c:5500::/64
|
||||
# 2001:871:266:4f57::/64
|
||||
# 2001:9e8:2478:9c00::/64
|
||||
# 2001:bc8:47b0:1719::/64
|
||||
# 2003:e0:712:9e80::/64
|
||||
# 2401:4900:190a:9085::/64
|
||||
# 2401:4900:60e2:41ca::/64
|
||||
# 2405:201:580b:7020::/64
|
||||
# 2405:201:a42e:c014::/64
|
||||
# 2405:3800:811:bd79::/64
|
||||
# 2409:4089:aa84:92f5::/64
|
||||
# 2600:387:f:5831::/64
|
||||
# 2800:200:e200:1307::/64
|
||||
# 2800:200:e800:2e69::/64
|
||||
# 2800:200:f140:33f::/64
|
||||
# 2800:a4:1a10:6200::/64
|
||||
# 2800:af0:103b:4871::/64
|
||||
# 2800:e2:637f:fcc1::/64
|
||||
# 2804:431:c7d9:8aa0::/64
|
||||
# 2804:7efc:42a:3901::/64
|
||||
# 2806:2a0:43c:82cb::/64
|
||||
# 2806:2f0:72a0:fef9::/64
|
||||
# 2a01:4f8:c17:750::/64
|
||||
# 2a01:c23:8d83:9200::/64
|
||||
# 2a01:cb06:2f9:da00::/64
|
||||
# 2a02:2f08:1201:2c00::/64
|
||||
# 2a02:2f08:6917:eb00::/64
|
||||
# 2a02:2f0d:b819:cb00::/64
|
||||
# 2a02:8084:61a3:db00::/64
|
||||
# 2a03:b0c0:3:d0::/64
|
||||
# 2a0c:5a80:4604:2100::/64
|
||||
|
||||
# From Cloudflare list I created called "attacker_ips":
|
||||
# (These were created around March 9th.)
|
||||
# (None)
|
||||
@@ -0,0 +1,28 @@
|
||||
# There's another ongoing DDoS, but it appears to be Python clients
|
||||
|
||||
# Top client appears to be using Python/3.10 aiohttp/3.8.3
|
||||
# Second client appears to be using python-urllib3/1.26.12
|
||||
# /tts/job/None is the top URL (191M)
|
||||
# /tts/queue_length is the second most visited URL (36k)
|
||||
|
||||
# /tts/job/None (191M requests, lots of IPs)
|
||||
104.251.211.22
|
||||
47.253.48.57
|
||||
81.56.107.8
|
||||
13.234.107.200
|
||||
104.247.114.86
|
||||
66.214.82.240
|
||||
|
||||
# Unban on 2023-05-19:
|
||||
# Vegito1089: I know you are super busy but is it possible to unblock this IP address?
|
||||
# This one paying customer refuses refunds and says he really wants to keep using our website.
|
||||
# His IP got blocked during the second DDOS attack
|
||||
# Vegito1089: 38.25.15.183
|
||||
# 38.25.15.183
|
||||
|
||||
# 2600:1700:4d40:4920:ac48:939e:b6c:9e7
|
||||
# 2800:bf0:10b:f82:1516:7cdc:974a:17e8
|
||||
|
||||
# /tts/queue_length (14k requests, just one IP)
|
||||
173.81.41.29
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+72
@@ -0,0 +1,72 @@
|
||||
# It looks like 101soundboards has fewer IP addresses they can use (relative to user accounts).
|
||||
# IPv4 addresses are the primary pool.
|
||||
|
||||
104.143.54.63
|
||||
141.98.84.147
|
||||
141.98.84.173
|
||||
141.98.84.44
|
||||
141.98.84.57
|
||||
147.78.181.146
|
||||
147.78.183.60
|
||||
174.107.171.93
|
||||
176.119.141.136
|
||||
178.20.30.32
|
||||
185.102.112.120
|
||||
185.102.113.129
|
||||
185.102.113.94
|
||||
185.152.92.89
|
||||
185.61.216.111
|
||||
185.61.216.174
|
||||
185.61.221.200
|
||||
185.81.144.108
|
||||
185.81.144.90
|
||||
185.81.145.102
|
||||
185.81.145.168
|
||||
185.81.145.76
|
||||
185.88.100.90
|
||||
185.89.100.27
|
||||
185.96.37.100
|
||||
185.96.37.83
|
||||
193.202.82.158
|
||||
193.203.10.225
|
||||
193.203.11.59
|
||||
193.31.126.43
|
||||
194.156.124.101
|
||||
204.116.214.102
|
||||
212.119.44.13
|
||||
212.119.46.138
|
||||
212.119.46.69
|
||||
212.119.47.163
|
||||
212.119.47.178
|
||||
212.119.47.99
|
||||
212.60.20.209
|
||||
212.60.21.120
|
||||
213.108.0.114
|
||||
213.108.0.140
|
||||
213.108.0.157
|
||||
213.108.0.179
|
||||
213.108.0.235
|
||||
213.108.0.60
|
||||
213.108.3.105
|
||||
213.108.3.14
|
||||
45.10.164.163
|
||||
45.10.164.26
|
||||
45.10.164.30
|
||||
45.10.167.215
|
||||
45.138.100.15
|
||||
45.148.234.61
|
||||
45.66.208.149
|
||||
45.66.208.222
|
||||
5.181.169.143
|
||||
5.181.169.167
|
||||
5.181.169.220
|
||||
5.181.169.35
|
||||
5.181.169.83
|
||||
5.183.252.70
|
||||
72.219.85.206
|
||||
76.0.25.232
|
||||
77.220.192.46
|
||||
83.142.52.192
|
||||
83.142.54.125
|
||||
83.142.55.165
|
||||
98.143.187.29
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
# It looks like 101soundboards has fewer IP addresses they can use (relative to user accounts).
|
||||
# They have a few IPv6 addresses that are infrequently used.
|
||||
|
||||
# TODO: Support IPv6 addresses and CIDRs
|
||||
# 2600:6c64:4c7f:f11f:4171:9854:beed:6dde
|
||||
# 2601:205:c380:6810:5860:82ac:f25c:81de
|
||||
# 2601:300:4400:3290:1864:2e36:fdab:dd9b
|
||||
# 2601:648:8300:4cc0:a9c7:d8bc:9614:c76d
|
||||
# 2603:9001:3f00:4e29:e4e9:56c0:ffc:f1d5
|
||||
+1064
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
use crate::public::media_uploads::directory::MediaUploadDirectory;
|
||||
use crate::public::public_path::PublicPath;
|
||||
use crockford::crockford_entropy_lower;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const ORIGINAL_FILE_BASENAME : &'static str = "original_upload.bin";
|
||||
|
||||
@@ -37,6 +38,10 @@ impl MediaUploadOriginalFilePath {
|
||||
&self.full_object_path
|
||||
}
|
||||
|
||||
pub fn to_full_object_pathbuf(&self) -> PathBuf {
|
||||
PathBuf::from(&self.full_object_path)
|
||||
}
|
||||
|
||||
pub fn get_directory(&self) -> &MediaUploadDirectory {
|
||||
&self.directory
|
||||
}
|
||||
@@ -53,6 +58,7 @@ impl MediaUploadOriginalFilePath {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::public::media_uploads::original_file::MediaUploadOriginalFilePath;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
pub fn generate_new_entropy() {
|
||||
@@ -67,6 +73,12 @@ mod tests {
|
||||
assert_eq!(file.get_full_object_path_str(), "/media_upload/a/b/c/d/e/abcdefghijk/original_upload.bin");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn to_full_object_pathbuf() {
|
||||
let file = MediaUploadOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
assert_eq!(file.to_full_object_pathbuf(), PathBuf::from("/media_upload/a/b/c/d/e/abcdefghijk/original_upload.bin"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str_short_name() {
|
||||
let file = MediaUploadOriginalFilePath::from_object_hash("foo");
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod media_uploads;
|
||||
pub mod public_path;
|
||||
pub mod public_path;
|
||||
pub mod voice_conversion_results;
|
||||
@@ -0,0 +1,63 @@
|
||||
use crate::public::public_path::PublicPath;
|
||||
use crate::util::hashed_directory_path_long_string::hashed_directory_path_long_string;
|
||||
|
||||
// TODO: Generate these from a macro.
|
||||
|
||||
// TODO: Use a central path registry for quick reference
|
||||
const DIRECTORY: &'static str = "/voice_conversion";
|
||||
|
||||
/// Directory for voice conversion results.
|
||||
/// Each result gets its own directory so that we can store the result
|
||||
/// alongside metadata and re-processed derivatives.
|
||||
#[derive(Clone)]
|
||||
pub struct VoiceConversionResultDirectory {
|
||||
object_hash: String,
|
||||
directory: String,
|
||||
}
|
||||
|
||||
impl PublicPath for VoiceConversionResultDirectory {}
|
||||
|
||||
impl VoiceConversionResultDirectory {
|
||||
|
||||
pub fn from_public_bucket_directory_hash(object_hash: &str) -> Self {
|
||||
// TODO: Path construction could be cleaner.
|
||||
let middle = hashed_directory_path_long_string(object_hash);
|
||||
let directory = format!("{}/{}{}", DIRECTORY, middle, object_hash);
|
||||
Self {
|
||||
object_hash: object_hash.to_string(),
|
||||
directory,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_directory_path_str(&self) -> &str {
|
||||
&self.directory
|
||||
}
|
||||
|
||||
pub fn get_object_hash(&self) -> &str {
|
||||
&self.object_hash
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::public::voice_conversion_results::directory::VoiceConversionResultDirectory;
|
||||
|
||||
#[test]
|
||||
pub fn get_directory_path_str() {
|
||||
let directory = VoiceConversionResultDirectory::from_public_bucket_directory_hash("abcdefghijk");
|
||||
assert_eq!(directory.get_directory_path_str(), "/voice_conversion/a/b/c/d/e/abcdefghijk");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_directory_path_str_short_name() {
|
||||
let directory = VoiceConversionResultDirectory::from_public_bucket_directory_hash("foo");
|
||||
assert_eq!(directory.get_directory_path_str(), "/voice_conversion/f/o/foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_object_hash() {
|
||||
let hash = "abcdefghijk";
|
||||
let directory = VoiceConversionResultDirectory::from_public_bucket_directory_hash(hash);
|
||||
assert_eq!(directory.get_object_hash(), hash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod directory;
|
||||
pub mod original_file;
|
||||
@@ -0,0 +1,105 @@
|
||||
use crate::public::public_path::PublicPath;
|
||||
use crate::public::voice_conversion_results::directory::VoiceConversionResultDirectory;
|
||||
use crockford::crockford_entropy_lower;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const ORIGINAL_FILE_PREFIX : &'static str = "fakeyou_";
|
||||
const ORIGINAL_FILE_SUFFIX : &'static str = ".wav";
|
||||
|
||||
// TODO: Generate these from a macro.
|
||||
|
||||
/// The original user upload file.
|
||||
/// It may have derivative files (down samples, crops, etc.) that live alongside it.
|
||||
#[derive(Clone)]
|
||||
pub struct VoiceConversionResultOriginalFilePath {
|
||||
directory: VoiceConversionResultDirectory,
|
||||
basename: String,
|
||||
full_object_path: String,
|
||||
}
|
||||
|
||||
impl PublicPath for VoiceConversionResultOriginalFilePath {}
|
||||
|
||||
impl VoiceConversionResultOriginalFilePath {
|
||||
|
||||
pub fn generate_new() -> Self {
|
||||
let entropy = crockford_entropy_lower(32);
|
||||
Self::from_object_hash(&entropy)
|
||||
}
|
||||
|
||||
pub fn from_object_hash(hash: &str) -> Self {
|
||||
// TODO: Path construction could be cleaner.
|
||||
let directory = VoiceConversionResultDirectory::from_public_bucket_directory_hash(hash);
|
||||
let basename = format!("{}{}{}", ORIGINAL_FILE_PREFIX, hash, ORIGINAL_FILE_SUFFIX);
|
||||
let full_object_path = format!("{}/{}{}{}", directory.get_directory_path_str(), ORIGINAL_FILE_PREFIX, hash, ORIGINAL_FILE_SUFFIX);
|
||||
Self {
|
||||
directory,
|
||||
basename,
|
||||
full_object_path,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_full_object_path_str(&self) -> &str {
|
||||
&self.full_object_path
|
||||
}
|
||||
|
||||
pub fn to_full_object_pathbuf(&self) -> PathBuf {
|
||||
PathBuf::from(&self.full_object_path)
|
||||
}
|
||||
|
||||
pub fn get_directory(&self) -> &VoiceConversionResultDirectory {
|
||||
&self.directory
|
||||
}
|
||||
|
||||
pub fn get_object_hash(&self) -> &str {
|
||||
&self.directory.get_object_hash()
|
||||
}
|
||||
|
||||
pub fn get_basename(&self) -> &str {
|
||||
&self.basename
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::public::voice_conversion_results::original_file::VoiceConversionResultOriginalFilePath;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
pub fn generate_new_entropy() {
|
||||
let file = VoiceConversionResultOriginalFilePath::generate_new();
|
||||
assert_eq!(file.get_object_hash().len(), 32);
|
||||
assert_eq!(file.get_directory().get_object_hash().len(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str() {
|
||||
let file = VoiceConversionResultOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
assert_eq!(file.get_full_object_path_str(), "/voice_conversion/a/b/c/d/e/abcdefghijk/fakeyou_abcdefghijk.wav");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn to_full_object_pathbuf() {
|
||||
let file = VoiceConversionResultOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
assert_eq!(file.to_full_object_pathbuf(), PathBuf::from("/voice_conversion/a/b/c/d/e/abcdefghijk/fakeyou_abcdefghijk.wav"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str_short_name() {
|
||||
let file = VoiceConversionResultOriginalFilePath::from_object_hash("foo");
|
||||
assert_eq!(file.get_full_object_path_str(), "/voice_conversion/f/o/foo/fakeyou_foo.wav");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_full_object_path_str_starts_with_directory() {
|
||||
let file = VoiceConversionResultOriginalFilePath::from_object_hash("abcdefghijk");
|
||||
let full_path = file.get_full_object_path_str();
|
||||
assert!(full_path.starts_with(file.get_directory().get_directory_path_str()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_object_hash() {
|
||||
let hash = "abcdefghijk";
|
||||
let file = VoiceConversionResultOriginalFilePath::from_object_hash(hash);
|
||||
assert_eq!(file.get_object_hash(), hash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
/// Used in the `audit_logs` table in a `VARCHAR(32)` field named `entity_action`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
pub enum AuditLogEntityAction {
|
||||
/// Create action
|
||||
#[serde(rename = "create")]
|
||||
Create,
|
||||
|
||||
/// Edit action
|
||||
#[serde(rename = "edit")]
|
||||
Edit,
|
||||
|
||||
/// Delete action
|
||||
#[serde(rename = "delete")]
|
||||
Delete,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(AuditLogEntityAction);
|
||||
impl_mysql_enum_coders!(AuditLogEntityAction);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl AuditLogEntityAction {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Create => "create",
|
||||
Self::Edit => "edit",
|
||||
Self::Delete => "delete",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"create" => Ok(Self::Create),
|
||||
"edit" => Ok(Self::Edit),
|
||||
"delete" => Ok(Self::Delete),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::audit_logs::audit_log_entity_action::AuditLogEntityAction;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(AuditLogEntityAction::Create, "create");
|
||||
assert_serialization(AuditLogEntityAction::Edit, "edit");
|
||||
assert_serialization(AuditLogEntityAction::Delete, "delete");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
assert_eq!(AuditLogEntityAction::Create.to_str(), "create");
|
||||
assert_eq!(AuditLogEntityAction::Edit.to_str(), "edit");
|
||||
assert_eq!(AuditLogEntityAction::Delete.to_str(), "delete");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(AuditLogEntityAction::from_str("create").unwrap(), AuditLogEntityAction::Create);
|
||||
assert_eq!(AuditLogEntityAction::from_str("edit").unwrap(), AuditLogEntityAction::Edit);
|
||||
assert_eq!(AuditLogEntityAction::from_str("delete").unwrap(), AuditLogEntityAction::Delete);
|
||||
assert!(AuditLogEntityAction::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
/// Used in the `audit_logs` table in a `VARCHAR(32)` field named `entity_type`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
pub enum AuditLogEntityType {
|
||||
/// Comment system
|
||||
#[serde(rename = "comment")]
|
||||
Comment,
|
||||
|
||||
/// TTS model (architecture does not matter)
|
||||
#[serde(rename = "tts_model")]
|
||||
TtsModel,
|
||||
|
||||
/// TTS result (architecture does not matter)
|
||||
#[serde(rename = "tts_result")]
|
||||
TtsResult,
|
||||
|
||||
/// W2L template
|
||||
#[serde(rename = "w2l_template")]
|
||||
W2lTemplate,
|
||||
|
||||
/// W2L result
|
||||
#[serde(rename = "w2l_result")]
|
||||
W2lResult,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(AuditLogEntityType);
|
||||
impl_mysql_enum_coders!(AuditLogEntityType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl AuditLogEntityType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Comment => "comment",
|
||||
Self::TtsModel => "tts_model",
|
||||
Self::TtsResult => "tts_result",
|
||||
Self::W2lTemplate => "w2l_template",
|
||||
Self::W2lResult => "w2l_result",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"comment" => Ok(Self::Comment),
|
||||
"tts_model" => Ok(Self::TtsModel),
|
||||
"tts_result" => Ok(Self::TtsResult),
|
||||
"w2l_template" => Ok(Self::W2lTemplate),
|
||||
"w2l_result" => Ok(Self::W2lResult),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::audit_logs::audit_log_entity_type::AuditLogEntityType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(AuditLogEntityType::Comment, "comment");
|
||||
assert_serialization(AuditLogEntityType::TtsModel, "tts_model");
|
||||
assert_serialization(AuditLogEntityType::TtsResult, "tts_result");
|
||||
assert_serialization(AuditLogEntityType::W2lTemplate, "w2l_template");
|
||||
assert_serialization(AuditLogEntityType::W2lResult, "w2l_result");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
assert_eq!(AuditLogEntityType::Comment.to_str(), "comment");
|
||||
assert_eq!(AuditLogEntityType::TtsModel.to_str(), "tts_model");
|
||||
assert_eq!(AuditLogEntityType::TtsResult.to_str(), "tts_result");
|
||||
assert_eq!(AuditLogEntityType::W2lTemplate.to_str(), "w2l_template");
|
||||
assert_eq!(AuditLogEntityType::W2lResult.to_str(), "w2l_result");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(AuditLogEntityType::from_str("comment").unwrap(), AuditLogEntityType::Comment);
|
||||
assert_eq!(AuditLogEntityType::from_str("tts_model").unwrap(), AuditLogEntityType::TtsModel);
|
||||
assert_eq!(AuditLogEntityType::from_str("tts_result").unwrap(), AuditLogEntityType::TtsResult);
|
||||
assert_eq!(AuditLogEntityType::from_str("w2l_template").unwrap(), AuditLogEntityType::W2lTemplate);
|
||||
assert_eq!(AuditLogEntityType::from_str("w2l_result").unwrap(), AuditLogEntityType::W2lResult);
|
||||
assert!(AuditLogEntityType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod audit_log_entity_action;
|
||||
pub mod audit_log_entity_type;
|
||||
@@ -0,0 +1,102 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
/// Used in the `comments` table in a `VARCHAR(32)` field named `entity_type`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
pub enum CommentEntityType {
|
||||
/// User
|
||||
#[serde(rename = "user")]
|
||||
User,
|
||||
|
||||
/// TTS model (architecture does not matter)
|
||||
#[serde(rename = "tts_model")]
|
||||
TtsModel,
|
||||
|
||||
/// TTS result (architecture does not matter)
|
||||
#[serde(rename = "tts_result")]
|
||||
TtsResult,
|
||||
|
||||
/// W2L template
|
||||
#[serde(rename = "w2l_template")]
|
||||
W2lTemplate,
|
||||
|
||||
/// W2L result
|
||||
#[serde(rename = "w2l_result")]
|
||||
W2lResult,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(CommentEntityType);
|
||||
impl_mysql_enum_coders!(CommentEntityType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl CommentEntityType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::User => "user",
|
||||
Self::TtsModel => "tts_model",
|
||||
Self::TtsResult => "tts_result",
|
||||
Self::W2lTemplate => "w2l_template",
|
||||
Self::W2lResult => "w2l_result",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"user" => Ok(Self::User),
|
||||
"tts_model" => Ok(Self::TtsModel),
|
||||
"tts_result" => Ok(Self::TtsResult),
|
||||
"w2l_template" => Ok(Self::W2lTemplate),
|
||||
"w2l_result" => Ok(Self::W2lResult),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::comments::comment_entity_type::CommentEntityType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(CommentEntityType::User, "user");
|
||||
assert_serialization(CommentEntityType::TtsModel, "tts_model");
|
||||
assert_serialization(CommentEntityType::TtsResult, "tts_result");
|
||||
assert_serialization(CommentEntityType::W2lTemplate, "w2l_template");
|
||||
assert_serialization(CommentEntityType::W2lResult, "w2l_result");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
assert_eq!(CommentEntityType::User.to_str(), "user");
|
||||
assert_eq!(CommentEntityType::TtsModel.to_str(), "tts_model");
|
||||
assert_eq!(CommentEntityType::TtsResult.to_str(), "tts_result");
|
||||
assert_eq!(CommentEntityType::W2lTemplate.to_str(), "w2l_template");
|
||||
assert_eq!(CommentEntityType::W2lResult.to_str(), "w2l_result");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(CommentEntityType::from_str("user").unwrap(), CommentEntityType::User);
|
||||
assert_eq!(CommentEntityType::from_str("tts_model").unwrap(), CommentEntityType::TtsModel);
|
||||
assert_eq!(CommentEntityType::from_str("tts_result").unwrap(), CommentEntityType::TtsResult);
|
||||
assert_eq!(CommentEntityType::from_str("w2l_template").unwrap(), CommentEntityType::W2lTemplate);
|
||||
assert_eq!(CommentEntityType::from_str("w2l_result").unwrap(), CommentEntityType::W2lResult);
|
||||
assert!(CommentEntityType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod comment_entity_type;
|
||||
+32
-1
@@ -22,6 +22,12 @@ pub enum GenericDownloadType {
|
||||
#[sqlx(rename = "hifigan_rocket_vc")]
|
||||
HifiGanRocketVc,
|
||||
|
||||
/// NB: Note - this is hifigan for SoVitsSvc
|
||||
/// Some work will need to be done to unify this with other hifigan types.
|
||||
#[serde(rename = "hifigan_so_vits_svc")]
|
||||
#[sqlx(rename = "hifigan_so_vits_svc")]
|
||||
HifiGanSoVitsSvc,
|
||||
|
||||
//#[serde(rename = "melgan_vocodes")]
|
||||
//#[sqlx(rename = "melgan_vocodes")]
|
||||
//MelGanVocodes,
|
||||
@@ -32,10 +38,20 @@ pub enum GenericDownloadType {
|
||||
#[sqlx(rename = "rocket_vc")]
|
||||
RocketVc,
|
||||
|
||||
/// so-vits-svc voice conversion models
|
||||
#[serde(rename = "so_vits_svc")]
|
||||
#[sqlx(rename = "so_vits_svc")]
|
||||
SoVitsSvc,
|
||||
|
||||
/// Tacotron TTS models.
|
||||
#[serde(rename = "tacotron2")]
|
||||
#[sqlx(rename = "tacotron2")]
|
||||
Tacotron2,
|
||||
|
||||
/// VITS TTS models.
|
||||
#[serde(rename = "vits")]
|
||||
#[sqlx(rename = "vits")]
|
||||
Vits,
|
||||
}
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
@@ -44,8 +60,11 @@ impl GenericDownloadType {
|
||||
match self {
|
||||
Self::HifiGan => "hifigan",
|
||||
Self::HifiGanRocketVc => "hifigan_rocket_vc",
|
||||
Self::HifiGanSoVitsSvc => "hifigan_so_vits_svc",
|
||||
Self::RocketVc => "rocket_vc",
|
||||
Self::SoVitsSvc => "so_vits_svc",
|
||||
Self::Tacotron2 => "tacotron2",
|
||||
Self::Vits => "vits",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +72,11 @@ impl GenericDownloadType {
|
||||
match value {
|
||||
"hifigan" => Ok(Self::HifiGan),
|
||||
"hifigan_rocket_vc" => Ok(Self::HifiGanRocketVc),
|
||||
"hifigan_so_vits_svc" => Ok(Self::HifiGanSoVitsSvc),
|
||||
"rocket_vc" => Ok(Self::RocketVc),
|
||||
"so_vits_svc" => Ok(Self::SoVitsSvc),
|
||||
"tacotron2" => Ok(Self::Tacotron2),
|
||||
"vits" => Ok(Self::Vits),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -62,30 +84,39 @@ impl GenericDownloadType {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::workers::generic_download_type::GenericDownloadType;
|
||||
use crate::by_table::generic_download_jobs::generic_download_type::GenericDownloadType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(GenericDownloadType::HifiGan, "hifigan");
|
||||
assert_serialization(GenericDownloadType::HifiGanRocketVc, "hifigan_rocket_vc");
|
||||
assert_serialization(GenericDownloadType::HifiGanSoVitsSvc, "hifigan_so_vits_svc");
|
||||
assert_serialization(GenericDownloadType::RocketVc, "rocket_vc");
|
||||
assert_serialization(GenericDownloadType::SoVitsSvc, "so_vits_svc");
|
||||
assert_serialization(GenericDownloadType::Tacotron2, "tacotron2");
|
||||
assert_serialization(GenericDownloadType::Vits, "vits");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(GenericDownloadType::HifiGan.to_str(), "hifigan");
|
||||
assert_eq!(GenericDownloadType::HifiGanRocketVc.to_str(), "hifigan_rocket_vc");
|
||||
assert_eq!(GenericDownloadType::HifiGanSoVitsSvc.to_str(), "hifigan_so_vits_svc");
|
||||
assert_eq!(GenericDownloadType::RocketVc.to_str(), "rocket_vc");
|
||||
assert_eq!(GenericDownloadType::SoVitsSvc.to_str(), "so_vits_svc");
|
||||
assert_eq!(GenericDownloadType::Tacotron2.to_str(), "tacotron2");
|
||||
assert_eq!(GenericDownloadType::Vits.to_str(), "vits");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(GenericDownloadType::from_str("hifigan").unwrap(), GenericDownloadType::HifiGan);
|
||||
assert_eq!(GenericDownloadType::from_str("hifigan_rocket_vc").unwrap(), GenericDownloadType::HifiGanRocketVc);
|
||||
assert_eq!(GenericDownloadType::from_str("hifigan_so_vits_svc").unwrap(), GenericDownloadType::HifiGanSoVitsSvc);
|
||||
assert_eq!(GenericDownloadType::from_str("rocket_vc").unwrap(), GenericDownloadType::RocketVc);
|
||||
assert_eq!(GenericDownloadType::from_str("so_vits_svc").unwrap(), GenericDownloadType::SoVitsSvc);
|
||||
assert_eq!(GenericDownloadType::from_str("tacotron2").unwrap(), GenericDownloadType::Tacotron2);
|
||||
assert_eq!(GenericDownloadType::from_str("vits").unwrap(), GenericDownloadType::Vits);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod generic_download_type;
|
||||
@@ -0,0 +1,93 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
|
||||
/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `inference_category`.
|
||||
///
|
||||
/// Our "generic inference" pipeline supports a wide variety of ML models and other media.
|
||||
/// Each "category" of inference is identified by the following enum variants.
|
||||
/// These types are present in the HTTP API and database columns as serialized here.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
pub enum InferenceCategory {
|
||||
#[serde(rename = "text_to_speech")]
|
||||
TextToSpeech,
|
||||
|
||||
#[serde(rename = "voice_conversion")]
|
||||
VoiceConversion,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(InferenceCategory);
|
||||
impl_mysql_enum_coders!(InferenceCategory);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl InferenceCategory {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::TextToSpeech => "text_to_speech",
|
||||
Self::VoiceConversion => "voice_conversion",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"text_to_speech" => Ok(Self::TextToSpeech),
|
||||
"voice_conversion" => Ok(Self::VoiceConversion),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
// NB: BTreeSet is sorted
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
Self::TextToSpeech,
|
||||
Self::VoiceConversion,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(InferenceCategory::TextToSpeech, "text_to_speech");
|
||||
assert_serialization(InferenceCategory::VoiceConversion, "voice_conversion");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(InferenceCategory::TextToSpeech.to_str(), "text_to_speech");
|
||||
assert_eq!(InferenceCategory::VoiceConversion.to_str(), "voice_conversion");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(InferenceCategory::from_str("text_to_speech").unwrap(), InferenceCategory::TextToSpeech);
|
||||
assert_eq!(InferenceCategory::from_str("voice_conversion").unwrap(), InferenceCategory::VoiceConversion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
let mut variants = InferenceCategory::all_variants();
|
||||
assert_eq!(variants.len(), 2);
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::TextToSpeech));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::VoiceConversion));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
|
||||
// Generated check
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(InferenceCategory::all_variants().len(), InferenceCategory::iter().len());
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
|
||||
/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `maybe_input_source_token`.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
pub enum InferenceInputSourceTokenType {
|
||||
#[serde(rename = "media_upload")]
|
||||
MediaUpload,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(InferenceInputSourceTokenType);
|
||||
impl_mysql_enum_coders!(InferenceInputSourceTokenType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl InferenceInputSourceTokenType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::MediaUpload => "media_upload",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"media_upload" => Ok(Self::MediaUpload),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<InferenceInputSourceTokenType> {
|
||||
// NB: BTreeSet is sorted
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
InferenceInputSourceTokenType::MediaUpload,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::generic_inference_jobs::inference_input_source_token_type::InferenceInputSourceTokenType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(InferenceInputSourceTokenType::MediaUpload, "media_upload");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(InferenceInputSourceTokenType::MediaUpload.to_str(), "media_upload");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(InferenceInputSourceTokenType::from_str("media_upload").unwrap(), InferenceInputSourceTokenType::MediaUpload);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
let mut variants = InferenceInputSourceTokenType::all_variants();
|
||||
assert_eq!(variants.len(), 1);
|
||||
assert_eq!(variants.pop_first(), Some(InferenceInputSourceTokenType::MediaUpload));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
|
||||
// Generated check
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(InferenceInputSourceTokenType::all_variants().len(), InferenceInputSourceTokenType::iter().len());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
|
||||
|
||||
/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `maybe_model_type`.
|
||||
///
|
||||
/// Our "generic inference" pipeline supports a wide variety of ML models and other media.
|
||||
/// Each inference "model type" identified by the following enum variants, though some pipelines
|
||||
/// may use multiple models or no model (and may report NULL).
|
||||
///
|
||||
/// These types are present in the HTTP API and database columns as serialized here.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
pub enum InferenceModelType {
|
||||
#[serde(rename = "so_vits_svc")]
|
||||
SoVitsSvc,
|
||||
|
||||
// TODO: Does this need to be "legacy_tacotron2" ?
|
||||
#[serde(rename = "tacotron2")]
|
||||
Tacotron2,
|
||||
|
||||
#[serde(rename = "vits")]
|
||||
Vits,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(InferenceModelType);
|
||||
impl_mysql_enum_coders!(InferenceModelType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl InferenceModelType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::SoVitsSvc => "so_vits_svc",
|
||||
Self::Tacotron2 => "tacotron2",
|
||||
Self::Vits => "vits",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"so_vits_svc" => Ok(Self::SoVitsSvc),
|
||||
"tacotron2" => Ok(Self::Tacotron2),
|
||||
"vits" => Ok(Self::Vits),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<InferenceModelType> {
|
||||
// NB: BTreeSet is sorted
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
InferenceModelType::SoVitsSvc,
|
||||
InferenceModelType::Tacotron2,
|
||||
InferenceModelType::Vits,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(InferenceModelType::SoVitsSvc, "so_vits_svc");
|
||||
assert_serialization(InferenceModelType::Tacotron2, "tacotron2");
|
||||
assert_serialization(InferenceModelType::Vits, "vits");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(InferenceModelType::SoVitsSvc.to_str(), "so_vits_svc");
|
||||
assert_eq!(InferenceModelType::Tacotron2.to_str(), "tacotron2");
|
||||
assert_eq!(InferenceModelType::Vits.to_str(), "vits");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(InferenceModelType::from_str("so_vits_svc").unwrap(), InferenceModelType::SoVitsSvc);
|
||||
assert_eq!(InferenceModelType::from_str("tacotron2").unwrap(), InferenceModelType::Tacotron2);
|
||||
assert_eq!(InferenceModelType::from_str("vits").unwrap(), InferenceModelType::Vits);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
let mut variants = InferenceModelType::all_variants();
|
||||
assert_eq!(variants.len(), 3);
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::SoVitsSvc));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::Tacotron2));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::Vits));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
|
||||
// Generated check
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(InferenceModelType::all_variants().len(), InferenceModelType::iter().len());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user