Compare commits

..
Author SHA1 Message Date
Michael Chung 0033af73ce Feedback addressed! 2023-12-05 20:26:07 -05:00
Michael Chung b5fcc3cdfa Added documentation about the documentation 2023-12-05 19:14:02 -05:00
Michael Chung e986a44e9d documentation system open api spec. 2023-12-05 19:00:44 -05:00
Brandon Thomas 28770ef736 fix query issue 2023-12-04 05:00:46 -05:00
Brandon Thomas 894084fba6 Merge pull request #181 from storytold/brandon-queue-controls
Kill inference jobs (mod endpoint)
2023-12-04 03:54:05 -05:00
Brandon Thomas 4bf1a25fbb Kill inference jobs (mod endpoint) 2023-12-04 03:46:29 -05:00
Brandon Thomas b0a9342194 updated queue stats 2023-12-01 07:09:23 -05:00
Brandon Thomas 3cc1ea6935 capture stderr for svc and rvc 2023-12-01 01:36:33 -05:00
Brandon Thomas b74cf7853d fix web break 2023-11-30 22:46:35 -05:00
Brandon Thomas 3cdce86162 warn on slow batch queries 2023-11-30 17:25:23 -05:00
Brandon Thomas b0a87e83a0 log batch index 2023-11-30 17:19:23 -05:00
Brandon Thomas 979c234ed2 cleanup logging 2023-11-30 16:27:25 -05:00
Brandon Thomas 4837106d37 distinguish logs 2023-11-30 16:10:01 -05:00
Brandon Thomas cfd92e814d Merge pull request #166 from storytold/dependabot/cargo/env_logger-0.10.1
Bump env_logger from 0.7.1 to 0.10.1
2023-11-30 16:02:23 -05:00
Brandon Thomas 6d27214a14 codegen 2023-11-30 15:50:05 -05:00
Brandon Thomas b628fb0a11 premium TTS duration 2023-11-30 15:21:07 -05:00
dependabot[bot] 456b9e1ce6 Bump env_logger from 0.7.1 to 0.10.1
Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.7.1 to 0.10.1.
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.7.1...v0.10.1)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 09:35:18 +00:00
Brandon Thomas 6f7b6da595 Merge pull request #167 from storytold/dependabot/cargo/rand-0.8.5
Bump rand from 0.7.3 to 0.8.5
2023-11-30 04:33:54 -05:00
Brandon Thomas 18ad28135f safe delete 2023-11-30 02:36:33 -05:00
Brandon Thomas ff4a3115d2 clear up more directories when file system is full 2023-11-30 02:34:33 -05:00
dependabot[bot] ccae943037 Bump rand from 0.7.3 to 0.8.5
Bumps [rand](https://github.com/rust-random/rand) from 0.7.3 to 0.8.5.
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.7.3...0.8.5)

---
updated-dependencies:
- dependency-name: rand
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 07:32:36 +00:00
Brandon Thomas 12ef105ced fix errors 2023-11-30 02:27:08 -05:00
Brandon Thomas b27070e23e get rid of more of container_common 2023-11-30 02:25:16 -05:00
Brandon Thomas 8e45a4ea45 delete mod 2023-11-30 02:05:15 -05:00
Brandon Thomas a669ac7f03 move remaining container_common::files -> filesys crate 2023-11-30 02:04:41 -05:00
Brandon Thomas b5ed9acdd4 move check_directory_exists to filesys crate 2023-11-30 01:56:55 -05:00
Brandon Thomas ff2aaa9f3d move check_file_exists to filesys crate 2023-11-30 01:53:42 -05:00
Brandon Thomas f93421eadc keep IoError around; better casting 2023-11-30 01:35:48 -05:00
Brandon Thomas b82ffcce86 much more StorageFull error ! 2023-11-30 01:26:03 -05:00
Brandon Thomas e2c5839d01 surface storage full errors 2023-11-30 01:05:26 -05:00
Brandon Thomas 896e8591ba cleanup 2023-11-29 23:10:15 -05:00
Brandon Thomas 19dcfdc629 cleanup 2023-11-29 22:51:12 -05:00
Brandon Thomas cec7bce450 try copy instead 2023-11-29 22:49:00 -05:00
Brandon Thomas 6cc3062da8 don't fail if file is gone (not sure why this happens) 2023-11-29 22:01:53 -05:00
Brandon Thomas efdd03bbbd logging 2023-11-29 21:50:30 -05:00
Brandon Thomas c207356ac5 cleanup retry 2023-11-29 21:44:20 -05:00
Brandon Thomas 3243cc51b7 try to delete and re-copy 2023-11-29 21:36:47 -05:00
Brandon Thomas ee4af2976f flag to permit cold filesystem cache 2023-11-29 21:26:03 -05:00
Brandon Thomas 4fb2a38c68 report temp file size 2023-11-29 21:10:01 -05:00
Brandon Thomas a549ceb609 check vocoder and synthesizer sizes 2023-11-29 20:53:00 -05:00
Brandon Thomas 003f0cdeea struct args for downloader (safer) 2023-11-29 20:46:33 -05:00
Brandon Thomas 9e0772141a download file size check and logging 2023-11-29 20:25:37 -05:00
Brandon Thomas 542b79dd90 log http errors 2023-11-29 19:49:52 -05:00
Brandon Thomas 363f8cbc96 debug log statements, FileCacheDir (not yet used) 2023-11-29 19:28:32 -05:00
Brandon Thomas f2e75f8637 rename files across fs devices 2023-11-29 18:46:00 -05:00
Brandon Thomas f48cbb7978 fix 2023-11-29 18:16:45 -05:00
Brandon Thomas edd5cd6156 Merge pull request #179 from storytold/brandon-fix-job-pathing
Brandon fix job pathing
2023-11-29 17:49:39 -05:00
Brandon Thomas 37c016cecb "semi persistent dir" needs cleanup, this is confusing 2023-11-29 17:48:29 -05:00
Brandon Thomas 1a3e111dd6 Fix job pathing for outage and to make easier to manage 2023-11-29 17:30:03 -05:00
Brandon Thomas 0c456d957c fix build errors 2023-11-29 15:46:43 -05:00
Brandon Thomas 85ecce7b38 comments 2023-11-29 03:07:07 -05:00
Brandon Thomas 2f1d682438 Merge pull request #176 from storytold/nov-29-mithoo
fail model deleted inference jobs
2023-11-29 02:44:38 -05:00
Brandon Thomas c6fbfaa6ba fix test failures and nits 2023-11-29 02:43:31 -05:00
Brandon Thomas 038401bff4 Merge pull request #177 from storytold/brandon-revert-sha2-bump
Revert "Bump sha2 from 0.9.9 to 0.10.8"
2023-11-29 02:29:16 -05:00
Brandon Thomas e1c7231d96 Revert "Bump sha2 from 0.9.9 to 0.10.8"
This reverts commit 951afc2e5d.
2023-11-29 02:28:51 -05:00
kasisnu 1e11fdb35d fail model deleted inference jobs 2023-11-29 12:43:49 +05:30
Brandon Thomas 74c477b045 Merge pull request #169 from storytold/dependabot/cargo/sha2-0.10.8
Bump sha2 from 0.9.9 to 0.10.8
2023-11-28 21:37:50 -05:00
Brandon Thomas 042fa1574d Merge pull request #168 from storytold/dependabot/cargo/time-0.3.30
Bump time from 0.2.27 to 0.3.30
2023-11-28 21:37:26 -05:00
Brandon Thomas 4387e6326f LFU cache in TT2 inference-job 2023-11-28 17:47:46 -05:00
Brandon Thomas 3ad2b744b7 test comment out Dockerfile /etc/ssl copy 2023-11-28 15:42:24 -05:00
Brandon Thomas 8bf85b637b notes on dependencies 2023-11-28 15:40:26 -05:00
Brandon Thomas 50c3b5ed65 codegen db 2023-11-28 15:23:43 -05:00
Brandon Thomas df15395bf7 fix build error 2023-11-28 15:08:39 -05:00
Brandon Thomas 5666d58da0 fix SSL problem? 2023-11-28 14:54:53 -05:00
dependabot[bot] 0a85e9c581 Bump time from 0.2.27 to 0.3.30
Bumps [time](https://github.com/time-rs/time) from 0.2.27 to 0.3.30.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.2.27...v0.3.30)

---
updated-dependencies:
- dependency-name: time
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-28 16:45:21 +00:00
ArEnSc bd0ce25d94 Merge pull request #151 from storytold/feature/weights_queries
Feature/weights queries
2023-11-28 11:43:00 -05:00
ArEnSc 9f2335bfba Merge branch 'master' into feature/weights_queries 2023-11-28 11:30:22 -05:00
Brandon Thomas 63eca62f1d ssl to GCS broken in production, maybe this fixes? 2023-11-28 11:01:36 -05:00
Brandon Thomas 2808d20a35 fix wrong cleanup 2023-11-28 08:43:00 -05:00
Brandon Thomas 2d67947479 comment 2023-11-28 08:39:54 -05:00
Brandon Thomas 9722a34c8b extra care to delete temp directories 2023-11-28 08:37:08 -05:00
Brandon Thomas 643dffc08c scoped TempDir 2023-11-28 08:23:43 -05:00
Brandon Thomas 1433eca29a queue stats for inference-job's tacotron2 2023-11-28 07:27:26 -05:00
Brandon Thomas 8176f0d6bd fix lints 2023-11-28 06:26:17 -05:00
Brandon Thomas 2cfcbf8a75 db codegen + fix build errors 2023-11-28 06:19:37 -05:00
Brandon Thomas fb9a9b75bf Merge pull request #171 from storytold/brandon-tts-on-inference-job
tts-inference-job --> inference-job
2023-11-28 05:51:58 -05:00
Brandon Thomas 2a1675d865 formatting 2023-11-28 05:42:50 -05:00
Brandon Thomas f672df7386 add TT2 HTTP sidecar health checking (hacky) 2023-11-28 05:11:43 -05:00
Brandon Thomas 59fc891ce4 filter out certain model types (so we don't leak to competitors) 2023-11-28 02:59:01 -05:00
Brandon Thomas 739f234ac3 emulate TTS Results in media file pages 2023-11-28 02:42:55 -05:00
Michael Chung 8303066c38 Added serial test to run the database tests in serial, prevent failing when running the suite. 2023-11-28 00:16:44 -05:00
Michael Chung 5feb500b5e unit test for paging 2023-11-27 23:16:43 -05:00
Brandon Thomas 626157b615 emulate TTS inference job status checking for generic jobs 2023-11-27 22:19:27 -05:00
Brandon Thomas 7f3ccdc53d cleanup dependency checking 2023-11-27 21:22:27 -05:00
Brandon Thomas cc1d7f6de1 theoretically TTS HTTP works with inference-job 2023-11-27 20:55:13 -05:00
Brandon Thomas 3d4a870190 streamline inference-job tt2 2023-11-27 20:55:13 -05:00
Brandon Thomas 824d113dfc port some dependencies of tts-inference-job to inference-job 2023-11-27 20:55:13 -05:00
Brandon Thomas eaadc8242d remove (unused) tts-inference-job shell out code 2023-11-27 20:55:13 -05:00
Brandon Thomas bf5dddf6a9 Merge pull request #170 from storytold/brandon-seed-tt2-models
seed tool: TT2 models (with idempotency + early exit)
2023-11-27 20:50:31 -05:00
dependabot[bot] 951afc2e5d Bump sha2 from 0.9.9 to 0.10.8
Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.9.9 to 0.10.8.
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.9.9...sha2-v0.10.8)

---
updated-dependencies:
- dependency-name: sha2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 22:32:08 +00:00
Michael Chung d990fd4bfa Merge branch 'feature/weights_queries' of https://github.com/storytold/storyteller-rust into feature/weights_queries 2023-11-27 12:12:02 -05:00
Michael Chung 6f5edf0c96 fixed issues with weights queries and the tests, tests slightly flaky need to have it delete the rows, and ensure it doesn't run in prod. 2023-11-27 12:09:34 -05:00
ArEnSc b99756a7d1 Merge pull request #165 from storytold/nov-27-mithoo
query builder quickfix
2023-11-27 11:23:13 -05:00
kasisnu dcbdaf9cd6 query builder quickfix 2023-11-27 17:47:55 +05:30
Michael Chung 8e4f419091 QiueryBuilder tests needed 2023-11-27 00:46:46 -05:00
Michael Chung b779946fe7 Queries pass need just some mock data to test it in the test.rs 2023-11-26 15:29:57 -05:00
Michael Chung a244e614cf need to run tests on the query builder then can work on the rest of the code 2023-11-26 14:22:42 -05:00
Michael Chung 2e6708168b building wip ... then test then endpoints probably need seed data for this that is a bit diverse. 2023-11-25 03:53:19 -05:00
Michael Chung 8c46f47352 queries building is wip. 2023-11-25 03:28:34 -05:00
Michael Chung fdbf028743 test works query builder now. 2023-11-25 02:40:46 -05:00
Michael Chung becf58a357 Time to test. 2023-11-25 01:51:02 -05:00
Michael Chung a4c227a4ca Fixes to the weights now need filter 2023-11-25 01:40:54 -05:00
Michael Chung 0e1e8a87f1 Mapping list_weights_by_user.rs done need filter and then test 2023-11-25 00:17:58 -05:00
Michael Chung c9df278d40 weights_queries list weights by user more testing and implementation needed 2023-11-24 23:50:50 -05:00
Michael Chung ddb35c5133 Added more data for seeding
Added to test lists need to get list_weights_by_user tested
2023-11-24 22:24:34 -05:00
Michael Chung df3fc1bf51 more tests undelete and delete. 2023-11-24 00:35:43 -05:00
Michael Chung 21f2c3ac78 fixed weights queries get_weight hardcode transform 2023-11-24 00:19:21 -05:00
Michael Chung be429017eb Deleting weights from the database works for user 2023-11-23 23:34:14 -05:00
Michael Chung 2a623bd8eb Ok just mapped this by hand, super dissapointed that I can't use the the proper way to do it for some unknown reason. 2023-11-23 22:46:28 -05:00
Michael Chung 8b2765ba65 Weight types is failing to serialize :S 2023-11-23 21:39:42 -05:00
Michael Chung ccf1adae61 Add a test mod 2023-11-23 21:22:23 -05:00
Michael Chung 1a144ac8cf Writing unit tests for the queries 2023-11-23 19:41:33 -05:00
Michael Chung ce3aa6be74 model_weights delete need tests 2023-11-23 01:09:17 -05:00
Michael Chung f63eb94ed7 update_weight needs testing 2023-11-23 00:46:11 -05:00
Michael Chung 2e4e109065 Notes 2023-11-22 23:41:16 -05:00
Michael Chung 8481d37167 Fixed compile errors. 2023-11-22 23:25:19 -05:00
Michael Chung 5ed397af4e WIP get and update gotta write unit tests, WIP do not review. 2023-11-22 23:05:25 -05:00
Michael Chung ccbc89fd3e Fix function name issues 2023-11-22 13:21:52 -05:00
Michael Chung 5893753e35 Weights operations 2023-11-21 19:34:26 -05:00
Michael Chung 6026748563 Seeding Weights probably actually need real weights 2023-11-19 23:36:59 -05:00
Michael Chung bffe8d39ae model_weights/create_weight.rs being worked on 2023-11-18 00:44:41 -05:00
Michael Chung c36ca5e73c create model_weights 2023-11-17 23:59:53 -05:00
Michael Chung 55344fc6dd Model Weight Queries has to be worked on categories and types tests written. 2023-11-17 23:39:55 -05:00
177 changed files with 6812 additions and 1101 deletions
+1
View File
@@ -75,3 +75,4 @@ TTS_HIFIGAN_SUPERRES_VOCODER_MODEL_FILENAME=hifigan_superres_twilight_33000.pt
# Development key. Permissible to check in.
NEWRELIC_API_KEY=c402be1c4c4216ec83d0cfc0851520cfFFFFNRAL
STORYTELLER_ROOT="/home/tensor/code/storyteller/"
+1
View File
@@ -47,6 +47,7 @@
<w>vocoder</w>
<w>vocoders</w>
<w>vocodes</w>
<w>waveglow</w>
</words>
</dictionary>
</component>
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT *\nFROM tts_model_upload_jobs\nWHERE\n (\n status IN (\"pending\", \"attempt_failed\")\n )\n AND\n (\n retry_at IS NULL\n OR\n retry_at < CURRENT_TIMESTAMP\n )\n LIMIT ?\n ",
"query": "\nSELECT\n id,\n token,\n uuid_idempotency_token,\n on_success_result_token,\n creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,\n creator_ip_address,\n creator_set_visibility,\n title,\n tts_model_type,\n download_url,\n status,\n attempt_count,\n failure_reason,\n created_at,\n updated_at,\n retry_at\nFROM tts_model_upload_jobs\nWHERE\n (\n status IN (\"pending\", \"attempt_failed\")\n )\n AND\n (\n retry_at IS NULL\n OR\n retry_at < CURRENT_TIMESTAMP\n )\n LIMIT ?\n ",
"describe": {
"columns": [
{
@@ -45,37 +45,7 @@
},
{
"ordinal": 4,
"name": "title",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 5,
"name": "tts_model_type",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 60
}
},
{
"ordinal": 6,
"name": "download_url",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 2048
}
},
{
"ordinal": 7,
"name": "creator_user_token",
"name": "creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
@@ -84,7 +54,7 @@
}
},
{
"ordinal": 8,
"ordinal": 5,
"name": "creator_ip_address",
"type_info": {
"type": "VarString",
@@ -94,7 +64,7 @@
}
},
{
"ordinal": 9,
"ordinal": 6,
"name": "creator_set_visibility",
"type_info": {
"type": "String",
@@ -103,6 +73,36 @@
"max_size": 28
}
},
{
"ordinal": 7,
"name": "title",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 8,
"name": "tts_model_type",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 60
}
},
{
"ordinal": 9,
"name": "download_url",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 2048
}
},
{
"ordinal": 10,
"name": "status",
@@ -174,17 +174,17 @@
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
true,
false,
false,
true
]
},
"hash": "7ab54466ca3021d90e0feb234acba56bf53d415dde69bc1c35120ed0c8dd1858"
"hash": "066c16a04112b0ee83a54e29d5f96125f7c90db89ec9bd16275172d14722a381"
}
@@ -1,12 +1,12 @@
{
"db_name": "MySQL",
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n inference_category = ?,\n maybe_model_type = ?,\n maybe_model_token = ?,\n\n maybe_input_source_token = ?,\n maybe_input_source_token_type = ?,\n\n maybe_raw_inference_text = ?,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?,\n\n priority_level = ?,\n is_keepalive_required = ?,\n\n is_debug_request = ?,\n maybe_routing_tag = ?,\n\n status = \"pending\"\n ",
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n inference_category = ?,\n maybe_model_type = ?,\n maybe_model_token = ?,\n\n maybe_input_source_token = ?,\n maybe_input_source_token_type = ?,\n\n maybe_raw_inference_text = ?,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?,\n\n priority_level = ?,\n is_keepalive_required = ?,\n max_duration_seconds = ?,\n\n is_debug_request = ?,\n maybe_routing_tag = ?,\n\n status = \"pending\"\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 17
"Right": 18
},
"nullable": []
},
"hash": "b1750559783bcd55b2ae139372a4782ae363787a840a32f5c17c8408dbf15bc7"
"hash": "0d780caac7560f84efb50bd2ed876cbdd728b32e26b73dfbb3009ada12985405"
}
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n tts_results.token as tts_result_token,\n\n tts_results.raw_inference_text,\n\n tts_results.model_token as tts_model_token,\n tts_models.title as tts_model_title,\n\n tts_results.maybe_pretrained_vocoder_used,\n\n users.token as maybe_creator_user_token,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n users.is_banned as maybe_creator_is_banned,\n\n model_users.token as maybe_model_creator_user_token,\n model_users.username as maybe_model_creator_username,\n model_users.display_name as maybe_model_creator_display_name,\n model_users.email_gravatar_hash as maybe_model_creator_gravatar_hash,\n model_users.is_banned as maybe_model_creator_is_banned,\n\n tts_results.public_bucket_wav_audio_path,\n tts_results.public_bucket_spectrogram_path,\n\n tts_results.creator_set_visibility,\n\n tts_results.generated_by_worker,\n tts_results.is_debug_request,\n\n tts_results.file_size_bytes,\n tts_results.duration_millis,\n tts_results.created_at,\n tts_results.updated_at,\n\n tts_results.creator_ip_address,\n tts_results.user_deleted_at,\n tts_results.mod_deleted_at\n\nFROM tts_results\nLEFT OUTER JOIN tts_models\n ON tts_results.model_token = tts_models.token\nLEFT OUTER JOIN users\n ON tts_results.maybe_creator_user_token = users.token\nLEFT OUTER JOIN users as model_users\n ON tts_models.creator_user_token = model_users.token\nWHERE\n tts_results.token = ?\n ",
"query": "\nSELECT\n tts_results.token as tts_result_token,\n\n tts_results.raw_inference_text,\n\n tts_results.model_token as tts_model_token,\n tts_models.title as tts_model_title,\n\n tts_results.maybe_pretrained_vocoder_used,\n\n users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n users.is_banned as maybe_creator_is_banned,\n\n model_users.token as maybe_model_creator_user_token,\n model_users.username as maybe_model_creator_username,\n model_users.display_name as maybe_model_creator_display_name,\n model_users.email_gravatar_hash as maybe_model_creator_gravatar_hash,\n model_users.is_banned as maybe_model_creator_is_banned,\n\n tts_results.public_bucket_wav_audio_path,\n tts_results.public_bucket_spectrogram_path,\n\n tts_results.creator_set_visibility,\n\n tts_results.generated_by_worker,\n tts_results.is_debug_request,\n\n tts_results.file_size_bytes,\n tts_results.duration_millis,\n tts_results.created_at,\n tts_results.updated_at,\n\n tts_results.creator_ip_address,\n tts_results.user_deleted_at,\n tts_results.mod_deleted_at\n\nFROM tts_results\nLEFT OUTER JOIN tts_models\n ON tts_results.model_token = tts_models.token\nLEFT OUTER JOIN users\n ON tts_results.maybe_creator_user_token = users.token\nLEFT OUTER JOIN users as model_users\n ON tts_models.creator_user_token = model_users.token\nWHERE\n tts_results.token = ?\n ",
"describe": {
"columns": [
{
@@ -55,7 +55,7 @@
},
{
"ordinal": 5,
"name": "maybe_creator_user_token",
"name": "maybe_creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
@@ -307,5 +307,5 @@
true
]
},
"hash": "c7b4fecd829bddaeff77a6ce2240e2b939c5faac4a94da56aefd2a27eb9ed64a"
"hash": "1246d346e63efa99516ab4efa2aec90e37322184237d94782f77cf7a7a14d53f"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\n INSERT INTO model_weights\n SET\n token = ?,\n weights_type = ?,\n weights_category = ?,\n title = ?,\n maybe_thumbnail_token = ?,\n description_markdown = ?,\n description_rendered_html = ?,\n creator_user_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n maybe_last_update_user_token = ?,\n original_download_url = ?,\n original_filename = ?,\n file_size_bytes = ?,\n file_checksum_sha2 = ?,\n private_bucket_hash = ?,\n maybe_private_bucket_prefix = ?,\n maybe_private_bucket_extension = ?,\n cached_user_ratings_total_count = ?,\n cached_user_ratings_positive_count = ?,\n cached_user_ratings_negative_count = ?,\n maybe_cached_user_ratings_ratio = ?,\n version = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 23
},
"nullable": []
},
"hash": "274cfb1e3caca706e3dbc3d95064e0f4b354c936f8de948070854920f265cc41"
}
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n tts_results.token as tts_result_token,\n\n tts_results.raw_inference_text,\n\n tts_results.model_token as tts_model_token,\n tts_models.title as tts_model_title,\n\n tts_results.maybe_pretrained_vocoder_used,\n\n users.token as maybe_creator_user_token,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n users.is_banned as maybe_creator_is_banned,\n\n model_users.token as maybe_model_creator_user_token,\n model_users.username as maybe_model_creator_username,\n model_users.display_name as maybe_model_creator_display_name,\n model_users.email_gravatar_hash as maybe_model_creator_gravatar_hash,\n model_users.is_banned as maybe_model_creator_is_banned,\n\n tts_results.public_bucket_wav_audio_path,\n tts_results.public_bucket_spectrogram_path,\n\n tts_results.creator_set_visibility,\n\n tts_results.generated_by_worker,\n tts_results.is_debug_request,\n\n tts_results.file_size_bytes,\n tts_results.duration_millis,\n tts_results.created_at,\n tts_results.updated_at,\n\n tts_results.creator_ip_address,\n tts_results.user_deleted_at,\n tts_results.mod_deleted_at\n\nFROM tts_results\nLEFT OUTER JOIN tts_models\n ON tts_results.model_token = tts_models.token\nLEFT OUTER JOIN users\n ON tts_results.maybe_creator_user_token = users.token\nLEFT OUTER JOIN users as model_users\n ON tts_models.creator_user_token = model_users.token\nWHERE\n tts_results.token = ?\n AND tts_results.user_deleted_at IS NULL\n AND tts_results.mod_deleted_at IS NULL\n ",
"query": "\nSELECT\n tts_results.token as tts_result_token,\n\n tts_results.raw_inference_text,\n\n tts_results.model_token as tts_model_token,\n tts_models.title as tts_model_title,\n\n tts_results.maybe_pretrained_vocoder_used,\n\n users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n users.is_banned as maybe_creator_is_banned,\n\n model_users.token as maybe_model_creator_user_token,\n model_users.username as maybe_model_creator_username,\n model_users.display_name as maybe_model_creator_display_name,\n model_users.email_gravatar_hash as maybe_model_creator_gravatar_hash,\n model_users.is_banned as maybe_model_creator_is_banned,\n\n tts_results.public_bucket_wav_audio_path,\n tts_results.public_bucket_spectrogram_path,\n\n tts_results.creator_set_visibility,\n\n tts_results.generated_by_worker,\n tts_results.is_debug_request,\n\n tts_results.file_size_bytes,\n tts_results.duration_millis,\n tts_results.created_at,\n tts_results.updated_at,\n\n tts_results.creator_ip_address,\n tts_results.user_deleted_at,\n tts_results.mod_deleted_at\n\nFROM tts_results\nLEFT OUTER JOIN tts_models\n ON tts_results.model_token = tts_models.token\nLEFT OUTER JOIN users\n ON tts_results.maybe_creator_user_token = users.token\nLEFT OUTER JOIN users as model_users\n ON tts_models.creator_user_token = model_users.token\nWHERE\n tts_results.token = ?\n AND tts_results.user_deleted_at IS NULL\n AND tts_results.mod_deleted_at IS NULL\n ",
"describe": {
"columns": [
{
@@ -55,7 +55,7 @@
},
{
"ordinal": 5,
"name": "maybe_creator_user_token",
"name": "maybe_creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
@@ -307,5 +307,5 @@
true
]
},
"hash": "a3818a8688e1adab95f9f1263fbbd7effd5b77348b4e19cdba02672602b91d98"
"hash": "386edf6842d78c963b0ab35a25b8d00f65abb529e2a5e4c206895ac9a807085a"
}
@@ -0,0 +1,355 @@
{
"db_name": "MySQL",
"query": "\n SELECT \n mw.token as `token: tokens::tokens::model_weights::ModelWeightToken`,\n mw.title,\n mw.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n mw.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n mw.maybe_thumbnail_token,\n mw.description_markdown,\n mw.description_rendered_html,\n users.token as `creator_user_token: tokens::tokens::users::UserToken`,\n users.username as creator_username,\n users.display_name as creator_display_name,\n users.email_gravatar_hash as creator_email_gravatar_hash,\n mw.creator_ip_address,\n mw.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n mw.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,\n mw.original_download_url,\n mw.original_filename,\n mw.file_size_bytes,\n mw.file_checksum_sha2,\n mw.private_bucket_hash,\n mw.maybe_private_bucket_prefix,\n mw.maybe_private_bucket_extension,\n mw.cached_user_ratings_negative_count,\n mw.cached_user_ratings_positive_count,\n mw.cached_user_ratings_total_count,\n mw.maybe_cached_user_ratings_ratio,\n mw.cached_user_ratings_last_updated_at,\n mw.version,\n mw.created_at,\n mw.updated_at,\n mw.user_deleted_at,\n mw.mod_deleted_at\n FROM model_weights as mw\n JOIN users\n ON users.token = mw.creator_user_token\n WHERE\n users.username = ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token: tokens::tokens::model_weights::ModelWeightToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "title",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 2,
"name": "weights_type: enums::by_table::model_weights::weights_types::WeightsType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "weights_category: enums::by_table::model_weights::weights_category::WeightsCategory",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_thumbnail_token",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "description_markdown",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 6,
"name": "description_rendered_html",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 7,
"name": "creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "creator_username",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 9,
"name": "creator_display_name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 10,
"name": "creator_email_gravatar_hash",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 11,
"name": "creator_ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 12,
"name": "creator_set_visibility: enums::common::visibility::Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 13,
"name": "maybe_last_update_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 14,
"name": "original_download_url",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 2048
}
},
{
"ordinal": 15,
"name": "original_filename",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 16,
"name": "file_size_bytes",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 17,
"name": "file_checksum_sha2",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 256
}
},
{
"ordinal": 18,
"name": "private_bucket_hash",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 19,
"name": "maybe_private_bucket_prefix",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 20,
"name": "maybe_private_bucket_extension",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 21,
"name": "cached_user_ratings_negative_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 22,
"name": "cached_user_ratings_positive_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 23,
"name": "cached_user_ratings_total_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 24,
"name": "maybe_cached_user_ratings_ratio",
"type_info": {
"type": "Float",
"flags": "",
"char_set": 63,
"max_size": 12
}
},
{
"ordinal": 25,
"name": "cached_user_ratings_last_updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 26,
"name": "version",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 27,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 28,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 29,
"name": "user_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 30,
"name": "mod_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true
]
},
"hash": "3d586592422727dcc928574966bdf5081ac69fdbb856fffcbd68187fd99c4642"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE model_weights\nSET\n mod_deleted_at = NULL\nWHERE\n token = ?\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "3dfc7f22c16543116c4ca17f5bee0336f5cfa1522681ba1bb6b1874cd8f13297"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\n UPDATE model_weights\n SET\n title = ?,\n description_markdown = ?,\n maybe_thumbnail_token = ?,\n description_rendered_html = ?,\n creator_set_visibility = ?,\n version = version + 1\n WHERE token = ?\n LIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 6
},
"nullable": []
},
"hash": "4ed42766cc0ca2234b7bc1837d645d05198d483564b39a2a8b8034df25e287a4"
}
@@ -0,0 +1,322 @@
{
"db_name": "MySQL",
"query": "\n SELECT\n wt.token as `token: tokens::tokens::model_weights::ModelWeightToken`,\n wt.title,\n wt.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n wt.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n wt.maybe_thumbnail_token,\n wt.description_markdown,\n wt.description_rendered_html,\n wt.creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,\n wt.creator_ip_address,\n wt.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n wt.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,\n wt.original_download_url,\n wt.original_filename,\n wt.file_size_bytes,\n wt.file_checksum_sha2,\n wt.private_bucket_hash,\n wt.maybe_private_bucket_prefix,\n wt.maybe_private_bucket_extension,\n wt.cached_user_ratings_negative_count,\n wt.cached_user_ratings_positive_count,\n wt.cached_user_ratings_total_count,\n wt.maybe_cached_user_ratings_ratio,\n wt.cached_user_ratings_last_updated_at,\n wt.version,\n wt.created_at,\n wt.updated_at,\n wt.user_deleted_at,\n wt.mod_deleted_at\n FROM model_weights as wt\n WHERE\n wt.token = ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token: tokens::tokens::model_weights::ModelWeightToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "title",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 2,
"name": "weights_type: enums::by_table::model_weights::weights_types::WeightsType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "weights_category: enums::by_table::model_weights::weights_category::WeightsCategory",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_thumbnail_token",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "description_markdown",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 6,
"name": "description_rendered_html",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 7,
"name": "creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "creator_ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 9,
"name": "creator_set_visibility: enums::common::visibility::Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 10,
"name": "maybe_last_update_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 11,
"name": "original_download_url",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 2048
}
},
{
"ordinal": 12,
"name": "original_filename",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 13,
"name": "file_size_bytes",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 14,
"name": "file_checksum_sha2",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 256
}
},
{
"ordinal": 15,
"name": "private_bucket_hash",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 16,
"name": "maybe_private_bucket_prefix",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 17,
"name": "maybe_private_bucket_extension",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 18,
"name": "cached_user_ratings_negative_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 19,
"name": "cached_user_ratings_positive_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 20,
"name": "cached_user_ratings_total_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 21,
"name": "maybe_cached_user_ratings_ratio",
"type_info": {
"type": "Float",
"flags": "",
"char_set": 63,
"max_size": 12
}
},
{
"ordinal": 22,
"name": "cached_user_ratings_last_updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 23,
"name": "version",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 24,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 25,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 26,
"name": "user_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 27,
"name": "mod_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true
]
},
"hash": "6a94791c8a8f66ee54bb367a4e8c71106bbcbbb205f54c14e3657279e83dabb6"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE model_weights\nSET\n user_deleted_at = CURRENT_TIMESTAMP\nWHERE\n token = ?\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "7487c997706788c670a76da81ce90532b9748c8afcc707436d1f04ed976ce30e"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE model_weights\nSET\n user_deleted_at = NULL\nWHERE\n token = ?\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "7dbfbb21d502aad7859016fd287c57010296011928cf21b036a8dc57f1ef619d"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE model_weights\nSET\n mod_deleted_at = CURRENT_TIMESTAMP\nWHERE\n token = ?\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "9d2c8d49cf9840a547230e5c6febc041f39cd069bcb7a4a94ffb4f1cb3be6d7c"
}
@@ -0,0 +1,355 @@
{
"db_name": "MySQL",
"query": "\n SELECT\n mw.token as `token: tokens::tokens::model_weights::ModelWeightToken`,\n mw.title,\n mw.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n mw.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n mw.maybe_thumbnail_token,\n mw.description_markdown,\n mw.description_rendered_html,\n users.token as `creator_user_token: tokens::tokens::users::UserToken`,\n users.username as creator_username,\n users.display_name as creator_display_name,\n users.email_gravatar_hash as creator_email_gravatar_hash,\n mw.creator_ip_address,\n mw.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n mw.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,\n mw.original_download_url,\n mw.original_filename,\n mw.file_size_bytes,\n mw.file_checksum_sha2,\n mw.private_bucket_hash,\n mw.maybe_private_bucket_prefix,\n mw.maybe_private_bucket_extension,\n mw.cached_user_ratings_negative_count,\n mw.cached_user_ratings_positive_count,\n mw.cached_user_ratings_total_count,\n mw.maybe_cached_user_ratings_ratio,\n mw.cached_user_ratings_last_updated_at,\n mw.version,\n mw.created_at,\n mw.updated_at,\n mw.user_deleted_at,\n mw.mod_deleted_at\n FROM model_weights as mw\n JOIN users\n ON users.token = mw.creator_user_token\n WHERE\n users.username = ?\n AND mw.user_deleted_at IS NULL\n AND mw.mod_deleted_at IS NULL\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token: tokens::tokens::model_weights::ModelWeightToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "title",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 2,
"name": "weights_type: enums::by_table::model_weights::weights_types::WeightsType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "weights_category: enums::by_table::model_weights::weights_category::WeightsCategory",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_thumbnail_token",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "description_markdown",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 6,
"name": "description_rendered_html",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 7,
"name": "creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "creator_username",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 9,
"name": "creator_display_name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 10,
"name": "creator_email_gravatar_hash",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 11,
"name": "creator_ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 12,
"name": "creator_set_visibility: enums::common::visibility::Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 13,
"name": "maybe_last_update_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 14,
"name": "original_download_url",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 2048
}
},
{
"ordinal": 15,
"name": "original_filename",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 16,
"name": "file_size_bytes",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 17,
"name": "file_checksum_sha2",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 256
}
},
{
"ordinal": 18,
"name": "private_bucket_hash",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 19,
"name": "maybe_private_bucket_prefix",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 20,
"name": "maybe_private_bucket_extension",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 21,
"name": "cached_user_ratings_negative_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 22,
"name": "cached_user_ratings_positive_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 23,
"name": "cached_user_ratings_total_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 24,
"name": "maybe_cached_user_ratings_ratio",
"type_info": {
"type": "Float",
"flags": "",
"char_set": 63,
"max_size": 12
}
},
{
"ordinal": 25,
"name": "cached_user_ratings_last_updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 26,
"name": "version",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 27,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 28,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 29,
"name": "user_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 30,
"name": "mod_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true
]
},
"hash": "a6ed8524fb5339fed17bec6611f8f56b6bdee35bac63c9eacbe21eb032a6a831"
}
@@ -0,0 +1,322 @@
{
"db_name": "MySQL",
"query": "\n SELECT\n wt.token as `token: tokens::tokens::model_weights::ModelWeightToken`,\n wt.title,\n wt.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n wt.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n wt.maybe_thumbnail_token,\n wt.description_markdown,\n wt.description_rendered_html,\n wt.creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,\n wt.creator_ip_address,\n wt.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n wt.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,\n wt.original_download_url,\n wt.original_filename,\n wt.file_size_bytes,\n wt.file_checksum_sha2,\n wt.private_bucket_hash,\n wt.maybe_private_bucket_prefix,\n wt.maybe_private_bucket_extension,\n wt.cached_user_ratings_negative_count,\n wt.cached_user_ratings_positive_count,\n wt.cached_user_ratings_total_count,\n wt.maybe_cached_user_ratings_ratio,\n wt.cached_user_ratings_last_updated_at,\n wt.version,\n wt.created_at,\n wt.updated_at,\n wt.user_deleted_at,\n wt.mod_deleted_at\n FROM model_weights as wt\n WHERE\n wt.token = ?\n AND wt.user_deleted_at IS NULL\n AND wt.mod_deleted_at IS NULL\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token: tokens::tokens::model_weights::ModelWeightToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "title",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 2,
"name": "weights_type: enums::by_table::model_weights::weights_types::WeightsType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "weights_category: enums::by_table::model_weights::weights_category::WeightsCategory",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_thumbnail_token",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "description_markdown",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 6,
"name": "description_rendered_html",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
},
{
"ordinal": 7,
"name": "creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "creator_ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 9,
"name": "creator_set_visibility: enums::common::visibility::Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 10,
"name": "maybe_last_update_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 11,
"name": "original_download_url",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 2048
}
},
{
"ordinal": 12,
"name": "original_filename",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 13,
"name": "file_size_bytes",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 14,
"name": "file_checksum_sha2",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 256
}
},
{
"ordinal": 15,
"name": "private_bucket_hash",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 16,
"name": "maybe_private_bucket_prefix",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 17,
"name": "maybe_private_bucket_extension",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 18,
"name": "cached_user_ratings_negative_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 19,
"name": "cached_user_ratings_positive_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 20,
"name": "cached_user_ratings_total_count",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | UNSIGNED",
"char_set": 63,
"max_size": 10
}
},
{
"ordinal": 21,
"name": "maybe_cached_user_ratings_ratio",
"type_info": {
"type": "Float",
"flags": "",
"char_set": 63,
"max_size": 12
}
},
{
"ordinal": 22,
"name": "cached_user_ratings_last_updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 23,
"name": "version",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 24,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 25,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 26,
"name": "user_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 27,
"name": "mod_deleted_at",
"type_info": {
"type": "Timestamp",
"flags": "BINARY",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
false,
true,
true,
false,
false,
false,
true,
false,
false,
false,
false,
true,
true
]
},
"hash": "f0b5767d52c389660d1859e628c746f6f33a9e1c25f21f66aeeb0784df768c8e"
}
Generated
+143 -158
View File
@@ -736,12 +736,6 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "base-x"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
[[package]]
name = "base64"
version = "0.11.0"
@@ -1175,6 +1169,15 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "collections"
version = "0.0.1"
dependencies = [
"errors",
"my-workspace-hack",
"rand 0.8.5",
]
[[package]]
name = "color_quant"
version = "1.1.0"
@@ -1253,12 +1256,6 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
[[package]]
name = "const_fn"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
[[package]]
name = "constant_time_eq"
version = "0.1.5"
@@ -1867,12 +1864,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "discard"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "displaydoc"
version = "0.2.4"
@@ -2003,7 +1994,7 @@ name = "easyenv"
version = "0.1.0"
dependencies = [
"dotenv",
"env_logger 0.10.1",
"env_logger",
"log",
"my-workspace-hack",
"storyteller_root",
@@ -2184,26 +2175,13 @@ dependencies = [
"toml",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime 1.3.0",
"log",
"regex",
"termcolor",
]
[[package]]
name = "env_logger"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
dependencies = [
"humantime 2.1.0",
"humantime",
"is-terminal",
"log",
"regex",
@@ -2296,6 +2274,7 @@ name = "filesys"
version = "0.0.1"
dependencies = [
"errors",
"log",
"my-workspace-hack",
]
@@ -2848,15 +2827,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "humantime"
version = "2.1.0"
@@ -2994,6 +2964,7 @@ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown 0.14.2",
"serde",
]
[[package]]
@@ -3032,9 +3003,9 @@ dependencies = [
"buckets",
"chrono",
"cloud_storage",
"collections",
"concurrency",
"config",
"container_common",
"dotenv",
"easyenv",
"enums",
@@ -3045,6 +3016,7 @@ dependencies = [
"hyper",
"images",
"jobs_common",
"lfu",
"log",
"media",
"memory_caching",
@@ -3399,7 +3371,7 @@ name = "logging"
version = "0.0.1"
dependencies = [
"dotenv",
"env_logger 0.10.1",
"env_logger",
"log",
"my-workspace-hack",
]
@@ -3755,7 +3727,7 @@ dependencies = [
"syn 1.0.109",
"syn 2.0.39",
"time 0.3.30",
"time-macros 0.2.15",
"time-macros",
"tokio",
"tokio-stream",
"tracing",
@@ -3783,13 +3755,16 @@ dependencies = [
"log",
"my-workspace-hack",
"once_cell",
"rand 0.8.5",
"regex",
"reusable_types",
"serde",
"serde_derive",
"serde_json",
"serial_test",
"sqlx",
"tokens",
"tokio",
"toml",
]
@@ -3849,14 +3824,14 @@ name = "newrelic-telemetry"
version = "0.1.0"
dependencies = [
"anyhow",
"env_logger 0.7.1",
"env_logger",
"flate2",
"futures 0.3.29",
"hyper",
"hyper-tls",
"log",
"my-workspace-hack",
"rand 0.7.3",
"rand 0.8.5",
"serde",
"serde_json",
"tokio",
@@ -4420,10 +4395,28 @@ dependencies = [
]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
@@ -4464,12 +4457,6 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quick-xml"
version = "0.26.0"
@@ -4733,7 +4720,7 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"time 0.2.27",
"time 0.3.30",
]
[[package]]
@@ -4914,6 +4901,41 @@ dependencies = [
"quick-xml 0.30.0",
]
[[package]]
name = "rust-embed"
version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"shellexpand",
"syn 2.0.39",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada"
dependencies = [
"sha2 0.10.8",
"walkdir",
]
[[package]]
name = "rust-ini"
version = "0.18.0"
@@ -5449,6 +5471,15 @@ dependencies = [
"digest 0.10.7",
]
[[package]]
name = "shellexpand"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
dependencies = [
"dirs",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
@@ -5833,70 +5864,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "standback"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
dependencies = [
"version_check",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stdweb"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
dependencies = [
"discard",
"rustc_version 0.2.3",
"stdweb-derive",
"stdweb-internal-macros",
"stdweb-internal-runtime",
"wasm-bindgen",
]
[[package]]
name = "stdweb-derive"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn 1.0.109",
]
[[package]]
name = "stdweb-internal-macros"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
dependencies = [
"base-x",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"serde_json",
"sha1 0.6.1",
"syn 1.0.109",
]
[[package]]
name = "stdweb-internal-runtime"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]]
name = "storyteller-web"
version = "0.0.1"
@@ -5980,7 +5953,7 @@ dependencies = [
"speculoos",
"sqlx",
"symphonia",
"time 0.2.27",
"time 0.3.30",
"tokens",
"tokio",
"toml",
@@ -5990,6 +5963,8 @@ dependencies = [
"url_config",
"user_input_common",
"users_component",
"utoipa",
"utoipa-swagger-ui",
"uuid 0.8.2",
]
@@ -6426,21 +6401,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "time"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
dependencies = [
"const_fn",
"libc",
"standback",
"stdweb",
"time-macros 0.1.1",
"version_check",
"winapi 0.3.9",
]
[[package]]
name = "time"
version = "0.3.30"
@@ -6452,7 +6412,7 @@ dependencies = [
"powerfmt",
"serde",
"time-core",
"time-macros 0.2.15",
"time-macros",
]
[[package]]
@@ -6461,16 +6421,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
dependencies = [
"proc-macro-hack",
"time-macros-impl",
]
[[package]]
name = "time-macros"
version = "0.2.15"
@@ -6480,19 +6430,6 @@ dependencies = [
"time-core",
]
[[package]]
name = "time-macros-impl"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"standback",
"syn 1.0.109",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
@@ -6521,6 +6458,7 @@ dependencies = [
"sqlx-core",
"strum",
"toml",
"utoipa",
]
[[package]]
@@ -6774,6 +6712,7 @@ dependencies = [
"dotenv",
"easyenv",
"enums",
"filesys",
"google_drive_common",
"hashing",
"hostname",
@@ -6800,10 +6739,12 @@ dependencies = [
"chrono",
"clap 2.34.0",
"cloud_storage",
"collections",
"config",
"container_common",
"dotenv",
"easyenv",
"filesys",
"hashing",
"hostname",
"hyper",
@@ -6871,6 +6812,7 @@ dependencies = [
"anyhow",
"base64 0.21.5",
"chrono",
"collections",
"config",
"container_common",
"diesel",
@@ -6899,7 +6841,7 @@ dependencies = [
"serde_json",
"sha2 0.9.9",
"sqlx",
"time 0.2.27",
"time 0.3.30",
"tokens",
"tokio",
"tokio-tungstenite",
@@ -7137,7 +7079,7 @@ dependencies = [
"sha2 0.9.9",
"sqlx",
"strum_macros",
"time 0.2.27",
"time 0.3.30",
"tokens",
"toml",
"user_input_common",
@@ -7155,6 +7097,47 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "utoipa"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ff05e3bac2c9428f57ade702667753ca3f5cf085e2011fe697de5bfd49aa72d"
dependencies = [
"indexmap",
"serde",
"serde_json",
"utoipa-gen",
]
[[package]]
name = "utoipa-gen"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0b6f4667edd64be0e820d6631a60433a269710b6ee89ac39525b872b76d61d"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"regex",
"syn 2.0.39",
]
[[package]]
name = "utoipa-swagger-ui"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f839caa8e09dddc3ff1c3112a91ef7da0601075ba5025d9f33ae99c4cb9b6e51"
dependencies = [
"actix-web",
"mime_guess",
"regex",
"rust-embed",
"serde",
"serde_json",
"utoipa",
"zip",
]
[[package]]
name = "uuid"
version = "0.8.2"
@@ -7206,6 +7189,7 @@ dependencies = [
"container_common",
"dotenv",
"easyenv",
"filesys",
"google_drive_common",
"hashing",
"hostname",
@@ -7235,6 +7219,7 @@ dependencies = [
"container_common",
"dotenv",
"easyenv",
"filesys",
"google_drive_common",
"hostname",
"hyper",
@@ -7477,7 +7462,7 @@ dependencies = [
"serde_json",
"sha2 0.9.9",
"sqlx",
"time 0.2.27",
"time 0.3.30",
"tokio",
"toml",
"twitch_api2",
+1
View File
@@ -27,6 +27,7 @@ members = [
"crates/lib/bootstrap",
"crates/lib/caching/memory_caching",
"crates/lib/caching/redis_caching",
"crates/lib/collections",
"crates/lib/concurrency",
"crates/lib/cookies",
"crates/lib/crockford",
+3 -1
View File
@@ -29,7 +29,9 @@ Web API Overview
* `tts-inference-job` - (*deprecated*) Async TTS inference of Tacotron2 models only
* `w2l-download-job` - (*deprecated*) Async download of videos and images
* `w2l-inference-job` - (*deprecated*) Async W2L inference
* Documentation Server:
* `docs` - this will run a local swagger server with the endpoints that you have access to, http://127.0.0.1:8989/api-docs/openapi.json use this to port everything over to the post man.
### PowerStream
* [PowerStream](https://power.stream) (deprecated) is powered by the following applications:
@@ -380,3 +380,16 @@ of this error message. You can essentially ignore it.
### [Fix] Can't connect to local MySQL after install on Ubuntu
- If MySql in local dev can't be connected to, [reset the accounts](https://linuxconfig.org/how-to-reset-root-mysql-mariadb-password-on-ubuntu-20-04-focal-fossa-linux).
### API Server
```
cargo run --bin docs
```
This setups an api server with swagger docs to show you responses and requests with each associated endpoint
It is run at http://127.0.0.1:8989/
To obtain the json for the postman collection go to this url http://127.0.0.1:8989/api-docs/openapi.json
We use this: `https://github.com/juhaku/utoipa`
The documentation example is in:
`crates/service/web/storyteller_web/src/http_server/endpoints/voice_designer/inference/enqueue_tts_request.rs`
Write into the api doc to:
`crates/service/web/storyteller_web/src/api_doc.rs`
+14
View File
@@ -8,11 +8,25 @@ update generic_inference_jobs set status = 'dead' where maybe_routing_tag IS NOT
-- Get pending jobs
select count(*) from generic_inference_jobs where status = 'pending';
-- Kill outstanding jobs
update generic_inference_jobs
set status = 'dead'
where status IN ('pending', 'started', 'attempt_failed');
-- Kill outstanding jobs of type
update generic_inference_jobs
set status = 'dead'
where status IN ('pending', 'started', 'attempt_failed')
and maybe_model_type IN ('sad_talker', 'so_vits_svc');
-- Tacotron 2 TTS
update generic_inference_jobs
set status = 'dead'
where status IN ('pending', 'started', 'attempt_failed')
and maybe_model_type IN ('tacotron2');
-- Sad Talker Face Animation
update generic_inference_jobs
set status = 'dead'
where status IN ('pending', 'started', 'attempt_failed')
and maybe_model_type IN ('sad_talker');
Binary file not shown.
+1 -1
View File
@@ -7,7 +7,7 @@ set -euxo pipefail
# NB: Database used by desktop app for AiChatBot sidecar.
# Make sure it has been migrated (use aichatbot-sidecar app directory as root).
SQLITE_DATABASE_PATH=./runtime_data/database.db
# SQLITE_DATABASE_PATH=./runtime_data/database.db
# NB: OpenSSL is broken on Ubuntu 22.04 (this is documented elsewhere)
# See https://askubuntu.com/a/1403961
@@ -37,6 +37,9 @@ pub enum IdCategory {
/// Zs voice which lives in the zs_voices table
#[serde(rename = "zs_voice")]
ZeroShotVoiceEmbedding,
#[serde(rename = "model_weights")]
ModelWeights,
}
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
@@ -53,6 +56,7 @@ impl IdCategory {
Self::ZeroShotVoiceDataset => "zs_dataset",
Self::ZeroShotVoiceEmbedding => "zs_voice",
Self::ZeroShotTtsResult => "zs_tts_result",
Self::ModelWeights => "model_weights",
}
}
@@ -64,6 +68,7 @@ impl IdCategory {
"zs_dataset" => Ok(Self::ZeroShotVoiceDataset),
"zs_voice" => Ok(Self::ZeroShotVoiceEmbedding),
"zs_tts_result" => Ok(Self::ZeroShotTtsResult),
"model_weights" => Ok(Self::ModelWeights),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -78,6 +83,7 @@ impl IdCategory {
Self::ZeroShotTtsResult,
Self::ZeroShotVoiceDataset,
Self::ZeroShotVoiceEmbedding,
Self::ModelWeights,
])
}
}
@@ -98,6 +104,7 @@ mod tests {
assert_serialization(IdCategory::ZeroShotVoiceDataset, "zs_dataset");
assert_serialization(IdCategory::ZeroShotVoiceEmbedding, "zs_voice");
assert_serialization(IdCategory::ZeroShotTtsResult, "zs_tts_result");
assert_serialization(IdCategory::ModelWeights, "model_weights")
}
#[test]
@@ -108,6 +115,7 @@ mod tests {
assert_eq!(IdCategory::ZeroShotVoiceDataset.to_str(), "zs_dataset");
assert_eq!(IdCategory::ZeroShotVoiceEmbedding.to_str(), "zs_voice");
assert_eq!(IdCategory::ZeroShotTtsResult.to_str(), "zs_tts_result");
assert_eq!(IdCategory::ModelWeights.to_str(), "model_weights");
}
#[test]
@@ -118,19 +126,21 @@ mod tests {
assert_eq!(IdCategory::from_str("zs_dataset").unwrap(), IdCategory::ZeroShotVoiceDataset);
assert_eq!(IdCategory::from_str("zs_voice").unwrap(), IdCategory::ZeroShotVoiceEmbedding);
assert_eq!(IdCategory::from_str("zs_tts_result").unwrap(), IdCategory::ZeroShotTtsResult);
assert_eq!(IdCategory::from_str("model_weights").unwrap(), IdCategory::ModelWeights);
}
#[test]
fn all_variants() {
// Static check
let mut variants = IdCategory::all_variants();
assert_eq!(variants.len(), 6);
assert_eq!(variants.len(), 7);
assert_eq!(variants.pop_first(), Some(IdCategory::MediaFile));
assert_eq!(variants.pop_first(), Some(IdCategory::LipsyncAnimationResult));
assert_eq!(variants.pop_first(), Some(IdCategory::VoiceConversionResult));
assert_eq!(variants.pop_first(), Some(IdCategory::ZeroShotTtsResult));
assert_eq!(variants.pop_first(), Some(IdCategory::ZeroShotVoiceDataset));
assert_eq!(variants.pop_first(), Some(IdCategory::ZeroShotVoiceEmbedding));
assert_eq!(variants.pop_first(), Some(IdCategory::ModelWeights));
assert_eq!(variants.pop_first(), None);
// Generated check
+1 -1
View File
@@ -14,7 +14,7 @@ pub mod user_ratings;
pub mod voice_conversion_models;
pub mod voice_conversion_results;
pub mod zs_voices;
pub mod model_weights;
// ===== Sqlite =====
pub mod tts_render_tasks;
pub mod web_rendition_targets;
@@ -0,0 +1,2 @@
pub mod weights_types;
pub mod weights_category;
@@ -0,0 +1,84 @@
use std::collections::BTreeSet;
#[cfg(test)]
use strum::EnumCount;
#[cfg(test)]
use strum::EnumIter;
#[cfg_attr(test, derive(EnumIter, EnumCount))]
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
pub enum WeightsCategory {
#[serde(rename = "image_generation")]
ImageGeneration,
#[serde(rename = "text_to_speech")]
TextToSpeech,
#[serde(rename = "vocoder")]
Vocoder,
#[serde(rename = "voice_conversion")]
VoiceConversion,
}
impl WeightsCategory {
pub fn to_str(&self) -> &'static str {
match self {
Self::ImageGeneration => "image_generation",
Self::TextToSpeech => "text_to_speech",
Self::Vocoder => "vocoder",
Self::VoiceConversion => "voice_conversion",
}
}
pub fn from_str(value: &str) -> Result<Self, String> {
match value {
"image_generation" => Ok(Self::ImageGeneration),
"text_to_speech" => Ok(Self::TextToSpeech),
"vocoder" => Ok(Self::Vocoder),
"voice_conversion" => Ok(Self::VoiceConversion),
_ => Err(format!("invalid value: {:?}", value)),
}
}
pub fn all_variants() -> BTreeSet<Self> {
BTreeSet::from([
Self::ImageGeneration,
Self::TextToSpeech,
Self::Vocoder,
Self::VoiceConversion,
])
}
}
impl_enum_display_and_debug_using_to_str!(WeightsCategory);
impl_mysql_enum_coders!(WeightsCategory);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_str() {
assert_eq!(WeightsCategory::ImageGeneration.to_str(), "image_generation");
assert_eq!(WeightsCategory::TextToSpeech.to_str(), "text_to_speech");
assert_eq!(WeightsCategory::Vocoder.to_str(), "vocoder");
assert_eq!(WeightsCategory::VoiceConversion.to_str(), "voice_conversion");
}
#[test]
fn test_from_str() {
assert_eq!(WeightsCategory::from_str("image_generation").unwrap(), WeightsCategory::ImageGeneration);
assert_eq!(WeightsCategory::from_str("text_to_speech").unwrap(), WeightsCategory::TextToSpeech);
assert_eq!(WeightsCategory::from_str("vocoder").unwrap(), WeightsCategory::Vocoder);
assert_eq!(WeightsCategory::from_str("voice_conversion").unwrap(), WeightsCategory::VoiceConversion);
assert!(WeightsCategory::from_str("invalid").is_err());
}
#[test]
fn test_all_variants() {
let variants = WeightsCategory::all_variants();
assert_eq!(variants.len(), 4);
assert!(variants.contains(&WeightsCategory::ImageGeneration));
assert!(variants.contains(&WeightsCategory::TextToSpeech));
assert!(variants.contains(&WeightsCategory::Vocoder));
assert!(variants.contains(&WeightsCategory::VoiceConversion));
}
}
@@ -0,0 +1,111 @@
use std::collections::BTreeSet;
#[cfg(test)]
use strum::EnumCount;
#[cfg(test)]
use strum::EnumIter;
#[cfg_attr(test, derive(EnumIter, EnumCount))]
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
pub enum WeightsType {
#[serde(rename = "hifigan_tt2")]
HifiganTacotron2,
#[serde(rename = "rvc_v2")]
RvcV2,
#[serde(rename = "sd_1.5")]
StableDiffusion15,
#[serde(rename = "sdxl")]
StableDiffusionXL,
#[serde(rename = "so_vits_svc")]
SoVitsSvc,
#[serde(rename = "tt2")]
Tacotron2,
#[serde(rename = "loRA")]
LoRA,
}
impl WeightsType {
pub fn to_str(&self) -> &'static str {
match self {
Self::HifiganTacotron2 => "hifigan_tt2",
Self::RvcV2 => "rvc_v2",
Self::StableDiffusion15 => "sd_1.5",
Self::StableDiffusionXL => "sdxl",
Self::SoVitsSvc => "so_vits_svc",
Self::Tacotron2 => "tt2",
Self::LoRA => "loRA",
}
}
pub fn from_str(value: &str) -> Result<Self, String> {
match value {
"hifigan_tt2" => Ok(Self::HifiganTacotron2),
"rvc_v2" => Ok(Self::RvcV2),
"sd_1.5" => Ok(Self::StableDiffusion15),
"sdxl" => Ok(Self::StableDiffusionXL),
"so_vits_svc" => Ok(Self::SoVitsSvc),
"tt2" => Ok(Self::Tacotron2),
"loRA" => Ok(Self::LoRA),
_ => Err(format!("invalid value: {:?}", value)),
}
}
pub fn all_variants() -> BTreeSet<Self> {
BTreeSet::from([
Self::HifiganTacotron2,
Self::RvcV2,
Self::StableDiffusion15,
Self::StableDiffusionXL,
Self::SoVitsSvc,
Self::Tacotron2,
Self::LoRA,
])
}
}
impl_enum_display_and_debug_using_to_str!(WeightsType);
impl_mysql_enum_coders!(WeightsType);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_str() {
assert_eq!(WeightsType::HifiganTacotron2.to_str(), "hifigan_tt2");
assert_eq!(WeightsType::RvcV2.to_str(), "rvc_v2");
assert_eq!(WeightsType::StableDiffusion15.to_str(), "sd_1.5");
assert_eq!(WeightsType::StableDiffusionXL.to_str(), "sdxl");
assert_eq!(WeightsType::SoVitsSvc.to_str(), "so_vits_svc");
assert_eq!(WeightsType::Tacotron2.to_str(), "tt2");
assert_eq!(WeightsType::LoRA.to_str(), "loRA");
}
#[test]
fn test_from_str() {
assert_eq!(WeightsType::from_str("hifigan_tt2").unwrap(), WeightsType::HifiganTacotron2);
assert_eq!(WeightsType::from_str("rvc_v2").unwrap(), WeightsType::RvcV2);
assert_eq!(WeightsType::from_str("sd_1.5").unwrap(), WeightsType::StableDiffusion15);
assert_eq!(WeightsType::from_str("sdxl").unwrap(), WeightsType::StableDiffusionXL);
assert_eq!(WeightsType::from_str("so_vits_svc").unwrap(), WeightsType::SoVitsSvc);
assert_eq!(WeightsType::from_str("tt2").unwrap(), WeightsType::Tacotron2);
assert_eq!(WeightsType::from_str("loRA").unwrap(), WeightsType::LoRA);
assert!(WeightsType::from_str("invalid").is_err());
}
#[test]
fn test_all_variants() {
let variants = WeightsType::all_variants();
assert_eq!(variants.len(), 7);
assert!(variants.contains(&WeightsType::HifiganTacotron2));
assert!(variants.contains(&WeightsType::RvcV2));
assert!(variants.contains(&WeightsType::StableDiffusion15));
assert!(variants.contains(&WeightsType::StableDiffusionXL));
assert!(variants.contains(&WeightsType::SoVitsSvc));
assert!(variants.contains(&WeightsType::Tacotron2));
assert!(variants.contains(&WeightsType::LoRA));
}
}
+3 -1
View File
@@ -18,7 +18,7 @@ serde = "1.0.125"
serde_derive = "1.0.125"
# Random
rand = "0.8.3"
rand = "0.8.5"
# MySql Database
# "offline" supports typesafe builds without a live database
@@ -28,6 +28,8 @@ sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls",
sqlx-core = { version = "0.7.2" }
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
utoipa = { version = "4", features = ["actix_extras"] }
[dev-dependencies]
# Enum utilities
@@ -4,9 +4,10 @@ use serde::Deserialize;
use serde::Serialize;
use crate::prefixes::TokenPrefix;
use utoipa::ToSchema;
/// The primary key for "generic" inference jobs.
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize)]
#[derive(Clone, PartialEq, Eq, sqlx::Type, Debug, Serialize, Deserialize,ToSchema)]
#[sqlx(transparent)]
pub struct InferenceJobToken(String);
+6
View File
@@ -7,12 +7,14 @@ use errors::AnyhowResult;
use crate::bucket_clients::get_bucket_clients;
use crate::cli_args::parse_cli_args;
use crate::seeding::model_weights::seed_weights;
use crate::seeding::tts_tacotron2::seed_tts_tacotron2;
use crate::seeding::users::seed_user_accounts;
use crate::seeding::voice_conversion::seed_voice_conversion;
use crate::seeding::zero_shot_tts::seed_zero_shot_tts;
pub mod bucket_clients;
pub mod cli_args;
pub mod seeding;
@@ -52,6 +54,10 @@ pub async fn main() -> AnyhowResult<()> {
seed_user_accounts(&pool).await?;
seed_zero_shot_tts(&pool, maybe_bucket_clients.as_ref()).await?;
seed_voice_conversion(&pool).await?;
seed_weights(&pool).await?;
seed_tts_tacotron2(&pool, maybe_bucket_clients.as_ref()).await?;
info!("Done!");
@@ -1,4 +1,5 @@
pub mod tts_tacotron2;
pub mod users;
pub mod voice_conversion;
pub mod zero_shot_tts;
pub mod zero_shot_tts;
pub mod model_weights;
@@ -0,0 +1,335 @@
use log::info;
use tokens::tokens::users::UserToken;
use sqlx::{ MySql, Pool };
use enums::by_table::model_weights::{
weights_types::WeightsType,
weights_category::WeightsCategory,
};
use errors::{ anyhow, AnyhowResult };
use crate::seeding::users::HANASHI_USERNAME;
use mysql_queries::queries::model_weights::create_weight::{ create_weight, CreateModelWeightsArgs };
use tokens::tokens::model_weights::ModelWeightToken;
use enums::common::visibility::Visibility;
use mysql_queries::queries::users::user::get_user_token_by_username::get_user_token_by_username;
pub async fn seed_weights_for_user_token(
mysql_pool: &Pool<MySql>,
user_token: UserToken
) -> AnyhowResult<()> {
info!("Seeding weights...");
let model_weight_token1 = ModelWeightToken("11".to_string());
let model_weight_token2 = ModelWeightToken("22".to_string());
let model_weight_token3 = ModelWeightToken("33".to_string());
let model_weight_token4 = ModelWeightToken("44".to_string());
let model_weight_token5 = ModelWeightToken("55".to_string());
let model_weights_args = vec![
CreateModelWeightsArgs {
token: &model_weight_token1, // replace with actual ModelWeightToken
weights_type: WeightsType::RvcV2, // replace with actual WeightsType
weights_category: WeightsCategory::VoiceConversion, // replace with actual WeightsCategory
title: "Title 1".to_string(),
maybe_thumbnail_token: Some("Thumbnail 1".to_string()),
description_markdown: "Description 1".to_string(),
description_rendered_html: "<p>Description 1</p>".to_string(),
creator_user_token: Some(&user_token), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 1".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum1".to_string(),
private_bucket_hash: "bucket_hash1".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token2, // replace with actual ModelWeightToken
weights_type: WeightsType::HifiganTacotron2, // replace with actual WeightsType
weights_category: WeightsCategory::TextToSpeech, // replace with actual WeightsCategory
title: "Title 2".to_string(),
maybe_thumbnail_token: Some("Thumbnail 2".to_string()),
description_markdown: "Description 2".to_string(),
description_rendered_html: "<p>Description 2</p>".to_string(),
creator_user_token: Some(&user_token), // replace with actual UserToken
creator_ip_address: "292.268.2.2",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 2".to_string()),
original_download_url: Some("http://example.com/download2".to_string()),
original_filename: Some("filename2.txt".to_string()),
file_size_bytes: 2024,
file_checksum_sha2: "checksum2".to_string(),
private_bucket_hash: "bucket_hash2".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("tt2".to_string()),
cached_user_ratings_total_count: 20,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 2,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 2,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token3, // replace with actual ModelWeightToken
weights_type: WeightsType::StableDiffusion15, // replace with actual WeightsType
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
title: "Title 3".to_string(),
maybe_thumbnail_token: Some("Thumbnail 3".to_string()),
description_markdown: "Description 3".to_string(),
description_rendered_html: "<p>Description 3</p>".to_string(),
creator_user_token: Some(&user_token), // replace with actual UserToken
creator_ip_address: "392.368.3.3",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 3".to_string()),
original_download_url: Some("http://example.com/download3".to_string()),
original_filename: Some("filename3.txt".to_string()),
file_size_bytes: 3024,
file_checksum_sha2: "checksum3".to_string(),
private_bucket_hash: "bucket_hash3".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("safetensors".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token4, // replace with actual ModelWeightToken
weights_type: WeightsType::LoRA, // replace with actual WeightsType
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
title: "Title 4".to_string(),
maybe_thumbnail_token: Some("Thumbnail 4".to_string()),
description_markdown: "Description 4".to_string(),
description_rendered_html: "<p>Description 4</p>".to_string(),
creator_user_token: Some(&user_token), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 4".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum4".to_string(),
private_bucket_hash: "bucket_hash4".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("LoRA".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 2,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token5, // replace with actual ModelWeightToken
weights_type: WeightsType::LoRA, // replace with actual WeightsType
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
title: "Title 5".to_string(),
maybe_thumbnail_token: Some("Thumbnail 4".to_string()),
description_markdown: "Description 4".to_string(),
description_rendered_html: "<p>Description 4</p>".to_string(),
creator_user_token: Some(&user_token), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 4".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum4".to_string(),
private_bucket_hash: "bucket_hash4".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("LoRA".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 2,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
}
];
for model_weights_arg in model_weights_args {
create_weight(model_weights_arg).await?;
}
Ok(())
}
pub async fn seed_weights(mysql_pool: &Pool<MySql>) -> AnyhowResult<()> {
info!("Seeding weights...");
let user_token = match get_user_token_by_username(HANASHI_USERNAME, mysql_pool).await? {
None => {
return Err(anyhow!("could not find user hanashi"));
}
Some(token) => token,
};
let model_weight_token1 = ModelWeightToken("1".to_string());
let creator_token1 = UserToken("creatorToken1".to_string());
let model_weight_token2 = ModelWeightToken("2".to_string());
let creator_token2 = UserToken("creatorToken2".to_string());
let model_weight_token3 = ModelWeightToken("3".to_string());
let creator_token3 = UserToken("creatorToken3".to_string());
let model_weight_token4 = ModelWeightToken("4".to_string());
let creator_token4 = UserToken("creatorToken4".to_string());
let model_weight_token5 = ModelWeightToken("5".to_string());
let creator_token5 = UserToken("creatorToken5".to_string());
let model_weights_args = vec![
CreateModelWeightsArgs {
token: &model_weight_token1, // replace with actual ModelWeightToken
weights_type: WeightsType::RvcV2, // replace with actual WeightsType
weights_category: WeightsCategory::VoiceConversion, // replace with actual WeightsCategory
title: "Title 1".to_string(),
maybe_thumbnail_token: Some("Thumbnail 1".to_string()),
description_markdown: "Description 1".to_string(),
description_rendered_html: "<p>Description 1</p>".to_string(),
creator_user_token: Some(&creator_token1), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 1".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum1".to_string(),
private_bucket_hash: "bucket_hash1".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token2, // replace with actual ModelWeightToken
weights_type: WeightsType::HifiganTacotron2, // replace with actual WeightsType
weights_category: WeightsCategory::TextToSpeech, // replace with actual WeightsCategory
title: "Title 2".to_string(),
maybe_thumbnail_token: Some("Thumbnail 2".to_string()),
description_markdown: "Description 2".to_string(),
description_rendered_html: "<p>Description 2</p>".to_string(),
creator_user_token: Some(&creator_token2), // replace with actual UserToken
creator_ip_address: "292.268.2.2",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 2".to_string()),
original_download_url: Some("http://example.com/download2".to_string()),
original_filename: Some("filename2.txt".to_string()),
file_size_bytes: 2024,
file_checksum_sha2: "checksum2".to_string(),
private_bucket_hash: "bucket_hash2".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("tt2".to_string()),
cached_user_ratings_total_count: 20,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 2,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 2,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token3, // replace with actual ModelWeightToken
weights_type: WeightsType::StableDiffusion15, // replace with actual WeightsType
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
title: "Title 3".to_string(),
maybe_thumbnail_token: Some("Thumbnail 3".to_string()),
description_markdown: "Description 3".to_string(),
description_rendered_html: "<p>Description 3</p>".to_string(),
creator_user_token: Some(&creator_token3), // replace with actual UserToken
creator_ip_address: "392.368.3.3",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 3".to_string()),
original_download_url: Some("http://example.com/download3".to_string()),
original_filename: Some("filename3.txt".to_string()),
file_size_bytes: 3024,
file_checksum_sha2: "checksum3".to_string(),
private_bucket_hash: "bucket_hash3".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("safetensors".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token4, // replace with actual ModelWeightToken
weights_type: WeightsType::LoRA, // replace with actual WeightsType
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
title: "Title 4".to_string(),
maybe_thumbnail_token: Some("Thumbnail 4".to_string()),
description_markdown: "Description 4".to_string(),
description_rendered_html: "<p>Description 4</p>".to_string(),
creator_user_token: Some(&creator_token4), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 4".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum4".to_string(),
private_bucket_hash: "bucket_hash4".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("LoRA".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 2,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
},
CreateModelWeightsArgs {
token: &model_weight_token5, // replace with actual ModelWeightToken
weights_type: WeightsType::LoRA, // replace with actual WeightsType
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
title: "Title 5".to_string(),
maybe_thumbnail_token: Some("Thumbnail 5".to_string()),
description_markdown: "Description 5".to_string(),
description_rendered_html: "<p>Description 5</p>".to_string(),
creator_user_token: Some(&creator_token5), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 5".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1025,
file_checksum_sha2: "checksum5".to_string(),
private_bucket_hash: "bucket_hash5".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("LoRA".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 2,
mysql_pool: &mysql_pool, // replace with actual MySqlPool
}
];
for model_weights_arg in model_weights_args {
create_weight(model_weights_arg).await?;
}
// adds this to HANASHI
get_user_token_by_username(HANASHI_USERNAME, mysql_pool).await?;
seed_weights_for_user_token(mysql_pool, user_token).await?;
Ok(())
}
@@ -6,7 +6,7 @@ use sqlx::{MySql, Pool};
use cloud_storage::bucket_path_unifier::BucketPathUnifier;
use enums::by_table::tts_models::tts_model_type::TtsModelType;
use enums::common::visibility::Visibility;
use errors::{anyhow, AnyhowResult};
use errors::AnyhowResult;
use filesys::file_read_bytes::file_read_bytes;
use filesys::path_to_string::path_to_string;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
@@ -48,7 +48,7 @@ async fn create_rvc_model(
original_download_url: "https://example.com",
original_filename: "unknown.zip",
file_size_bytes: 1234,
creator_user_token: creator_user_token.as_str(),
creator_user_token,
creator_ip_address: "127.0.0.1",
creator_set_visibility: Default::default(),
has_index_file,
+1 -1
View File
@@ -21,7 +21,7 @@ errors = { path = "../../lib/errors" }
# External
log = "0.4.20"
once_cell = "1.18.0"
rand = "0.8.1"
rand = "0.8.5"
regex = "1.10.0"
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
+26
View File
@@ -0,0 +1,26 @@
[package]
name = "collections"
edition = "2018"
version = "0.0.1"
authors = [
"Brandon Thomas <bt@brand.io>",
"Brandon Thomas <echelon@gmail.com>",
]
publish = false
[lib]
# NB: Public "collections" crate is not yet taken (!!), so we're fine to use this internally for now.
name = "collections"
path = "src/lib.rs"
[dependencies]
# Internal
errors = { path = "../errors" }
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
# External
# KEEP THIS TO A MINIMUM OR NIL.
rand = "0.8.5"
[dev-dependencies]
# None yet
+22
View File
@@ -0,0 +1,22 @@
//! collections
//!
//! The purpose of this library is to provide "extra" data structures or utilities related to
//! data structures. There should be minimal dependency introduction here.
//!
// Never allow these
#![forbid(private_in_public)]
#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things
// Okay to toggle
#![forbid(unreachable_patterns)]
#![forbid(unused_imports)]
#![forbid(unused_mut)]
#![forbid(unused_variables)]
// Always allow
#![allow(dead_code)]
#![allow(non_snake_case)]
pub mod multiple_random_from_vec;
pub mod random_from_vec;
@@ -12,7 +12,7 @@ pub fn multiple_random_from_vec<T>(vec: &Vec<T>, amount: usize) -> Vec<&T> {
#[cfg(test)]
mod tests {
use crate::collections::multiple_random_from_vec::multiple_random_from_vec;
use crate::multiple_random_from_vec::multiple_random_from_vec;
#[test]
fn pulls_item_from_vec() {
@@ -7,7 +7,7 @@ pub fn random_from_vec<T>(vec: &Vec<T>) -> Option<&T> {
#[cfg(test)]
mod tests {
use crate::collections::random_from_vec::random_from_vec;
use crate::random_from_vec::random_from_vec;
#[test]
fn pulls_item_from_vec() {
+1 -1
View File
@@ -15,7 +15,7 @@ name = "crockford"
path = "src/lib.rs"
[dependencies]
rand = "0.8.3"
rand = "0.8.5"
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
[dev-dependencies]
@@ -17,7 +17,7 @@ path = "src/lib.rs"
# External
anyhow = "1.0.75"
once_cell = "1.18.0"
rand = "0.8.3"
rand = "0.8.5"
uuid = { version = "0.8.2", features = ["v4"] }
log = "0.4.14"
@@ -1,2 +0,0 @@
pub mod multiple_random_from_vec;
pub mod random_from_vec;
@@ -1,15 +0,0 @@
use std::path::PathBuf;
use anyhow::bail;
use crate::anyhow_result::AnyhowResult;
pub fn check_directory_exists(path: &PathBuf) -> AnyhowResult<()> {
if !path.exists() {
bail!("Path doesn't exist: {:?}", path);
}
if !path.is_dir() {
bail!("Path isn't a directory: {:?}", path);
}
Ok(())
}
@@ -1,5 +0,0 @@
pub mod check_directory_exists;
pub mod check_file_exists;
pub mod safe_delete_possible_temp_file;
pub mod safe_delete_temp_directory;
pub mod safe_delete_temp_file;
@@ -1,7 +1,5 @@
pub mod anyhow_result;
pub mod collections;
pub mod files;
pub mod filesystem;
pub mod i18n;
pub mod numerics;
pub mod thread;
@@ -1,3 +1,2 @@
pub mod random_crockford_token;
pub mod random_prefix_crockford_token;
pub mod random_uuid;
@@ -1,100 +0,0 @@
use anyhow::anyhow;
use rand::Rng;
use crate::anyhow_result::AnyhowResult;
// Crockford characters
const CROCKFORD_UPPERCASE_CHARSET: &[u8] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
const CROCKFORD_LOWERCASE_CHARSET: &[u8] = b"0123456789abcdefghjkmnpqrstvwxyz";
// Random part can't be any less than this.
const MIN_ENTROPY_LENGTH : usize = 8;
#[deprecated(note = "see internal 'crockford' and 'token' crates")]
pub fn random_prefix_crockford_token(prefix: &str, length: usize, uppercase: bool) -> AnyhowResult<String> {
let mut prefix = prefix.trim().to_string();
if prefix.is_empty() {
return Err(anyhow!("prefix not set; use other crockford functions"));
}
if !prefix.ends_with(":") {
prefix = format!("{}:", prefix);
}
let entropy_length : usize = length.saturating_sub(prefix.len());
if entropy_length < MIN_ENTROPY_LENGTH {
return Err(anyhow!("not enough entropy in token"));
}
let mut rng = rand::thread_rng();
let charset = if uppercase { CROCKFORD_UPPERCASE_CHARSET } else { CROCKFORD_LOWERCASE_CHARSET };
let entropy_part: String = (0..entropy_length)
.map(|_| {
let idx = rng.gen_range(0..charset.len());
charset[idx] as char
})
.collect();
let token = format!("{}{}", prefix, entropy_part);
Ok(token)
}
#[cfg(test)]
mod tests {
use crate::token::random_prefix_crockford_token::random_prefix_crockford_token;
#[test]
fn no_prefix_error() {
assert!(random_prefix_crockford_token("", 0, false).is_err());
assert!(random_prefix_crockford_token("", 10, false).is_err());
assert!(random_prefix_crockford_token("", 32, false).is_err());
assert!(random_prefix_crockford_token("", 0, true).is_err());
assert!(random_prefix_crockford_token("", 10, true).is_err());
assert!(random_prefix_crockford_token("", 32, true).is_err());
}
#[test]
fn not_enough_entropy_error() {
assert!(random_prefix_crockford_token("foo", 0, false).is_err());
assert!(random_prefix_crockford_token("foo", 5, false).is_err());
assert!(random_prefix_crockford_token("foo", 11, false).is_err());
assert!(random_prefix_crockford_token("foo:", 11, false).is_err());
assert!(random_prefix_crockford_token("foo", 0, true).is_err());
assert!(random_prefix_crockford_token("foo", 5, true).is_err());
assert!(random_prefix_crockford_token("foo", 11, true).is_err());
assert!(random_prefix_crockford_token("foo:", 11, true).is_err());
}
#[test]
fn starts_with() {
assert!(random_prefix_crockford_token("w", 10, false).unwrap().starts_with("w:"));
assert!(random_prefix_crockford_token("w", 10, false).unwrap().starts_with("w:"));
assert!(random_prefix_crockford_token("prefix", 16, false).unwrap().starts_with("prefix:"));
assert!(random_prefix_crockford_token("prefix:", 16, false).unwrap().starts_with("prefix:"));
assert!(random_prefix_crockford_token("w", 10, true).unwrap().starts_with("w:"));
assert!(random_prefix_crockford_token("w", 10, true).unwrap().starts_with("w:"));
assert!(random_prefix_crockford_token("prefix", 16, true).unwrap().starts_with("prefix:"));
assert!(random_prefix_crockford_token("prefix:", 16, true).unwrap().starts_with("prefix:"));
}
#[test]
fn length() {
assert_eq!(random_prefix_crockford_token("w", 10, false).unwrap().len(), 10);
assert_eq!(random_prefix_crockford_token("w:", 10, false).unwrap().len(), 10);
assert_eq!(random_prefix_crockford_token("prefix", 16, false).unwrap().len(), 16);
assert_eq!(random_prefix_crockford_token("prefix:", 16, false).unwrap().len(), 16);
assert_eq!(random_prefix_crockford_token("asdf:", 32, false).unwrap().len(), 32);
assert_eq!(random_prefix_crockford_token("asdf", 32, false).unwrap().len(), 32);
assert_eq!(random_prefix_crockford_token("w", 10, true).unwrap().len(), 10);
assert_eq!(random_prefix_crockford_token("w:", 10, true).unwrap().len(), 10);
assert_eq!(random_prefix_crockford_token("prefix", 16, true).unwrap().len(), 16);
assert_eq!(random_prefix_crockford_token("prefix:", 16, true).unwrap().len(), 16);
assert_eq!(random_prefix_crockford_token("asdf:", 32, true).unwrap().len(), 32);
assert_eq!(random_prefix_crockford_token("asdf", 32, true).unwrap().len(), 32);
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ storyteller_root = { path = "../storyteller_root" }
# External
dotenv = "0.15.0"
env_logger = "0.10.0"
env_logger = "0.10.1"
log = "0.4.14"
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
+1
View File
@@ -17,6 +17,7 @@ path = "src/lib.rs"
# Internal
errors = { path = "../../errors" }
my-workspace-hack = { version = "0.1", path = "../../../../my-workspace-hack" }
log = "0.4.20"
# External
# KEEP THIS TO A MINIMUM OR NIL.
@@ -0,0 +1,15 @@
use std::path::Path;
use errors::{AnyhowResult, bail};
pub fn check_directory_exists<P: AsRef<Path>>(path: P) -> AnyhowResult<()> {
let check_path = path.as_ref();
if !check_path.exists() {
bail!("Path doesn't exist: {:?}", check_path);
}
if !check_path.is_dir() {
bail!("Path isn't a directory: {:?}", check_path);
}
Ok(())
}
@@ -1,8 +1,7 @@
use std::path::PathBuf;
use anyhow::bail;
use crate::anyhow_result::AnyhowResult;
use errors::AnyhowResult;
use errors::bail;
pub fn check_file_exists(path: &PathBuf) -> AnyhowResult<()> {
if !path.exists() {
@@ -7,6 +7,7 @@ use errors::{anyhow, AnyhowResult};
pub fn file_size<P: AsRef<Path>>(filename: P) -> AnyhowResult<u64> {
let metadata = std::fs::metadata(filename.as_ref())?;
// TODO(bt,2023-11-29): Return io::Result and errors here.
if !metadata.is_file() {
Err(anyhow!("path {:?} is not a file", filename.as_ref()))
} else if metadata.is_symlink() {
@@ -0,0 +1,16 @@
// Nearly a third of `ErrorKind` is nightly rust, so we're going to have to match on
// unix error codes until the rest of the ErrorKind enum variants are stable.
// The error codes are maintained in sys/unix/mod.rs - decode_error_kind(i32)
const E_FILESYSTEM_QUOTA_EXCEEDED : i32 = 122; // pub const EDQUOT: ::c_int = 122;
const E_STORAGE_FULL : i32 = 28; // pub const ENOSPC: ::c_int = 28;
/// Reports if an io::Error was caused by the filesystem being full.
pub fn is_filesystem_full_error(err: &std::io::Error) -> bool {
match err.raw_os_error() {
Some(E_FILESYSTEM_QUOTA_EXCEEDED) => true,
Some(E_STORAGE_FULL) => true,
_ => false,
}
}
+6
View File
@@ -18,11 +18,17 @@
#![allow(dead_code)]
#![allow(non_snake_case)]
pub mod check_file_exists;
pub mod create_dir_all_if_missing;
pub mod directory_exists;
pub mod file_exists;
pub mod file_read_bytes;
pub mod file_size;
pub mod filename_concat;
pub mod is_filesystem_full_error;
pub mod path_to_string;
pub mod rename_across_devices;
pub mod check_directory_exists;
pub mod safe_delete_temp_file;
pub mod safe_delete_possible_temp_file;
pub mod safe_delete_temp_directory;
@@ -1,30 +1,80 @@
use std::error::Error;
use std::fmt;
use std::path::Path;
use log::error;
use crate::is_filesystem_full_error::is_filesystem_full_error;
#[derive(Debug)]
pub enum RenameError {
StorageFull,
IoError(std::io::Error),
}
impl Error for RenameError {}
impl fmt::Display for RenameError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RenameError::StorageFull => write!(f, "RenameError: storage is full"),
RenameError::IoError(err) => write!(f, "{:?}", err),
}
}
}
impl From<std::io::Error> for RenameError {
fn from(error: std::io::Error) -> Self {
RenameError::IoError(error)
}
}
/// Rename a file.
/// Ordinary rename will fail in Linux if it is across physical devices.
/// This function will perform a copy followed by delete in that case.
pub fn rename_across_devices<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> std::io::Result<()> {
/// In both cases, this function will overwrite the destination if it already exists.
pub fn rename_across_devices<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<(), RenameError> {
let result = std::fs::rename(&from, &to);
let err = match result.as_ref() {
let err = match result {
Ok(_) => return Ok(()), // Rename succeeded.
Err(err) => err,
};
// Nearly a third of `ErrorKind` is nightly rust, so we're going to have to match on
// unix error codes until the rest of the ErrorKind enum variants are stable.
// The error codes are maintained in sys/unix/mod.rs - decode_error_kind(i32)
const E_CROSSES_DEVICES : i32 = 18; // pub const EXDEV: ::c_int = 18;
if is_filesystem_full_error(&err) {
error!("Filesystem is full during rename.");
return Err(RenameError::StorageFull);
}
match err.raw_os_error() {
Some(18) => {
// NO-OP: pass-through
// NB: We can clean this up in the future when `err.kind() == ErrorKind::CrossDevices`
// stabilizes. For now we can assume code "18" means we're trying to rename across devices.
Some(E_CROSSES_DEVICES) => {
// NB: Fall through.
}
_ => {
// Something else happened. Return original error.
return result;
return Err(RenameError::IoError(err));
}
}
let _num_bytes = std::fs::copy(&from, &to)?;
// NB: In production we've seen std::fs::copy silently succeed, yet copy zero bytes. The reason
// is more than likely that the filesystem is full. We'll check the number of copied bytes to
// confirm. Moreover, the Rust docs say wrt std::fs::copy, "On success, the total number of bytes
// copied is returned and it is equal to the length of the to file as reported by metadata."
let original_file_size = std::fs::metadata(from.as_ref())?.len();
let num_bytes_copied = std::fs::copy(&from, &to)?;
if num_bytes_copied != original_file_size {
error!("Filesystem is full during copy. Not all bytes copied.");
return Err(RenameError::StorageFull);
}
// An emulated "rename" would delete the source file.
std::fs::remove_file(&from)?;
Ok(())
@@ -1,6 +1,6 @@
use std::path::Path;
use crate::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use crate::safe_delete_temp_file::safe_delete_temp_file;
pub fn safe_delete_possible_temp_file<P: AsRef<Path>>(maybe_file_path: Option<P>) {
if let Some(file_path) = maybe_file_path {
+1 -1
View File
@@ -15,7 +15,7 @@ path = "src/lib.rs"
[dependencies]
dotenv = "0.15.0"
env_logger = "0.10.0"
env_logger = "0.10.1"
log = "0.4.20"
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
+5 -1
View File
@@ -38,11 +38,15 @@ serde = "1.0.125"
serde_derive = "1.0.125"
serde_json = "1.0.108"
toml = "0.5.8"
serial_test = "2.0.0"
# MySql Database
# "offline" supports typesafe builds without a live database
# "rustls" doesn't appear to work with IP addresses, per:
# https://github.com/launchbadge/sqlx/issues/1095#issuecomment-798050828
tokio = { version = "1.6.0", features = ["full"] }
rand = "0.8"
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
@@ -85,7 +85,7 @@ impl BadgeGranter {
}
/// This needs to be called *after* successful upload.
pub async fn maybe_grant_voice_conversion_model_uploads_badge(&self, user_token: &str) -> AnyhowResult<()> {
pub async fn maybe_grant_voice_conversion_model_uploads_badge(&self, user_token: &UserToken) -> AnyhowResult<()> {
let count = self.count_voice_conversion_models_uploaded(user_token).await?;
let mut maybe_badge = None;
@@ -119,16 +119,16 @@ impl BadgeGranter {
None => return Ok(()),
};
if self.has_badge(user_token, badge).await? {
if self.has_badge(user_token.as_str(), badge).await? {
return Ok(())
}
let _record_id = self.insert(
badge,
user_token,
user_token.as_str(),
).await?;
self.firehose_publisher.publish_user_badge_granted(user_token, badge.to_db_value())
self.firehose_publisher.publish_user_badge_granted(user_token.as_str(), badge.to_db_value())
.await?;
Ok(())
@@ -184,8 +184,8 @@ impl BadgeGranter {
}
/// This needs to be called *after* successful upload.
pub async fn maybe_grant_vocoder_model_uploads_badge(&self, user_token: &str) -> AnyhowResult<()> {
let count = self.count_vocoder_models_uploaded(user_token).await?;
pub async fn maybe_grant_vocoder_model_uploads_badge(&self, user_token: &UserToken) -> AnyhowResult<()> {
let count = self.count_vocoder_models_uploaded(user_token.as_str()).await?;
let mut maybe_badge = None;
@@ -218,24 +218,24 @@ impl BadgeGranter {
None => return Ok(()),
};
if self.has_badge(user_token, badge).await? {
if self.has_badge(user_token.as_str(), badge).await? {
return Ok(())
}
let _record_id = self.insert(
badge,
user_token,
user_token.as_str(),
).await?;
self.firehose_publisher.publish_user_badge_granted(user_token, badge.to_db_value())
self.firehose_publisher.publish_user_badge_granted(user_token.as_str(), badge.to_db_value())
.await?;
Ok(())
}
/// This needs to be called *after* successful upload.
pub async fn maybe_grant_softvc_vocoder_model_uploads_badge(&self, user_token: &str) -> AnyhowResult<()> {
let count = self.count_softvc_vocoder_models_uploaded(user_token).await?;
pub async fn maybe_grant_softvc_vocoder_model_uploads_badge(&self, user_token: &UserToken) -> AnyhowResult<()> {
let count = self.count_softvc_vocoder_models_uploaded(user_token.as_str()).await?;
let mut maybe_badge = None;
@@ -268,16 +268,16 @@ impl BadgeGranter {
None => return Ok(()),
};
if self.has_badge(user_token, badge).await? {
if self.has_badge(user_token.as_str(), badge).await? {
return Ok(())
}
let _record_id = self.insert(
badge,
user_token,
user_token.as_str(),
).await?;
self.firehose_publisher.publish_user_badge_granted(user_token, badge.to_db_value())
self.firehose_publisher.publish_user_badge_granted(user_token.as_str(), badge.to_db_value())
.await?;
Ok(())
@@ -345,7 +345,7 @@ LIMIT 1
async fn count_voice_conversion_models_uploaded(
&self,
user_token: &str,
user_token: &UserToken,
) -> AnyhowResult<u64> {
// NB: This could get expensive!
let maybe_result = sqlx::query_as!(
@@ -125,10 +125,10 @@ impl FirehosePublisher {
Ok(())
}
pub async fn publish_tts_model_upload_finished(&self, user_token: &str, model_token: &str) -> AnyhowResult<()> {
pub async fn publish_tts_model_upload_finished(&self, user_token: &UserToken, model_token: &str) -> AnyhowResult<()> {
let _record_id = self.insert(
FirehoseEvent::TtsModelUploadCompleted,
Some(user_token),
Some(user_token.as_str()),
Some(model_token),
Some(model_token)
).await?;
@@ -258,10 +258,10 @@ impl FirehosePublisher {
}
// NB: Entity token is optional.
pub async fn publish_generic_download_finished(&self, user_token: &str, entity_token: Option<&str>) -> AnyhowResult<()> {
pub async fn publish_generic_download_finished(&self, user_token: &UserToken, entity_token: Option<&str>) -> AnyhowResult<()> {
let _record_id = self.insert(
FirehoseEvent::GenericDownloadCompleted,
Some(user_token),
Some(user_token.as_str()),
entity_token,
entity_token,
).await?;
@@ -1,13 +1,11 @@
use anyhow::anyhow;
use log::warn;
use sqlx::MySqlPool;
use enums::by_table::favorites::favorite_entity_type::FavoriteEntityType;
use errors::AnyhowResult;
use tokens::tokens::users::UserToken;
use crate::queries::favorites::favorite_entity_token::FavoriteEntityToken;
use crate::queries::favorites::list_user_favorites_result::{UserFavorite, RawUserFavoriteRecord};
use crate::queries::favorites::list_user_favorites_result::{RawUserFavoriteRecord, UserFavorite};
pub async fn list_user_favorites(
username: &str,
@@ -24,6 +24,8 @@ pub struct InsertGenericInferenceArgs<'a> {
pub maybe_raw_inference_text: Option<&'a str>,
pub maybe_max_duration_seconds: Option<i32>,
pub maybe_inference_args: Option<GenericInferenceArgs>,
pub maybe_creator_user_token: Option<&'a UserToken>,
@@ -54,6 +56,11 @@ pub async fn insert_generic_inference_job(args: InsertGenericInferenceArgs<'_>)
routing_tag
});
// This only applies to certain types of inference.
// "0" is the default value, typically 12 seconds for TTS.
// "-1" means "unlimited"
let max_duration_seconds = args.maybe_max_duration_seconds.unwrap_or(0);
let query = sqlx::query!(
r#"
INSERT INTO generic_inference_jobs
@@ -80,6 +87,7 @@ SET
priority_level = ?,
is_keepalive_required = ?,
max_duration_seconds = ?,
is_debug_request = ?,
maybe_routing_tag = ?,
@@ -109,6 +117,7 @@ SET
args.priority_level,
args.requires_keepalive,
max_duration_seconds,
args.is_debug_request,
maybe_routing_tag,
@@ -0,0 +1,157 @@
use std::collections::HashSet;
use anyhow::anyhow;
use sqlx::{MySql, MySqlPool, QueryBuilder};
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
use enums::common::job_status::JobStatus;
use errors::AnyhowResult;
/// Only certain job statuses should be modified.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum KillableStatus {
Failed,
Pending,
Started,
}
/// Target everything, by job category, or by model type.
#[derive(Clone)]
pub enum KillableTarget {
AllJobs,
Category(InferenceCategory),
ModelType(InferenceModelType),
}
pub struct KillGenericInferenceJobsArgs<'a> {
pub job_statuses: HashSet<KillableStatus>,
pub target: KillableTarget,
pub maybe_priority_or_lower: Option<u8>,
pub mysql_pool: &'a MySqlPool,
}
pub async fn kill_generic_inference_jobs(args: KillGenericInferenceJobsArgs<'_>) -> AnyhowResult<()> {
let mut query = query_builder(
args.job_statuses,
args.target,
args.maybe_priority_or_lower
);
let query = query.build();
let result = query.execute(args.mysql_pool).await;
match result {
Err(err) => {
Err(anyhow!("error with query: {:?}", err))
},
Ok(_r) => Ok(()),
}
}
fn query_builder(
job_statuses: HashSet<KillableStatus>,
target: KillableTarget,
maybe_priority_or_lower: Option<u8>,
) -> QueryBuilder<'static, MySql> {
// NB: Query cannot be statically checked by sqlx
let mut query_builder: QueryBuilder<MySql> = QueryBuilder::new(
r#"
UPDATE generic_inference_jobs
SET status='cancelled_by_system'
WHERE status IN(
"#
);
let job_statuses = job_statuses.into_iter()
.map(|status| match status {
KillableStatus::Failed => JobStatus::AttemptFailed.to_str(),
KillableStatus::Pending => JobStatus::Pending.to_str(),
KillableStatus::Started => JobStatus::Started.to_str(),
})
.collect::<Vec<_>>();
// NB: Syntax will be wrong if list has zero length
let mut separated = query_builder.separated(", ");
for value_type in job_statuses.into_iter() {
separated.push_bind(value_type);
}
separated.push_unseparated(") ");
if let Some(priority) = maybe_priority_or_lower {
query_builder.push(format!(" AND priority_level <= {priority} "));
}
match target {
KillableTarget::AllJobs => {
// No need to modify query.
}
KillableTarget::Category(category) => {
query_builder.push(" AND inference_category = ");
query_builder.push_bind(category);
}
KillableTarget::ModelType(model_type) => {
query_builder.push(" AND maybe_model_type = ");
query_builder.push_bind(model_type);
}
}
query_builder
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use regex::Regex;
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
use crate::queries::generic_inference::web::kill_generic_inference_jobs::{KillableStatus, KillableTarget, query_builder};
fn cleanup_query(query: &str) -> String {
let regex = Regex::new(r#"\s+"#).unwrap();
let result = regex.replace_all(query, " ").trim().to_string();
result
}
#[test]
fn test_statuses() {
let statuses = HashSet::from([KillableStatus::Failed]);
let builder = query_builder(statuses, KillableTarget::AllJobs, None);
let query = cleanup_query(&builder.into_sql());
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?)".to_string());
let statuses = HashSet::from([KillableStatus::Failed, KillableStatus::Pending, KillableStatus::Started]);
let builder = query_builder(statuses, KillableTarget::AllJobs, None);
let query = cleanup_query(&builder.into_sql());
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?, ?, ?)".to_string());
}
#[test]
fn test_priority() {
let statuses = HashSet::from([KillableStatus::Failed]);
let builder = query_builder(statuses, KillableTarget::AllJobs, Some(10));
let query = cleanup_query(&builder.into_sql());
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?) AND priority_level <= 10".to_string());
}
#[test]
fn test_category_target() {
let statuses = HashSet::from([KillableStatus::Failed]);
let builder = query_builder(statuses, KillableTarget::Category(InferenceCategory::LipsyncAnimation), None);
let query = cleanup_query(&builder.into_sql());
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?) AND inference_category = ?".to_string());
}
#[test]
fn test_model_target() {
let statuses = HashSet::from([KillableStatus::Failed]);
let builder = query_builder(statuses, KillableTarget::ModelType(InferenceModelType::RvcV2), None);
let query = cleanup_query(&builder.into_sql());
assert_eq!(query, "UPDATE generic_inference_jobs SET status='cancelled_by_system' WHERE status IN( ?) AND maybe_model_type = ?".to_string());
}
}
@@ -1,3 +1,4 @@
pub mod get_inference_job_status;
pub mod get_pending_inference_job_count;
pub mod insert_generic_inference_job;
pub mod kill_generic_inference_jobs;
+4 -1
View File
@@ -22,4 +22,7 @@ pub mod vocoder;
pub mod voice_clone_requests;
pub mod voice_conversion;
pub mod voice_designer;
pub mod w2l;
pub mod w2l;
pub mod model_weights;
@@ -0,0 +1,103 @@
use container_common::anyhow_result::AnyhowResult;
use sqlx::MySqlPool;
use enums::by_table::model_weights::{
weights_types::WeightsType,
weights_category::WeightsCategory,
};
use log::warn;
use enums::common::visibility::Visibility;
use tokens::tokens::{ users::UserToken, model_weights::ModelWeightToken };
pub struct CreateModelWeightsArgs<'a> {
pub token: &'a ModelWeightToken,
pub weights_type: WeightsType,
pub weights_category: WeightsCategory,
pub title: String,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: Option<&'a UserToken>,
pub creator_ip_address: &'a str,
pub creator_set_visibility: Visibility,
pub maybe_last_update_user_token: Option<String>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_total_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_negative_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub version: i32,
pub mysql_pool: &'a MySqlPool,
}
pub async fn create_weight(args: CreateModelWeightsArgs<'_>) -> AnyhowResult<ModelWeightToken> {
let model_weights_token = ModelWeightToken::generate();
let transaction = args.mysql_pool.begin().await?;
let query_result = sqlx
::query!(
r#"
INSERT INTO model_weights
SET
token = ?,
weights_type = ?,
weights_category = ?,
title = ?,
maybe_thumbnail_token = ?,
description_markdown = ?,
description_rendered_html = ?,
creator_user_token = ?,
creator_ip_address = ?,
creator_set_visibility = ?,
maybe_last_update_user_token = ?,
original_download_url = ?,
original_filename = ?,
file_size_bytes = ?,
file_checksum_sha2 = ?,
private_bucket_hash = ?,
maybe_private_bucket_prefix = ?,
maybe_private_bucket_extension = ?,
cached_user_ratings_total_count = ?,
cached_user_ratings_positive_count = ?,
cached_user_ratings_negative_count = ?,
maybe_cached_user_ratings_ratio = ?,
version = ?
"#,
args.token.as_str(),
args.weights_type.to_str(),
args.weights_category.to_str(),
args.title,
args.maybe_thumbnail_token,
args.description_markdown,
args.description_rendered_html,
args.creator_user_token.as_deref(),
args.creator_ip_address,
args.creator_set_visibility.to_str(),
args.maybe_last_update_user_token,
args.original_download_url,
args.original_filename,
args.file_size_bytes,
args.file_checksum_sha2,
args.private_bucket_hash,
args.maybe_private_bucket_prefix,
args.maybe_private_bucket_extension,
args.cached_user_ratings_total_count,
args.cached_user_ratings_positive_count,
args.cached_user_ratings_negative_count,
args.maybe_cached_user_ratings_ratio,
args.version
)
.execute(args.mysql_pool).await;
match query_result {
Ok(_) => { Ok(model_weights_token) }
Err(err) => {
transaction.rollback().await?;
warn!("Transaction failure: {:?}", err);
Err(err.into())
}
}
}
@@ -0,0 +1,82 @@
use sqlx::MySqlPool;
use errors::AnyhowResult;
use tokens::tokens::model_weights::ModelWeightToken;
pub async fn delete_weights_as_user(
weight_token: &ModelWeightToken,
mysql_pool: &MySqlPool
) -> AnyhowResult<()> {
let _r = sqlx
::query!(
r#"
UPDATE model_weights
SET
user_deleted_at = CURRENT_TIMESTAMP
WHERE
token = ?
LIMIT 1
"#,
weight_token.to_string()
)
.execute(mysql_pool).await?;
Ok(())
}
pub async fn delete_weights_as_mod(weight_token: &ModelWeightToken, mysql_pool: &MySqlPool) -> AnyhowResult<()> {
let _r = sqlx
::query!(
r#"
UPDATE model_weights
SET
mod_deleted_at = CURRENT_TIMESTAMP
WHERE
token = ?
LIMIT 1
"#,
weight_token.to_string()
)
.execute(mysql_pool).await?;
Ok(())
}
pub async fn undelete_weights_as_user(
weight_token: &ModelWeightToken,
mysql_pool: &MySqlPool
) -> AnyhowResult<()> {
let _r = sqlx
::query!(
r#"
UPDATE model_weights
SET
user_deleted_at = NULL
WHERE
token = ?
LIMIT 1
"#,
weight_token.to_string()
)
.execute(mysql_pool).await?;
Ok(())
}
pub async fn undelete_weights_as_mod(
weight_token: &ModelWeightToken,
mysql_pool: &MySqlPool
) -> AnyhowResult<()> {
let _r = sqlx
::query!(
r#"
UPDATE model_weights
SET
mod_deleted_at = NULL
WHERE
token = ?
LIMIT 1
"#,
weight_token.to_string()
)
.execute(mysql_pool).await?;
Ok(())
}
@@ -0,0 +1,244 @@
use container_common::anyhow_result::AnyhowResult;
use sqlx::{ MySqlPool, MySql };
use sqlx::pool::PoolConnection;
use anyhow::anyhow;
use log::{ error };
use enums::by_table::model_weights::weights_types::WeightsType;
use enums::by_table::model_weights::weights_category::WeightsCategory;
use enums::common::visibility::Visibility;
use tokens::tokens::{ users::UserToken, model_weights::ModelWeightToken };
use chrono::{ DateTime, Utc };
// Notes ensure that Enums have sqlx::Type
// 'weights_type: enums::by_table::model_weights::weights_types::WeightsType' use this to map
// Retrieved Model Weight can be constrained to the fields that are needed
pub struct RetrivedModelWeight {
pub token: ModelWeightToken,
pub title: String,
pub weights_type: WeightsType,
pub weights_category: WeightsCategory,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: UserToken,
pub creator_ip_address: String,
pub creator_set_visibility: Visibility,
pub maybe_last_update_user_token: Option<UserToken>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_negative_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_total_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub cached_user_ratings_last_updated_at: DateTime<Utc>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub user_deleted_at: Option<DateTime<Utc>>,
pub mod_deleted_at: Option<DateTime<Utc>>,
}
pub async fn get_weight_by_token(
weight_token: &ModelWeightToken,
can_see_deleted: bool,
mysql_pool: &MySqlPool
) -> AnyhowResult<Option<RetrivedModelWeight>> {
let mut connection = mysql_pool.acquire().await?;
get_weights_by_token_with_connection(weight_token, can_see_deleted, &mut connection).await
}
pub async fn get_weights_by_token_with_connection(
weight_token: &ModelWeightToken,
can_see_deleted: bool,
mysql_connection: &mut PoolConnection<MySql>
) -> AnyhowResult<Option<RetrivedModelWeight>> {
let maybe_result = if can_see_deleted {
select_include_deleted(weight_token, mysql_connection).await
} else {
select_without_deleted(weight_token, mysql_connection).await
};
let record: RawWeight = match maybe_result {
Ok(record) => record,
Err(sqlx::Error::RowNotFound) => {
return Ok(None);
}
Err(err) => {
error!("Error fetching weights by token: {:?}", err);
return Err(anyhow!("Error fetching weights by token: {:?}", err));
}
};
// unwrap the result
Ok(
Some(RetrivedModelWeight {
token: record.token,
title: record.title,
weights_type: record.weights_type,
weights_category: record.weights_category,
maybe_thumbnail_token: record.maybe_thumbnail_token,
description_markdown: record.description_markdown,
description_rendered_html: record.description_rendered_html,
creator_user_token: record.creator_user_token,
creator_ip_address: record.creator_ip_address,
creator_set_visibility: record.creator_set_visibility,
maybe_last_update_user_token: record.maybe_last_update_user_token,
original_download_url: record.original_download_url,
original_filename: record.original_filename,
file_size_bytes: record.file_size_bytes,
file_checksum_sha2: record.file_checksum_sha2,
private_bucket_hash: record.private_bucket_hash,
maybe_private_bucket_prefix: record.maybe_private_bucket_prefix,
maybe_private_bucket_extension: record.maybe_private_bucket_extension,
cached_user_ratings_negative_count: record.cached_user_ratings_negative_count,
cached_user_ratings_positive_count: record.cached_user_ratings_positive_count,
cached_user_ratings_total_count: record.cached_user_ratings_total_count,
maybe_cached_user_ratings_ratio: record.maybe_cached_user_ratings_ratio,
cached_user_ratings_last_updated_at: record.cached_user_ratings_last_updated_at,
version: record.version,
created_at: record.created_at,
updated_at: record.updated_at,
user_deleted_at: record.user_deleted_at,
mod_deleted_at: record.mod_deleted_at,
})
)
}
async fn select_include_deleted(
weight_token: &ModelWeightToken,
mysql_connection: &mut PoolConnection<MySql>
) -> Result<RawWeight, sqlx::Error> {
sqlx
::query_as!(
RawWeight,
r#"
SELECT
wt.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
wt.title,
wt.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
wt.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,
wt.maybe_thumbnail_token,
wt.description_markdown,
wt.description_rendered_html,
wt.creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,
wt.creator_ip_address,
wt.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
wt.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,
wt.original_download_url,
wt.original_filename,
wt.file_size_bytes,
wt.file_checksum_sha2,
wt.private_bucket_hash,
wt.maybe_private_bucket_prefix,
wt.maybe_private_bucket_extension,
wt.cached_user_ratings_negative_count,
wt.cached_user_ratings_positive_count,
wt.cached_user_ratings_total_count,
wt.maybe_cached_user_ratings_ratio,
wt.cached_user_ratings_last_updated_at,
wt.version,
wt.created_at,
wt.updated_at,
wt.user_deleted_at,
wt.mod_deleted_at
FROM model_weights as wt
WHERE
wt.token = ?
"#,
weight_token.as_str()
)
.fetch_one(&mut **mysql_connection).await
}
async fn select_without_deleted(
weight_token: &ModelWeightToken,
mysql_connection: &mut PoolConnection<MySql>
) -> Result<RawWeight, sqlx::Error> {
//as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
//as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`
sqlx
::query_as!(
RawWeight,
r#"
SELECT
wt.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
wt.title,
wt.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
wt.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,
wt.maybe_thumbnail_token,
wt.description_markdown,
wt.description_rendered_html,
wt.creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,
wt.creator_ip_address,
wt.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
wt.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,
wt.original_download_url,
wt.original_filename,
wt.file_size_bytes,
wt.file_checksum_sha2,
wt.private_bucket_hash,
wt.maybe_private_bucket_prefix,
wt.maybe_private_bucket_extension,
wt.cached_user_ratings_negative_count,
wt.cached_user_ratings_positive_count,
wt.cached_user_ratings_total_count,
wt.maybe_cached_user_ratings_ratio,
wt.cached_user_ratings_last_updated_at,
wt.version,
wt.created_at,
wt.updated_at,
wt.user_deleted_at,
wt.mod_deleted_at
FROM model_weights as wt
WHERE
wt.token = ?
AND wt.user_deleted_at IS NULL
AND wt.mod_deleted_at IS NULL
"#,
weight_token.as_str()
)
.fetch_one(&mut **mysql_connection).await
}
// RawWeight is the struct that is returned from the database in raw form.
#[derive(Serialize)]
pub struct RawWeight {
pub token: ModelWeightToken,
pub title: String,
pub weights_type: WeightsType,
pub weights_category: WeightsCategory,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: UserToken,
pub creator_ip_address: String,
pub creator_set_visibility: Visibility,
pub maybe_last_update_user_token: Option<UserToken>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_negative_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_total_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub cached_user_ratings_last_updated_at: DateTime<Utc>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub user_deleted_at: Option<DateTime<Utc>>,
pub mod_deleted_at: Option<DateTime<Utc>>,
}
@@ -0,0 +1,280 @@
use chrono::{DateTime, Utc};
use sqlx::{Acquire, MySqlConnection, MySqlPool};
use enums::by_table::model_weights::{
weights_category::WeightsCategory,
weights_types::WeightsType,
};
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use tokens::tokens::model_weights::ModelWeightToken;
use tokens::tokens::users::UserToken;
#[derive(Serialize)]
pub struct WeightsJoinUserRecord {
pub token: ModelWeightToken,
pub weights_type: WeightsType,
pub weights_category: WeightsCategory,
pub title: String,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: UserToken,
pub creator_ip_address: String,
pub creator_set_visibility: Visibility,
pub maybe_last_update_user_token: Option<UserToken>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_total_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_negative_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub cached_user_ratings_last_updated_at: DateTime<Utc>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub user_deleted_at: Option<DateTime<Utc>>,
pub mod_deleted_at: Option<DateTime<Utc>>,
pub creator_username: String,
pub creator_display_name: String,
pub creator_email_gravatar_hash: String,
}
pub async fn list_weights_by_creator_username(
mysql_pool: &MySqlPool,
creator_username: &str,
can_see_deleted: bool
) -> AnyhowResult<Vec<WeightsJoinUserRecord>> {
let mut connection = mysql_pool.acquire().await?;
let raw_weights: Vec<RawWeightJoinUser> = get_raw_weights_by_creator_username(&mut connection, creator_username, can_see_deleted).await?;
let weights_records: Vec<WeightsJoinUserRecord> = map_to_weights(raw_weights).await;
let filtered_weights: Vec<WeightsJoinUserRecord> = weights_records.into_iter().filter(|weight| {
weight.creator_username == creator_username && weight.creator_set_visibility == Visibility::Public && can_see_deleted
}).collect();
Ok(filtered_weights)
}
async fn get_raw_weights_by_creator_username(
connection: &mut MySqlConnection,
creator_username: &str,
can_see_deleted: bool
) -> AnyhowResult<Vec<RawWeightJoinUser>> {
let connection = connection.acquire().await?;
if can_see_deleted {
let raw_weights: Vec<RawWeightJoinUser> = sqlx::query_as!(
RawWeightJoinUser,
r#"
SELECT
mw.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
mw.title,
mw.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
mw.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,
mw.maybe_thumbnail_token,
mw.description_markdown,
mw.description_rendered_html,
users.token as `creator_user_token: tokens::tokens::users::UserToken`,
users.username as creator_username,
users.display_name as creator_display_name,
users.email_gravatar_hash as creator_email_gravatar_hash,
mw.creator_ip_address,
mw.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
mw.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,
mw.original_download_url,
mw.original_filename,
mw.file_size_bytes,
mw.file_checksum_sha2,
mw.private_bucket_hash,
mw.maybe_private_bucket_prefix,
mw.maybe_private_bucket_extension,
mw.cached_user_ratings_negative_count,
mw.cached_user_ratings_positive_count,
mw.cached_user_ratings_total_count,
mw.maybe_cached_user_ratings_ratio,
mw.cached_user_ratings_last_updated_at,
mw.version,
mw.created_at,
mw.updated_at,
mw.user_deleted_at,
mw.mod_deleted_at
FROM model_weights as mw
JOIN users
ON users.token = mw.creator_user_token
WHERE
users.username = ?
"#,
creator_username).fetch_all(connection)
.await?;
Ok(raw_weights)
} else {
let raw_weights: Vec<RawWeightJoinUser> = sqlx::query_as!(
RawWeightJoinUser,
r#"
SELECT
mw.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
mw.title,
mw.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
mw.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,
mw.maybe_thumbnail_token,
mw.description_markdown,
mw.description_rendered_html,
users.token as `creator_user_token: tokens::tokens::users::UserToken`,
users.username as creator_username,
users.display_name as creator_display_name,
users.email_gravatar_hash as creator_email_gravatar_hash,
mw.creator_ip_address,
mw.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
mw.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,
mw.original_download_url,
mw.original_filename,
mw.file_size_bytes,
mw.file_checksum_sha2,
mw.private_bucket_hash,
mw.maybe_private_bucket_prefix,
mw.maybe_private_bucket_extension,
mw.cached_user_ratings_negative_count,
mw.cached_user_ratings_positive_count,
mw.cached_user_ratings_total_count,
mw.maybe_cached_user_ratings_ratio,
mw.cached_user_ratings_last_updated_at,
mw.version,
mw.created_at,
mw.updated_at,
mw.user_deleted_at,
mw.mod_deleted_at
FROM model_weights as mw
JOIN users
ON users.token = mw.creator_user_token
WHERE
users.username = ?
AND mw.user_deleted_at IS NULL
AND mw.mod_deleted_at IS NULL
"#,
creator_username).fetch_all(connection).await?;
Ok(raw_weights)
}
}
async fn map_to_weights(dataset:Vec<RawWeightJoinUser>) -> Vec<WeightsJoinUserRecord> {
let weights: Vec<WeightsJoinUserRecord> = dataset
.into_iter()
.map(|dataset: RawWeightJoinUser| {
WeightsJoinUserRecord {
token: dataset.token,
title: dataset.title,
weights_type: dataset.weights_type,
weights_category: dataset.weights_category,
maybe_thumbnail_token: dataset.maybe_thumbnail_token,
description_markdown: dataset.description_markdown,
description_rendered_html: dataset.description_rendered_html,
creator_user_token: dataset.creator_user_token,
creator_ip_address: dataset.creator_ip_address,
creator_set_visibility: dataset.creator_set_visibility,
maybe_last_update_user_token: dataset.maybe_last_update_user_token,
original_download_url: dataset.original_download_url,
original_filename: dataset.original_filename,
file_size_bytes: dataset.file_size_bytes,
file_checksum_sha2: dataset.file_checksum_sha2,
private_bucket_hash: dataset.private_bucket_hash,
maybe_private_bucket_prefix: dataset.maybe_private_bucket_prefix,
maybe_private_bucket_extension: dataset.maybe_private_bucket_extension,
cached_user_ratings_negative_count: dataset.cached_user_ratings_negative_count,
cached_user_ratings_positive_count: dataset.cached_user_ratings_positive_count,
cached_user_ratings_total_count: dataset.cached_user_ratings_total_count,
maybe_cached_user_ratings_ratio: dataset.maybe_cached_user_ratings_ratio,
cached_user_ratings_last_updated_at: dataset.cached_user_ratings_last_updated_at,
version: dataset.version,
created_at: dataset.created_at,
updated_at: dataset.updated_at,
user_deleted_at: dataset.user_deleted_at,
mod_deleted_at: dataset.mod_deleted_at,
creator_username:dataset.creator_username,
creator_display_name:dataset.creator_display_name,
creator_email_gravatar_hash:dataset.creator_email_gravatar_hash
}
}).collect();
weights
}
#[derive(Serialize)]
pub struct RawWeightJoinUser {
pub token: ModelWeightToken,
pub weights_type: WeightsType,
pub weights_category: WeightsCategory,
pub title: String,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: UserToken,
pub creator_ip_address: String,
pub creator_set_visibility: Visibility,
pub maybe_last_update_user_token: Option<UserToken>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_total_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_negative_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub cached_user_ratings_last_updated_at: DateTime<Utc>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub user_deleted_at: Option<DateTime<Utc>>,
pub mod_deleted_at: Option<DateTime<Utc>>,
pub creator_username: String,
pub creator_display_name: String,
pub creator_email_gravatar_hash: String,
}
@@ -0,0 +1,589 @@
#![forbid(unused_imports)]
#![forbid(unused_mut)]
#![forbid(unused_variables)]
use chrono::{ DateTime, Utc };
use sqlx::MySqlPool;
use config::shared_constants::DEFAULT_MYSQL_QUERY_RESULT_PAGE_SIZE;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use tokens::tokens::users::UserToken;
use tokens::tokens::model_weights::ModelWeightToken;
use enums::by_table::model_weights::{
weights_types::WeightsType,
weights_category::WeightsCategory,
};
#[derive(Serialize)]
pub struct WeightsPage {
pub weights: Vec<WeightJoinUser>,
pub sort_ascending: bool,
pub first_id: Option<i64>,
pub last_id: Option<i64>,
}
// TODO: figure out what you want to expose ? since we don't have specs really
#[derive(Serialize)]
pub struct WeightJoinUser {
pub weight_id: i64,
pub token: ModelWeightToken,
pub weights_type: WeightsType,
pub weights_category: WeightsCategory,
pub title: String,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: UserToken,
pub creator_ip_address: String,
pub creator_set_visibility: Visibility,
pub maybe_last_update_user_token: Option<UserToken>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_total_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_negative_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub cached_user_ratings_last_updated_at: DateTime<Utc>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub user_deleted_at: Option<DateTime<Utc>>,
pub mod_deleted_at: Option<DateTime<Utc>>,
pub creator_username: String,
pub creator_display_name: String,
pub creator_email_gravatar_hash: String,
}
pub struct ListWeightsQueryBuilder {
scope_creator_username: Option<String>,
include_mod_deleted_results: bool,
include_user_deleted_results: bool,
include_user_hidden: bool,
sort_ascending: bool,
weights_type: Option<WeightsType>,
weights_category: Option<WeightsCategory>,
offset: Option<u64>,
limit: u16,
cursor_is_reversed: bool,
}
impl ListWeightsQueryBuilder {
pub fn new() -> Self {
Self {
scope_creator_username: None,
include_user_hidden: false,
include_mod_deleted_results: false,
include_user_deleted_results: false,
sort_ascending: false,
weights_type: None,
weights_category: None,
offset: None,
limit: DEFAULT_MYSQL_QUERY_RESULT_PAGE_SIZE,
cursor_is_reversed: false,
}
}
pub fn scope_creator_username(mut self, scope_creator_username: Option<&str>) -> Self {
self.scope_creator_username = scope_creator_username.map(|u| u.to_string());
self
}
pub fn include_user_hidden(mut self, include_user_hidden: bool) -> Self {
self.include_user_hidden = include_user_hidden;
self
}
pub fn include_mod_deleted_results(mut self, include_mod_deleted_results: bool) -> Self {
self.include_mod_deleted_results = include_mod_deleted_results;
self
}
pub fn include_user_deleted_results(mut self, include_user_deleted_results: bool) -> Self {
self.include_user_deleted_results = include_user_deleted_results;
self
}
pub fn sort_ascending(mut self, sort_ascending: bool) -> Self {
self.sort_ascending = sort_ascending;
self
}
pub fn weights_type(mut self, weights_type: WeightsType) -> Self {
self.weights_type = Some(weights_type);
self
}
pub fn weights_category(mut self, weights_category: WeightsCategory) -> Self {
self.weights_category = Some(weights_category);
self
}
pub fn offset(mut self, offset: Option<u64>) -> Self {
self.offset = offset;
self
}
pub fn limit(mut self, limit: u16) -> Self {
self.limit = limit;
self
}
pub fn cursor_is_reversed(mut self, cursor_is_reversed: bool) -> Self {
self.cursor_is_reversed = cursor_is_reversed;
self
}
async fn perform_internal_query(
&self,
mysql_pool: &MySqlPool
) -> AnyhowResult<Vec<RawWeightJoinUser>> {
let query = self.build_query_string();
//println!("HERE! query: {}", query);
//panic!("query: {:?}", query);
let mut query = sqlx::query_as::<_, RawWeightJoinUser>(&query);
// NB: The following bindings must match the order of the query builder !!
if let Some(username) = self.scope_creator_username.as_deref() {
query = query.bind(username);
}
if let Some(weights_type) = self.weights_type {
query = query.bind(weights_type);
}
if let Some(weights_category) = self.weights_category {
query = query.bind(weights_category);
}
query = query.bind(self.limit);
if let Some(offset) = self.offset {
query = query.bind(offset);
}
let mut results = query.fetch_all(mysql_pool).await?;
if self.cursor_is_reversed {
results.reverse();
}
Ok(results)
}
pub async fn perform_query_for_page(
&self,
mysql_pool: &MySqlPool
) -> AnyhowResult<WeightsPage> {
let weights = self.perform_internal_query(mysql_pool).await?;
let first_id = weights.first().map(|raw_result| raw_result.weight_id);
let last_id = weights.last().map(|raw_result| raw_result.weight_id);
let weights = weights
.into_iter()
.map(|record| {
// map the raw result into a WeightJoinUser
WeightJoinUser {
weight_id: record.weight_id,
token: record.token,
weights_type: WeightsType::from_str(record.weights_type.as_str()).unwrap(),
weights_category: WeightsCategory::from_str(
record.weights_category.as_str()
).unwrap(),
title: record.title,
maybe_thumbnail_token: record.maybe_thumbnail_token,
description_markdown: record.description_markdown,
description_rendered_html: record.description_rendered_html,
creator_user_token: UserToken::new_from_str(&record.creator_user_token),
creator_ip_address: record.creator_ip_address,
creator_set_visibility: Visibility::from_str(
&record.creator_set_visibility
).unwrap(),
maybe_last_update_user_token: record.maybe_last_update_user_token.map(|token|
UserToken::new_from_str(&token)
),
original_download_url: record.original_download_url,
original_filename: record.original_filename,
file_size_bytes: record.file_size_bytes,
file_checksum_sha2: record.file_checksum_sha2,
private_bucket_hash: record.private_bucket_hash,
maybe_private_bucket_prefix: record.maybe_private_bucket_prefix,
maybe_private_bucket_extension: record.maybe_private_bucket_extension,
cached_user_ratings_total_count: record.cached_user_ratings_total_count,
cached_user_ratings_positive_count: record.cached_user_ratings_positive_count,
cached_user_ratings_negative_count: record.cached_user_ratings_negative_count,
maybe_cached_user_ratings_ratio: record.maybe_cached_user_ratings_ratio,
cached_user_ratings_last_updated_at: record.cached_user_ratings_last_updated_at,
version: record.version,
created_at: record.created_at,
updated_at: record.updated_at,
user_deleted_at: record.user_deleted_at,
mod_deleted_at: record.mod_deleted_at,
creator_username: record.creator_username,
creator_display_name: record.creator_display_name,
creator_email_gravatar_hash: record.creator_email_gravatar_hash,
}
})
.collect::<Vec<WeightJoinUser>>();
Ok(WeightsPage {
weights,
sort_ascending: self.sort_ascending,
first_id,
last_id,
})
}
pub fn build_query_string(&self) -> String {
let mut query =
r#"
SELECT
model_weights.id AS weight_id,
model_weights.token,
model_weights.weights_type,
model_weights.weights_category,
model_weights.title,
model_weights.maybe_thumbnail_token,
model_weights.description_markdown,
model_weights.description_rendered_html,
model_weights.creator_user_token,
model_weights.creator_ip_address,
model_weights.creator_set_visibility,
model_weights.maybe_last_update_user_token,
model_weights.original_download_url,
model_weights.original_filename,
model_weights.file_size_bytes,
model_weights.file_checksum_sha2,
model_weights.private_bucket_hash,
model_weights.maybe_private_bucket_prefix,
model_weights.maybe_private_bucket_extension,
model_weights.cached_user_ratings_total_count,
model_weights.cached_user_ratings_positive_count,
model_weights.cached_user_ratings_negative_count,
model_weights.maybe_cached_user_ratings_ratio,
model_weights.cached_user_ratings_last_updated_at,
model_weights.version,
model_weights.created_at,
model_weights.updated_at,
model_weights.user_deleted_at,
model_weights.mod_deleted_at,
users.username AS creator_username,
users.display_name AS creator_display_name,
users.email_gravatar_hash AS creator_email_gravatar_hash
FROM model_weights
JOIN users
ON users.token = model_weights.creator_user_token
"#.to_string();
query.push_str(&self.build_predicates());
query
}
pub fn build_predicates(&self) -> String {
// NB: Reverse cursors require us to invert the sort direction.
let mut sort_ascending = self.sort_ascending;
let mut first_predicate_added = false;
let mut query = "".to_string();
if let Some(_offset) = self.offset {
if !first_predicate_added {
query.push_str(" WHERE");
first_predicate_added = true;
} else {
query.push_str(" AND");
}
if sort_ascending {
if self.cursor_is_reversed {
// NB: We're searching backwards.
query.push_str(" model_weights.id");
sort_ascending = !sort_ascending;
} else {
query.push_str(" model_weights.id");
}
} else {
if self.cursor_is_reversed {
// NB: We're searching backwards.
query.push_str(" model_weights.id");
sort_ascending = !sort_ascending;
} else {
query.push_str(" model_weights.id");
}
}
}
if let Some(_username) = self.scope_creator_username.as_deref() {
if !first_predicate_added {
query.push_str(" WHERE users.username = ?");
first_predicate_added = true;
} else {
query.push_str(" AND users.username = ?");
}
}
if let Some(_weights_type) = self.weights_type {
if !first_predicate_added {
query.push_str(" WHERE model_weights.weights_type = ?");
first_predicate_added = true;
} else {
query.push_str(" AND model_weights.weights_type = ?");
}
}
if let Some(_weights_category) = self.weights_category {
if !first_predicate_added {
query.push_str(" WHERE model_weights.weights_category = ?");
first_predicate_added = true;
} else {
query.push_str(" AND model_weights.weights_category = ?");
}
}
if !self.include_user_hidden {
if !first_predicate_added {
query.push_str(" WHERE model_weights.creator_set_visibility = 'public'");
first_predicate_added = true;
} else {
query.push_str(" AND model_weights.creator_set_visibility = 'public'");
}
}
if !self.include_mod_deleted_results {
if !first_predicate_added {
query.push_str(" WHERE model_weights.mod_deleted_at IS NULL");
first_predicate_added = true;
} else {
query.push_str(" AND model_weights.mod_deleted_at IS NULL");
}
}
if !self.include_user_deleted_results {
if !first_predicate_added {
query.push_str(" WHERE model_weights.user_deleted_at IS NULL");
first_predicate_added = true;
} else {
query.push_str(" AND model_weights.user_deleted_at IS NULL");
}
}
if sort_ascending {
query.push_str(" ORDER BY model_weights.id ASC");
} else {
query.push_str(" ORDER BY model_weights.id DESC");
}
if self.limit > 0 {
query.push_str(" LIMIT ?");
}
if let Some(_) = self.offset {
query.push_str(" OFFSET ?");
}
query
}
}
#[derive(Serialize)]
#[derive(sqlx::FromRow)]
struct RawWeightJoinUser {
pub weight_id: i64,
pub token: ModelWeightToken,
pub weights_type: String,
pub weights_category: String,
pub title: String,
pub maybe_thumbnail_token: Option<String>,
pub description_markdown: String,
pub description_rendered_html: String,
pub creator_user_token: String,
pub creator_ip_address: String,
pub creator_set_visibility: String,
pub maybe_last_update_user_token: Option<String>,
pub original_download_url: Option<String>,
pub original_filename: Option<String>,
pub file_size_bytes: i32,
pub file_checksum_sha2: String,
pub private_bucket_hash: String,
pub maybe_private_bucket_prefix: Option<String>,
pub maybe_private_bucket_extension: Option<String>,
pub cached_user_ratings_total_count: u32,
pub cached_user_ratings_positive_count: u32,
pub cached_user_ratings_negative_count: u32,
pub maybe_cached_user_ratings_ratio: Option<f32>,
pub cached_user_ratings_last_updated_at: DateTime<Utc>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub user_deleted_at: Option<DateTime<Utc>>,
pub mod_deleted_at: Option<DateTime<Utc>>,
pub creator_username: String,
pub creator_display_name: String,
pub creator_email_gravatar_hash: String,
}
#[cfg(test)]
mod tests {
use crate::queries::model_weights::list_weights_query_builder::ListWeightsQueryBuilder;
use enums::by_table::model_weights::{
weights_types::WeightsType,
weights_category::WeightsCategory,
};
#[test]
fn predicates_without_scoping() {
let query_builder = ListWeightsQueryBuilder::new();
println!("Query HERE! {}", &query_builder.build_predicates());
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.creator_set_visibility = 'public' \
AND model_weights.mod_deleted_at IS NULL \
AND model_weights.user_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_scoped_to_user() {
let query_builder = ListWeightsQueryBuilder::new().scope_creator_username(Some("echelon"));
assert_eq!(
&query_builder.build_predicates(),
" WHERE users.username = ? \
AND model_weights.creator_set_visibility = 'public' \
AND model_weights.mod_deleted_at IS NULL \
AND model_weights.user_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_scoped_to_weights_type() {
let query_builder = ListWeightsQueryBuilder::new().weights_type(WeightsType::RvcV2);
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.weights_type = ? \
AND model_weights.creator_set_visibility = 'public' \
AND model_weights.mod_deleted_at IS NULL \
AND model_weights.user_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_scoped_to_weights_category() {
let query_builder = ListWeightsQueryBuilder::new().weights_category(
WeightsCategory::VoiceConversion
);
println!("Query HERE! {}", &query_builder.build_predicates());
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.weights_category = ? \
AND model_weights.creator_set_visibility = 'public' \
AND model_weights.mod_deleted_at IS NULL \
AND model_weights.user_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_including_user_hidden() {
let query_builder = ListWeightsQueryBuilder::new().include_user_hidden(true);
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.mod_deleted_at IS NULL \
AND model_weights.user_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_including_mod_deleted() {
let query_builder = ListWeightsQueryBuilder::new().include_mod_deleted_results(true);
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.creator_set_visibility = 'public' \
AND model_weights.user_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_including_user_deleted() {
let query_builder = ListWeightsQueryBuilder::new().include_user_deleted_results(true);
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.creator_set_visibility = 'public' \
AND model_weights.mod_deleted_at IS NULL \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
#[test]
fn predicates_including_mod_deleted_and_user_deleted() {
let query_builder = ListWeightsQueryBuilder::new()
.include_mod_deleted_results(true)
.include_user_deleted_results(true);
assert_eq!(
&query_builder.build_predicates(),
" WHERE model_weights.creator_set_visibility = 'public' \
ORDER BY model_weights.id DESC \
LIMIT ?"
);
}
}
@@ -0,0 +1,7 @@
pub mod create_weight;
pub mod delete_weights;
pub mod get_weight;
pub mod update_weight;
pub mod list_weights_by_user;
pub mod list_weights_query_builder;
pub mod tests;
@@ -0,0 +1,37 @@
CREATE TABLE model_weights (
id BIGINT(20) NOT NULL AUTO_INCREMENT,
token VARCHAR(32) NOT NULL,
weights_type VARCHAR(32) NOT NULL,
weights_category VARCHAR(32) NOT NULL,
title VARCHAR(255) NOT NULL,
maybe_thumbnail_token VARCHAR(32) DEFAULT NULL,
description_markdown TEXT NOT NULL,
description_rendered_html TEXT NOT NULL,
creator_user_token VARCHAR(32) NOT NULL,
creator_ip_address VARCHAR(40) NOT NULL,
creator_set_visibility ENUM(
'public',
'hidden',
'private'
) NOT NULL DEFAULT 'public',
maybe_last_update_user_token VARCHAR(32) DEFAULT NULL,
original_download_url VARCHAR(512) DEFAULT NULL,
original_filename VARCHAR(255) DEFAULT NULL,
file_size_bytes INT(10) NOT NULL DEFAULT 0,
file_checksum_sha2 CHAR(64) NOT NULL,
private_bucket_hash VARCHAR(32) NOT NULL,
maybe_private_bucket_prefix VARCHAR(16) DEFAULT NULL,
maybe_private_bucket_extension VARCHAR(16) DEFAULT NULL,
cached_user_ratings_total_count INT(10) UNSIGNED NOT NULL DEFAULT 0,
cached_user_ratings_positive_count INT(10) UNSIGNED NOT NULL DEFAULT 0,
cached_user_ratings_negative_count INT(10) UNSIGNED NOT NULL DEFAULT 0,
maybe_cached_user_ratings_ratio FLOAT,
cached_user_ratings_last_updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
version INT NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
user_deleted_at TIMESTAMP NULL,
mod_deleted_at TIMESTAMP NULL,
PRIMARY KEY (id),
UNIQUE KEY (token)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -0,0 +1,599 @@
#[cfg(test)]
mod tests {
use std::result;
use anyhow::Ok;
use enums::by_table::model_weights::{weights_types, weights_category};
use sqlx::{MySqlPool, Acquire};
use rand::Rng;
use tokio;
use serial_test::serial;
use container_common::anyhow_result::AnyhowResult;
use sqlx::mysql::MySqlPoolOptions;
use config::shared_constants::{ DEFAULT_MYSQL_CONNECTION_STRING };
// common tests
use enums::by_table::model_weights::{
weights_types::WeightsType,
weights_category::WeightsCategory,
};
use enums::common::visibility::Visibility;
use tokens::tokens::{ users::UserToken, model_weights::ModelWeightToken };
use crate::queries::model_weights::create_weight::CreateModelWeightsArgs;
use crate::queries::model_weights::create_weight::create_weight;
use crate::queries::model_weights::get_weight::get_weight_by_token;
use crate::queries::model_weights::delete_weights::{ delete_weights_as_user, delete_weights_as_mod, undelete_weights_as_mod , undelete_weights_as_user};
use crate::queries::model_weights::list_weights_by_user::list_weights_by_creator_username;
use crate::queries::model_weights::list_weights_query_builder::ListWeightsQueryBuilder;
use crate::queries::users::user::get_user_token_by_username::get_user_token_by_username;
async fn setup() -> sqlx::Pool<sqlx::MySql> {
println!("Dropping database model_weights");
let db_connection_string = DEFAULT_MYSQL_CONNECTION_STRING;
let pool = MySqlPoolOptions::new()
.max_connections(3)
.connect(&db_connection_string).await
.unwrap();
// delete everything that exists in the database
delete_all_weights_for_table(&pool).await.unwrap();
pool
}
pub async fn delete_all_weights_for_table(mysql_pool: &MySqlPool) -> AnyhowResult<()> {
// write a query that deletes all weights
let _r = sqlx::query("DELETE FROM model_weights")
.execute(mysql_pool)
.await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_create_weights() -> AnyhowResult<()> {
let pool = setup().await;
// create a random token for the model weight
let mut rng = rand::thread_rng();
let random_number: u32 = rng.gen();
let model_weight_token1 = ModelWeightToken(random_number.to_string());
let creator_token1 = UserToken("creatorToken!1".to_string());
let args = CreateModelWeightsArgs {
token: &model_weight_token1, // replace with actual ModelWeightToken
weights_type: WeightsType::RvcV2, // replace with actual WeightsType
weights_category: WeightsCategory::VoiceConversion, // replace with actual WeightsCategory
title: "Title 1".to_string(),
maybe_thumbnail_token: Some("Thumbnail 1".to_string()),
description_markdown: "Description 1".to_string(),
description_rendered_html: "<p>Description 1</p>".to_string(),
creator_user_token: Some(&creator_token1), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 1".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum1".to_string(),
private_bucket_hash: "bucket_hash1".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &pool, // replace with actual MySqlPool
};
create_weight(args).await?;
let result = get_weight_by_token(&model_weight_token1, false, &pool).await?;
let result = result.unwrap();
// check if the result is the same as the args
assert_eq!(result.token, model_weight_token1);
assert_eq!(result.title, "Title 1".to_string());
assert_eq!(result.weights_type, WeightsType::RvcV2);
assert_eq!(result.weights_category, WeightsCategory::VoiceConversion);
assert_eq!(result.maybe_thumbnail_token, Some("Thumbnail 1".to_string()));
assert_eq!(result.description_markdown, "Description 1".to_string());
assert_eq!(result.description_rendered_html, "<p>Description 1</p>".to_string());
assert_eq!(result.creator_user_token, creator_token1);
assert_eq!(result.creator_ip_address, "192.168.1.1".to_string());
assert_eq!(result.creator_set_visibility, Visibility::Public);
assert_eq!(
result.maybe_last_update_user_token,
Some(UserToken("Last Update User Token 1".to_string()))
);
assert_eq!(result.original_download_url, Some("http://example.com/download1".to_string()));
assert_eq!(result.original_filename, Some("filename1.txt".to_string()));
assert_eq!(result.file_size_bytes, 1024);
assert_eq!(result.file_checksum_sha2, "checksum1".to_string());
assert_eq!(result.private_bucket_hash, "bucket_hash1".to_string());
assert_eq!(result.maybe_private_bucket_prefix, Some("_fake".to_string()));
assert_eq!(result.maybe_private_bucket_extension, Some("rvc".to_string()));
assert_eq!(result.cached_user_ratings_total_count, 10);
assert_eq!(result.cached_user_ratings_positive_count, 9);
assert_eq!(result.cached_user_ratings_negative_count, 1);
assert_eq!(result.maybe_cached_user_ratings_ratio, Some(0.9));
assert_eq!(result.version, 1);
Ok(())
}
#[tokio::test]
#[serial]
async fn test_delete_and_undelete_weights_user() -> AnyhowResult<()> {
let pool = setup().await;
// create a random token for the model weight
let mut rng = rand::thread_rng();
let random_number: u32 = rng.gen();
let model_weight_token1 = ModelWeightToken(random_number.to_string());
let creator_token1 = UserToken("creatorToken!1".to_string());
let args = CreateModelWeightsArgs {
token: &model_weight_token1, // replace with actual ModelWeightToken
weights_type: WeightsType::RvcV2, // replace with actual WeightsType
weights_category: WeightsCategory::VoiceConversion, // replace with actual WeightsCategory
title: "Title 1".to_string(),
maybe_thumbnail_token: Some("Thumbnail 1".to_string()),
description_markdown: "Description 1".to_string(),
description_rendered_html: "<p>Description 1</p>".to_string(),
creator_user_token: Some(&creator_token1), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 1".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum1".to_string(),
private_bucket_hash: "bucket_hash1".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &pool, // replace with actual MySqlPool
};
create_weight(args).await?;
delete_weights_as_user(&model_weight_token1, &pool).await?;
let result = get_weight_by_token(&model_weight_token1, true, &pool).await?;
let result = result.unwrap();
match result.user_deleted_at {
Some(date) => {
// `date` is the unwrapped value
// You can use `date` here
assert!(true, "user_deleted_at is Some");
}
None => {
// Handle the case where `user_deleted_at` is None
assert!(false, "user_deleted_at is None");
}
}
undelete_weights_as_user(&model_weight_token1, &pool).await?;
let result = get_weight_by_token(&model_weight_token1, true, &pool).await?;
let result = result.unwrap();
match result.user_deleted_at {
Some(date) => {
// `date` is the unwrapped value
// You can use `date` here
assert!(false, "user_deleted_at is Some");
}
None => {
// Handle the case where `user_deleted_at` is None
assert!(true, "user_deleted_at is None");
}
}
Ok(())
}
#[tokio::test]
#[serial]
async fn test_delete_and_undelete_weights_mod() -> AnyhowResult<()> {
let mut rng = rand::thread_rng();
let random_number: u32 = rng.gen();
let model_weight_token1 = ModelWeightToken(random_number.to_string());
let pool = setup().await;
// create a random token for the model weight
let creator_token1 = UserToken("creatorToken!1".to_string());
let args = CreateModelWeightsArgs {
token: &model_weight_token1, // replace with actual ModelWeightToken
weights_type: WeightsType::RvcV2, // replace with actual WeightsType
weights_category: WeightsCategory::VoiceConversion, // replace with actual WeightsCategory
title: "Title 1".to_string(),
maybe_thumbnail_token: Some("Thumbnail 1".to_string()),
description_markdown: "Description 1".to_string(),
description_rendered_html: "<p>Description 1</p>".to_string(),
creator_user_token: Some(&creator_token1), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some("Last Update User Token 1".to_string()),
original_download_url: Some("http://example.com/download1".to_string()),
original_filename: Some("filename1.txt".to_string()),
file_size_bytes: 1024,
file_checksum_sha2: "checksum1".to_string(),
private_bucket_hash: "bucket_hash1".to_string(),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &pool, // replace with actual MySqlPool
};
create_weight(args).await?;
delete_weights_as_mod(&model_weight_token1, &pool).await?;
let result = get_weight_by_token(&model_weight_token1, true, &pool).await?;
let result = result.unwrap();
match result.mod_deleted_at {
Some(date) => {
// `date` is the unwrapped value
// You can use `date` here
assert!(true, "mod_deleted_at is Some");
}
None => {
// Handle the case where `user_deleted_at` is None
assert!(false, "mod_deleted_at is None");
}
}
undelete_weights_as_mod(&model_weight_token1, &pool).await?;
let result = get_weight_by_token(&model_weight_token1, true, &pool).await?;
let result = result.unwrap();
match result.mod_deleted_at {
Some(date) => {
// `date` is the unwrapped value
// You can use `date` here
assert!(false, "mod_deleted is Some");
}
None => {
// Handle the case where `mod_deleted` is None
assert!(true, "mod_deleted is None");
}
}
Ok(())
}
#[tokio::test]
#[serial]
async fn list_all_weights_by_user() -> AnyhowResult<()> {
let pool = setup().await;
let creator_username = "hanashi".to_string();
let can_see_deleted = true;
seed_weights_with_category_and_type(WeightsType::LoRA,WeightsCategory::ImageGeneration,5,&creator_username).await?;
let weights_by_username = list_weights_by_creator_username(&pool, &creator_username, can_see_deleted).await?;
assert_eq!(weights_by_username.len(), 5);
Ok(())
}
async fn seed_weights_with_category_and_type(weights_type:WeightsType,weights_category:WeightsCategory,number_of_items:u32,creator_username:&str) -> AnyhowResult<()> {
let pool = setup().await;
let creator_token = get_user_token_by_username(&creator_username, &pool).await?.unwrap_or_else(
|| panic!("Could not find user with username {}", creator_username)
);
for i in 0..number_of_items {
let mut rng = rand::thread_rng();
let number: u32 = rng.gen();
let model_weight_token = ModelWeightToken(number.to_string());
let args = CreateModelWeightsArgs {
token: &model_weight_token, // replace with actual ModelWeightToken
weights_type:weights_type, // replace with actual WeightsType
weights_category: weights_category, // replace with actual WeightsCategory
title: format!("Title {}", i),
maybe_thumbnail_token: Some(format!("Thumbnail {}", i)),
description_markdown: format!("Description {}", i),
description_rendered_html: format!("<p>Description {}</p>", i),
creator_user_token: Some(&creator_token), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some(format!("Last Update User Token {}", i)),
original_download_url: Some(format!("http://example.com/download{}", i)),
original_filename: Some(format!("filename {}.txt", i)),
file_size_bytes: 1024,
file_checksum_sha2: format!("checksum{}", i),
private_bucket_hash: format!("bucket_hash{}", i),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &pool, // replace with actual MySqlPool
};
create_weight(args).await?;
}
Ok(())
}
// Tests paging for the list weights query builder
#[tokio::test]
#[serial]
async fn list_weights_query_build_test_paging() -> AnyhowResult<()> {
let pool = setup().await;
let creator_username = "hanashi".to_string();
seed_weights_with_category_and_type(WeightsType::LoRA,WeightsCategory::ImageGeneration,20,&creator_username).await?;
let qb = ListWeightsQueryBuilder::new()
.offset(Some(0))
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.limit(10)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false);
let result = qb.perform_query_for_page(&pool).await?;
// let result = qb.perform_query_for_page(&pool).await?;
assert_eq!(result.weights.len(), 10);
let qb = ListWeightsQueryBuilder::new()
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false)
.offset(Some(10))
.limit(10);
let result = qb.perform_query_for_page(&pool).await?;
assert_eq!(result.weights.len(), 10);
let qb = ListWeightsQueryBuilder::new()
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false)
.offset(Some(10))
.limit(10);
let result = qb.perform_query_for_page(&pool).await?;
assert_eq!(result.weights.len(), 10);
Ok(())
}
#[tokio::test]
#[serial]
async fn list_weights_query_build_test_asc_desc_cursor_reverse() -> AnyhowResult<()> {
let pool = setup().await;
let creator_username = "hanashi".to_string();
seed_weights_with_category_and_type(WeightsType::LoRA,WeightsCategory::ImageGeneration,10,&creator_username).await?;
let qb = ListWeightsQueryBuilder::new()
.offset(Some(0))
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.limit(10)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false)
.sort_ascending(true)
.cursor_is_reversed(false);
let result = qb.perform_query_for_page(&pool).await?;
// write code that will loop through the result and check if the ids are in ascending order
let mut previous_id = 0;
for weight in result.weights.iter() {
let current_id = weight.weight_id;
assert!(current_id > previous_id);
previous_id = current_id;
}
let qb = ListWeightsQueryBuilder::new()
.offset(Some(0))
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.limit(10)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false)
.sort_ascending(false)
.cursor_is_reversed(true);
let result = qb.perform_query_for_page(&pool).await?;
// write code that will loop through the result and check if the ids are in descending order
let mut previous_id
= 10000;
for weight in result.weights.iter() {
let current_id = weight.weight_id;
assert!(current_id < previous_id);
previous_id = current_id;
}
Ok(())
}
#[tokio::test]
#[serial]
// asc and desc tests
async fn list_weights_query_build_test_asc_desc() -> AnyhowResult<()> {
let pool = setup().await;
let creator_username = "hanashi".to_string();
seed_weights_with_category_and_type(WeightsType::LoRA,WeightsCategory::ImageGeneration,10,&creator_username).await?;
let qb = ListWeightsQueryBuilder::new()
.offset(Some(0))
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.limit(10)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false)
.sort_ascending(true);
let result = qb.perform_query_for_page(&pool).await?;
// write code that will loop through the result and check if the ids are in ascending order
let mut previous_id = 0;
for weight in result.weights.iter() {
let current_id = weight.weight_id;
assert!(current_id > previous_id);
previous_id = current_id;
}
let qb = ListWeightsQueryBuilder::new()
.offset(Some(0))
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.limit(10)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false)
.sort_ascending(false);
let result = qb.perform_query_for_page(&pool).await?;
// write code that will loop through the result and check if the ids are in descending order
let mut previous_id
= 10000;
for weight in result.weights.iter() {
let current_id = weight.weight_id;
assert!(current_id < previous_id);
previous_id = current_id;
}
Ok(())
}
#[tokio::test]
#[serial]
async fn list_weights_query_build_test() -> AnyhowResult<()> {
let pool = setup().await;
let creator_username = "hanashi".to_string();
let creator_token = get_user_token_by_username(&creator_username, &pool).await?.unwrap_or_else(
|| panic!("Could not find user with username {}", creator_username)
);
for i in 0..6 {
let weights_type = if i % 5 == 0 {
WeightsType::Tacotron2
} else if i % 5 == 1 {
WeightsType::LoRA
} else if i % 5 == 2 {
WeightsType::RvcV2
} else if i % 5 == 3 {
WeightsType::StableDiffusionXL
} else if i ^ 5 == 4 {
WeightsType::SoVitsSvc
} else {
WeightsType::StableDiffusion15
};
let weights_category = if i % 5 == 0 {
WeightsCategory::TextToSpeech
} else if i % 5 == 1 {
WeightsCategory::ImageGeneration
} else if i % 5 == 2 {
WeightsCategory::VoiceConversion
} else if i % 5 == 3 {
WeightsCategory::ImageGeneration
} else if i ^ 5 == 4 {
WeightsCategory::VoiceConversion
} else {
WeightsCategory::ImageGeneration
};
let mut rng = rand::thread_rng();
let number: u32 = rng.gen();
let model_weight_token = ModelWeightToken(number.to_string());
let args = CreateModelWeightsArgs {
token: &model_weight_token, // replace with actual ModelWeightToken
weights_type:weights_type, // replace with actual WeightsType
weights_category: weights_category, // replace with actual WeightsCategory
title: format!("Title {}", i),
maybe_thumbnail_token: Some(format!("Thumbnail {}", i)),
description_markdown: format!("Description {}", i),
description_rendered_html: format!("<p>Description {}</p>", i),
creator_user_token: Some(&creator_token), // replace with actual UserToken
creator_ip_address: "192.168.1.1",
creator_set_visibility: Visibility::Public,
maybe_last_update_user_token: Some(format!("Last Update User Token {}", i)),
original_download_url: Some(format!("http://example.com/download{}", i)),
original_filename: Some(format!("filename {}.txt", i)),
file_size_bytes: 1024,
file_checksum_sha2: format!("checksum{}", i),
private_bucket_hash: format!("bucket_hash{}", i),
maybe_private_bucket_prefix: Some("_fake".to_string()),
maybe_private_bucket_extension: Some("rvc".to_string()),
cached_user_ratings_total_count: 10,
cached_user_ratings_positive_count: 9,
cached_user_ratings_negative_count: 1,
maybe_cached_user_ratings_ratio: Some(0.9),
version: 1,
mysql_pool: &pool, // replace with actual MySqlPool
};
create_weight(args).await?;
}
// try a query with all the filters
let qb = ListWeightsQueryBuilder::new()
.weights_type(WeightsType::Tacotron2)
.weights_category(WeightsCategory::TextToSpeech)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false);
let result = qb.perform_query_for_page(&pool).await?;
assert_eq!(result.weights.len(), 2);
let qb = ListWeightsQueryBuilder::new()
.weights_type(WeightsType::LoRA)
.weights_category(WeightsCategory::ImageGeneration)
.scope_creator_username(Some("hanashi"))
.include_user_deleted_results(false);
let result = qb.perform_query_for_page(&pool).await?;
assert_eq!(result.weights.len(), 1);
assert_eq!(result.weights[0].weights_category, WeightsCategory::ImageGeneration);
assert_eq!(result.weights[0].weights_type, WeightsType::LoRA);
Ok(())
}
}
@@ -0,0 +1,74 @@
use anyhow::anyhow;
use sqlx::MySqlPool;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use tokens::tokens::model_weights::ModelWeightToken;
pub struct UpdateWeightArgs<'a> {
pub weight_token: &'a ModelWeightToken,
pub title: Option<&'a str>,
pub maybe_thumbnail_token: Option<&'a str>,
pub description_markdown: &'a str,
pub description_rendered_html: &'a str,
pub creator_set_visibility: &'a Visibility,
pub mysql_pool: &'a MySqlPool,
}
pub async fn update_weights(args: UpdateWeightArgs<'_>) -> AnyhowResult<()> {
let mut transaction = args.mysql_pool.begin().await?;
let query_result = sqlx
::query!(
r#"
UPDATE model_weights
SET
title = ?,
description_markdown = ?,
maybe_thumbnail_token = ?,
description_rendered_html = ?,
creator_set_visibility = ?,
version = version + 1
WHERE token = ?
LIMIT 1
"#,
args.title,
args.description_markdown,
args.maybe_thumbnail_token,
args.description_rendered_html,
args.creator_set_visibility.to_str(),
args.weight_token.as_str()
)
.execute(args.mysql_pool).await;
transaction.commit().await?;
match query_result {
Ok(_) => Ok(()),
Err(err) => {
Err(anyhow!("weights update error: {:?}", err))
}
}
}
#[cfg(test)]
mod tests {
// Template
use sqlx::mysql::MySqlPoolOptions;
use tokio;
use config::shared_constants::DEFAULT_MYSQL_CONNECTION_STRING;
use errors::AnyhowResult;
#[tokio::test]
async fn test_update_weights() -> AnyhowResult<()> {
let db_connection_string = DEFAULT_MYSQL_CONNECTION_STRING;
let pool = MySqlPoolOptions::new()
.max_connections(3)
.connect(&db_connection_string)
.await?;
Ok(())
}
}
@@ -6,6 +6,7 @@ use sqlx::MySqlPool;
use errors::AnyhowResult;
use tokens::tokens::tts_models::TtsModelToken;
use tokens::tokens::users::UserToken;
/// table: tts_model_upload_jobs
#[derive(Debug)]
@@ -14,7 +15,7 @@ pub struct TtsUploadJobRecord {
pub token: String,
pub uuid_idempotency_token: String,
pub on_success_result_token: Option<String>,
pub creator_user_token: String,
pub creator_user_token: UserToken,
pub creator_ip_address: String,
pub creator_set_visibility: String, // TODO
pub title: String,
@@ -34,7 +35,23 @@ pub async fn query_tts_upload_job_records(pool: &MySqlPool, num_records: u32)
let job_records = sqlx::query_as!(
TtsUploadJobRecord,
r#"
SELECT *
SELECT
id,
token,
uuid_idempotency_token,
on_success_result_token,
creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,
creator_ip_address,
creator_set_visibility,
title,
tts_model_type,
download_url,
status,
attempt_count,
failure_reason,
created_at,
updated_at,
retry_at
FROM tts_model_upload_jobs
WHERE
(
@@ -229,7 +246,7 @@ SET
"#,
&model_token,
job.title.to_string(),
job.creator_user_token.clone(),
job.creator_user_token.as_str(),
job.creator_ip_address.clone(),
job.creator_ip_address.clone(),
job.download_url.clone(),
@@ -10,6 +10,7 @@ use sqlx::MySqlPool;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use tokens::tokens::users::UserToken;
use crate::column_types::vocoder_type::VocoderType;
use crate::helpers::boolean_converters::{i8_to_bool, nullable_i8_to_bool};
@@ -24,7 +25,7 @@ pub struct TtsResultRecordForResponse {
pub maybe_pretrained_vocoder_used: Option<VocoderType>,
pub maybe_creator_user_token: Option<String>,
pub maybe_creator_user_token: Option<UserToken>,
pub maybe_creator_username: Option<String>,
pub maybe_creator_display_name: Option<String>,
pub maybe_creator_gravatar_hash: Option<String>,
@@ -79,7 +80,7 @@ pub struct TtsResultRecordRaw {
pub maybe_pretrained_vocoder_used: Option<String>,
pub maybe_creator_is_banned: Option<i8>,
pub maybe_creator_user_token: Option<String>,
pub maybe_creator_user_token: Option<UserToken>,
pub maybe_creator_username: Option<String>,
pub maybe_creator_display_name: Option<String>,
pub maybe_creator_gravatar_hash: Option<String>,
@@ -217,7 +218,7 @@ SELECT
tts_results.maybe_pretrained_vocoder_used,
users.token as maybe_creator_user_token,
users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,
users.username as maybe_creator_username,
users.display_name as maybe_creator_display_name,
users.email_gravatar_hash as maybe_creator_gravatar_hash,
@@ -279,7 +280,7 @@ SELECT
tts_results.maybe_pretrained_vocoder_used,
users.token as maybe_creator_user_token,
users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,
users.username as maybe_creator_username,
users.display_name as maybe_creator_display_name,
users.email_gravatar_hash as maybe_creator_gravatar_hash,
@@ -11,6 +11,7 @@ use sqlx::MySqlPool;
use enums::common::visibility::Visibility;
use enums::common::vocoder_type::VocoderType;
use errors::AnyhowResult;
use tokens::tokens::users::UserToken;
use tokens::tokens::vocoder_models::VocoderModelToken;
pub struct Args<'a, P: AsRef<Path>> {
@@ -22,7 +23,7 @@ pub struct Args<'a, P: AsRef<Path>> {
pub original_filename: &'a str,
pub file_size_bytes: u64,
pub creator_user_token: &'a str,
pub creator_user_token: &'a UserToken,
pub creator_ip_address: &'a str,
pub creator_set_visibility: Visibility,
@@ -6,6 +6,7 @@ use sqlx::MySqlPool;
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use tokens::tokens::users::UserToken;
use tokens::tokens::voice_conversion_models::VoiceConversionModelToken;
pub struct InsertVoiceConversionModelArgs<'a, P: AsRef<Path>> {
@@ -17,7 +18,7 @@ pub struct InsertVoiceConversionModelArgs<'a, P: AsRef<Path>> {
pub original_filename: &'a str,
pub file_size_bytes: u64,
pub creator_user_token: &'a str,
pub creator_user_token: &'a UserToken,
pub creator_ip_address: &'a str,
pub creator_set_visibility: Visibility,
@@ -18,7 +18,8 @@ pub struct UpdateVoiceArgs<'a> {
pub async fn update_voice(args: UpdateVoiceArgs<'_>) -> AnyhowResult<()>{
let transaction = args.mysql_pool.begin().await?;
let query_result = sqlx::query!(
let query_result = sqlx
::query!(
r#"
UPDATE zs_voices
SET
@@ -39,11 +40,13 @@ pub async fn update_voice(args: UpdateVoiceArgs<'_>) -> AnyhowResult<()>{
args.voice_token.as_str(),
).execute(args.mysql_pool).await;
// TODO(Kasisnu): This should probably rollback
transaction.commit().await?;
match query_result {
Ok(_) => Ok(()),
Err(err) => Err(anyhow!("zs voice update error: {:?}", err)),
Err(err) =>
{
Err(anyhow!("zs voice update error: {:?}", err))
},
}
}
+1 -1
View File
@@ -26,5 +26,5 @@ serde_derive = "1.0.125"
serde_json = "1.0.108"
# TODO: Get rid of in favor of std::time
time = "0.2.26"
time = "0.3.30"
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
-1
View File
@@ -23,6 +23,5 @@ errors = { path = "../errors" }
sqlx = { version = "0.7.2", features = [ "mysql", "runtime-tokio", "tls-rustls", "chrono" ] }
my-workspace-hack = { version = "0.1", path = "../../../my-workspace-hack" }
[dev-dependencies]
# None yet
+1 -1
View File
@@ -30,7 +30,7 @@ chrono = { version = "=0.4.22", features = ["serde"] }
dotenv = "0.15.0"
hostname = "0.3.1"
log = "0.4.14"
rand = "0.8.3"
rand = "0.8.5"
# MySql Database
# "offline" supports typesafe builds without a live database
@@ -6,7 +6,7 @@ use tempdir::TempDir;
use config::is_bad_download_url::is_bad_download_url;
use container_common::anyhow_result::AnyhowResult;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
use mysql_queries::queries::generic_download::job::mark_generic_download_job_done::mark_generic_download_job_done;
@@ -6,12 +6,12 @@ use anyhow::anyhow;
use log::{info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use enums::by_table::tts_models::tts_model_type::TtsModelType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
@@ -4,14 +4,14 @@ use anyhow::anyhow;
use log::{error, info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use enums::by_table::tts_models::tts_model_type::TtsModelType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::file_size::file_size;
use filesys::filename_concat::filename_concat;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
@@ -6,11 +6,11 @@ use anyhow::anyhow;
use log::{info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use enums::common::vocoder_type::VocoderType;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
@@ -6,11 +6,11 @@ use anyhow::anyhow;
use log::{info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use enums::common::vocoder_type::VocoderType;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
@@ -3,8 +3,8 @@ use std::path::{Path, PathBuf};
use log::{info, warn};
use tempdir::TempDir;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use errors::AnyhowResult;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use mimetypes::mimetype_for_file::get_mimetype_for_file;
#[derive(Debug)]
@@ -5,10 +5,10 @@ use log::info;
use tempdir::TempDir;
use cloud_storage::bucket_client::BucketClient;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use errors::AnyhowResult;
use filesys::create_dir_all_if_missing::create_dir_all_if_missing;
use filesys::file_exists::file_exists;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
#[derive(Clone)]
pub struct PretrainedHubertModel {
@@ -4,15 +4,15 @@ use anyhow::anyhow;
use log::{error, info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_possible_temp_file::safe_delete_possible_temp_file;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use crockford::crockford_entropy_lower;
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::file_size::file_size;
use filesys::safe_delete_possible_temp_file::safe_delete_possible_temp_file;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
use mysql_queries::queries::voice_conversion::models::insert_voice_conversion_model_from_download_job::{insert_voice_conversion_model_from_download_job, InsertVoiceConversionModelArgs};
@@ -4,13 +4,13 @@ use anyhow::anyhow;
use log::{error, info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::file_size::file_size;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
@@ -6,12 +6,12 @@ use anyhow::anyhow;
use log::{info, warn};
use tempdir::TempDir;
use container_common::filesystem::check_file_exists::check_file_exists;
use container_common::filesystem::safe_delete_temp_directory::safe_delete_temp_directory;
use container_common::filesystem::safe_delete_temp_file::safe_delete_temp_file;
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
use enums::common::visibility::Visibility;
use errors::AnyhowResult;
use filesys::check_file_exists::check_file_exists;
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::redis_job_status_logger::RedisJobStatusLogger;
use mysql_queries::queries::generic_download::job::list_available_generic_download_jobs::AvailableDownloadJob;
+1 -1
View File
@@ -33,8 +33,8 @@ use cloud_storage::bucket_path_unifier::BucketPathUnifier;
use config::common_env::CommonEnv;
use config::shared_constants::DEFAULT_MYSQL_CONNECTION_STRING;
use config::shared_constants::DEFAULT_RUST_LOG;
use container_common::filesystem::check_directory_exists::check_directory_exists;
use errors::AnyhowResult;
use filesys::check_directory_exists::check_directory_exists;
use google_drive_common::google_drive_download_command::GoogleDriveDownloadCommand;
use mysql_queries::common_inputs::container_environment_arg::ContainerEnvironmentArg;
use mysql_queries::mediators::badge_granter::BadgeGranter;
+2 -1
View File
@@ -19,9 +19,9 @@ actix_helpers = { path = "../../../lib/actix_helpers" }
bootstrap = { path = "../../../lib/bootstrap" }
buckets = { path = "../../../_types/buckets" }
cloud_storage = { path = "../../../lib/api_clients/cloud_storage" }
collections = { path = "../../../lib/collections" }
concurrency = { path = "../../../lib/concurrency" }
config = { path = "../../../lib/deprecated/config" }
container_common = { path = "../../../lib/deprecated/container_common" }
easyenv = { path = "../../../lib/easyenv" }
enums = { path = "../../../_types/enums" }
errors = { path = "../../../lib/errors" }
@@ -46,6 +46,7 @@ anyhow = "1.0.75"
chrono = { version = "=0.4.22", features = ["serde"] }
dotenv = "0.15.0"
hostname = "0.3.1"
lfu = "0.2.5"
log = "0.4.14"
once_cell = "1.18.0"
subprocess = "0.2.9"
@@ -81,7 +81,7 @@ SO_VITS_SVC_INFERENCE_MAYBE_DEFAULT_CONFIG_PATH="/models/voice_conversion/so-vit
TT2_LEGACY_ROOT_DIRECTORY="/models/tts"
TT2_LEGACY_MAYBE_PYTHON_INTERPRETER="python3.6"
TT2_LEGACY_MAYBE_DOCKER_IMAGE_SHA="9f1945388110"
TT2_LEGACY_MAYBE_DOCKER_IMAGE_SHA="0d29da13e2df"
# ================================= #
# #
@@ -1,16 +1,25 @@
use std::path::Path;
use log::warn;
use container_common::collections::multiple_random_from_vec::multiple_random_from_vec;
use collections::multiple_random_from_vec::multiple_random_from_vec;
use errors::AnyhowResult;
use filesys::safe_delete_temp_file::safe_delete_temp_file;
use jobs_common::semi_persistent_cache_dir::SemiPersistentCacheDir;
pub fn clear_full_filesystem(cache_dir: &SemiPersistentCacheDir) -> AnyhowResult<()> {
warn!("Deleting cached VC models to free up disk space.");
warn!("Deleting cached models to free up disk space.");
let model_dir = cache_dir.voice_conversion_model_directory();
decimate_directory(cache_dir.custom_vocoder_model_directory())?;
decimate_directory(cache_dir.tts_synthesizer_model_directory())?;
decimate_directory(cache_dir.voice_conversion_model_directory())?;
Ok(())
}
fn decimate_directory(path: &Path) -> AnyhowResult<()> {
// TODO: When this is no longer sufficient, delete other types of locally-cached data.
let paths = std::fs::read_dir(model_dir)?
let paths = std::fs::read_dir(path)?
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<_>, std::io::Error>>()?;
@@ -21,8 +30,8 @@ pub fn clear_full_filesystem(cache_dir: &SemiPersistentCacheDir) -> AnyhowResult
for model_to_delete in models_to_delete {
warn!("Deleting cached model file: {:?}", model_to_delete);
let full_model_path = cache_dir.voice_conversion_model_path(model_to_delete);
std::fs::remove_file(full_model_path)?;
let full_model_path = path.join(model_to_delete);
safe_delete_temp_file(full_model_path);
}
Ok(())
@@ -1,15 +1,17 @@
use std::path::PathBuf;
use anyhow::anyhow;
use log::warn;
use log::{info, warn};
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
use enums::by_table::tts_models::tts_model_type::TtsModelType;
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
use errors::AnyhowResult;
use filesys::file_exists::file_exists;
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
use mysql_queries::queries::tts::tts_models::get_tts_model_for_inference_improved::{get_tts_model_for_inference_improved, TtsModelForInferenceRecord};
use mysql_queries::queries::tts::tts_models::get_tts_model_for_inference_improved::{get_tts_model_for_inference_improved, TtsModelForInferenceError, TtsModelForInferenceRecord};
use mysql_queries::queries::voice_conversion::inference::get_voice_conversion_model_for_inference::{get_voice_conversion_model_for_inference, VoiceConversionModelForInference};
use crate::job::job_loop::process_single_job_error::ProcessSingleJobError;
use crate::job_dependencies::JobDependencies;
pub struct DependencyStatus {
@@ -30,13 +32,37 @@ pub enum MaybeInferenceModel {
VcModel(VoiceConversionModelForInference)
}
pub async fn determine_dependency_status(job_dependencies: &JobDependencies, job: &AvailableInferenceJob) -> AnyhowResult<DependencyStatus> {
pub async fn determine_dependency_status(job_dependencies: &JobDependencies, job: &AvailableInferenceJob) -> Result<DependencyStatus, ProcessSingleJobError> {
let maybe_model = get_model_record_from_cacheable_query(job_dependencies, job).await?;
let maybe_token_and_path = get_model_token_and_path(job_dependencies, &maybe_model);
let models_already_on_filesystem = match maybe_token_and_path.maybe_filesystem_path {
None => true,
Some(path) => {
info!("Checking if dynamic model dependency already on filesystem: {:?}", path);
let exists = file_exists(&path);
info!("Checking if dynamic model dependency already on filesystem: {:?} (exists = {})", path, exists);
exists
},
};
Ok(DependencyStatus {
maybe_inference_model: maybe_model,
maybe_model_token: maybe_token_and_path.maybe_model_token,
models_already_on_filesystem,
})
}
struct MaybeTokenAndPath {
maybe_model_token: Option<String>,
maybe_filesystem_path: Option<PathBuf>,
}
fn get_model_token_and_path(job_dependencies: &JobDependencies, maybe_model: &MaybeInferenceModel) -> MaybeTokenAndPath {
let mut maybe_model_token = None;
// TODO: Also check other paths (vocoders, etc.)
// TODO(bt,2023-05-01): Also check other paths (user-supplied vocoders, etc.)
let maybe_filesystem_path = match maybe_model {
MaybeInferenceModel::TtsModel(ref model) => {
match model.tts_model_type {
@@ -74,22 +100,22 @@ pub async fn determine_dependency_status(job_dependencies: &JobDependencies, job
}
};
let models_already_on_filesystem = match maybe_filesystem_path {
None => true,
Some(path) => file_exists(path),
};
Ok(DependencyStatus {
maybe_inference_model: maybe_model,
MaybeTokenAndPath {
maybe_model_token,
models_already_on_filesystem,
})
maybe_filesystem_path,
}
}
pub async fn get_model_record_from_cacheable_query(job_dependencies: &JobDependencies, job: &AvailableInferenceJob) -> AnyhowResult<MaybeInferenceModel> {
async fn get_model_record_from_cacheable_query(job_dependencies: &JobDependencies, job: &AvailableInferenceJob) -> Result<MaybeInferenceModel, ProcessSingleJobError> {
let model = match (job.inference_category, job.maybe_model_token.as_deref()) {
(InferenceCategory::TextToSpeech, Some(token)) => {
let maybe_model = job_dependencies.job.info.caches.tts_model_record_cache.copy_without_bump_if_unexpired(token.to_string())?;
let maybe_model = job_dependencies
.job
.info
.caches
.tts_model_record_cache
.copy_without_bump_if_unexpired(token.to_string())
.map_err(|err| ProcessSingleJobError::from_anyhow_error(err))?;
match maybe_model {
Some(model) => MaybeInferenceModel::TtsModel(model),
@@ -97,22 +123,36 @@ pub async fn get_model_record_from_cacheable_query(job_dependencies: &JobDepende
let maybe_tts_model = get_tts_model_for_inference_improved(
&job_dependencies.db.mysql_pool, token)
.await
.map_err(|err| anyhow!("database error: {:?}", err))?;
.map_err(|err| match err {
TtsModelForInferenceError::ModelDeleted => ProcessSingleJobError::ModelDeleted,
_ => ProcessSingleJobError::Other(anyhow!("database error: {:?}", err))
})?;
match maybe_tts_model {
None => MaybeInferenceModel::None,
Some(model) => {
let token = token.to_string();
let _r = job_dependencies.job.info.caches.tts_model_record_cache.store_copy(&token, &model)?;
let _r = job_dependencies
.job
.info
.caches
.tts_model_record_cache
.store_copy(&token, &model)
.map_err(|err| ProcessSingleJobError::from_anyhow_error(err))?;
MaybeInferenceModel::TtsModel(model)
},
None => MaybeInferenceModel::None,
}
}
}
}
(InferenceCategory::VoiceConversion, Some(token)) => {
let maybe_model = job_dependencies.job.info.caches.vc_model_record_cache.copy_without_bump_if_unexpired(token.to_string())?;
let maybe_model = job_dependencies
.job
.info
.caches
.vc_model_record_cache
.copy_without_bump_if_unexpired(token.to_string())
.map_err(|err| ProcessSingleJobError::from_anyhow_error(err))?;
match maybe_model {
Some(model) => MaybeInferenceModel::VcModel(model),
@@ -120,16 +160,22 @@ pub async fn get_model_record_from_cacheable_query(job_dependencies: &JobDepende
let maybe_vc_model = get_voice_conversion_model_for_inference(
&job_dependencies.db.mysql_pool, token)
.await
.map_err(|err| anyhow!("database error: {:?}", err))?;
.map_err(|err| ProcessSingleJobError::Other(anyhow!("database error: {:?}", err)))?;
match maybe_vc_model {
None => MaybeInferenceModel::None,
Some(model) => {
let token = token.to_string();
let _r = job_dependencies.job.info.caches.vc_model_record_cache.store_copy(&token, &model)?;
let _r = job_dependencies
.job
.info
.caches
.vc_model_record_cache
.store_copy(&token, &model)
.map_err(|err| ProcessSingleJobError::from_anyhow_error(err))?;
MaybeInferenceModel::VcModel(model)
},
None => MaybeInferenceModel::None,
}
}
}

Some files were not shown because too many files have changed in this diff Show More