refactor: make registry postgres-first
This commit is contained in:
@@ -15,6 +15,22 @@ jobs:
|
|||||||
rust:
|
rust:
|
||||||
name: Rust Checks
|
name: Rust Checks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
env:
|
||||||
|
POSTGRES_DB: rmcp_test
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U postgres -d rmcp_test"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
env:
|
||||||
|
TEST_DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/rmcp_test
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
Generated
+308
-66
@@ -122,6 +122,12 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
@@ -210,6 +216,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -244,6 +251,17 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "etcetera"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"home",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener"
|
name = "event-listener"
|
||||||
version = "5.4.1"
|
version = "5.4.1"
|
||||||
@@ -261,17 +279,6 @@ version = "0.1.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flume"
|
|
||||||
version = "0.11.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
|
||||||
"spin",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -303,17 +310,6 @@ version = "0.3.32"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-executor"
|
|
||||||
version = "0.3.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-task",
|
|
||||||
"futures-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-intrusive"
|
name = "futures-intrusive"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -417,6 +413,33 @@ version = "0.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hkdf"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
|
||||||
|
dependencies = [
|
||||||
|
"hmac",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "home"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -629,14 +652,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libredox"
|
||||||
version = "0.30.1"
|
version = "0.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
|
checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"bitflags",
|
||||||
"pkg-config",
|
"libc",
|
||||||
"vcpkg",
|
"plain",
|
||||||
|
"redox_syscall 0.7.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -788,6 +812,16 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "md-5"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
@@ -859,7 +893,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.5.18",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
@@ -883,10 +917,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "plain"
|
||||||
version = "0.3.32"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "potential_utf"
|
name = "potential_utf"
|
||||||
@@ -897,6 +931,15 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@@ -915,6 +958,36 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.18"
|
version = "0.5.18"
|
||||||
@@ -924,6 +997,15 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@@ -1117,6 +1199,9 @@ name = "smallvec"
|
|||||||
version = "1.15.1"
|
version = "1.15.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@@ -1128,15 +1213,6 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spin"
|
|
||||||
version = "0.9.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx"
|
name = "sqlx"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
@@ -1145,7 +1221,7 @@ checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-macros",
|
"sqlx-macros",
|
||||||
"sqlx-sqlite",
|
"sqlx-postgres",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1173,6 +1249,7 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rustls",
|
"rustls",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -1213,34 +1290,47 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-sqlite",
|
"sqlx-postgres",
|
||||||
"syn",
|
"syn",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-sqlite"
|
name = "sqlx-postgres"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
|
checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"flume",
|
"base64",
|
||||||
|
"bitflags",
|
||||||
|
"byteorder",
|
||||||
|
"crc",
|
||||||
|
"dotenvy",
|
||||||
|
"etcetera",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-executor",
|
|
||||||
"futures-intrusive",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"libsqlite3-sys",
|
"hex",
|
||||||
|
"hkdf",
|
||||||
|
"hmac",
|
||||||
|
"home",
|
||||||
|
"itoa",
|
||||||
"log",
|
"log",
|
||||||
"percent-encoding",
|
"md-5",
|
||||||
|
"memchr",
|
||||||
|
"once_cell",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_urlencoded",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
|
"smallvec",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
|
"stringprep",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1249,6 +1339,17 @@ version = "1.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stringprep"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-normalization",
|
||||||
|
"unicode-properties",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
@@ -1322,6 +1423,21 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.50.0"
|
version = "1.50.0"
|
||||||
@@ -1455,12 +1571,33 @@ version = "1.19.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-normalization"
|
||||||
|
version = "0.1.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-properties"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unsafe-libyaml"
|
name = "unsafe-libyaml"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@@ -1497,12 +1634,6 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vcpkg"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@@ -1515,6 +1646,12 @@ version = "0.11.1+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasite"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.26.11"
|
version = "0.26.11"
|
||||||
@@ -1533,19 +1670,47 @@ dependencies = [
|
|||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "whoami"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
|
||||||
|
dependencies = [
|
||||||
|
"libredox",
|
||||||
|
"wasite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1557,34 +1722,67 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
"windows_x86_64_msvc",
|
"windows_x86_64_msvc 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1597,24 +1795,48 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1650,6 +1872,26 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.47"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.47"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerofrom"
|
name = "zerofrom"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ axum = "0.8"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio-rustls", "sqlite"] }
|
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio-rustls", "postgres"] }
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
mod error;
|
mod error;
|
||||||
mod migrations;
|
mod migrations;
|
||||||
mod model;
|
mod model;
|
||||||
mod sqlite;
|
mod postgres;
|
||||||
|
|
||||||
pub use error::RegistryError;
|
pub use error::RegistryError;
|
||||||
pub use model::{
|
pub use model::{
|
||||||
@@ -11,4 +11,4 @@ pub use model::{
|
|||||||
SaveSampleMetadataRequest, YamlImportJob, YamlImportJobCompletion, YamlImportJobId,
|
SaveSampleMetadataRequest, YamlImportJob, YamlImportJobCompletion, YamlImportJobId,
|
||||||
YamlImportJobStatus,
|
YamlImportJobStatus,
|
||||||
};
|
};
|
||||||
pub use sqlite::SqliteRegistry;
|
pub use postgres::PostgresRegistry;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use sqlx::{SqlitePool, query};
|
use sqlx::{PgPool, query};
|
||||||
|
|
||||||
pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
pub async fn apply_postgres(pool: &PgPool) -> Result<(), sqlx::Error> {
|
||||||
query(
|
query(
|
||||||
"create table if not exists operations (
|
"create table if not exists operations (
|
||||||
id text primary key,
|
id text primary key,
|
||||||
@@ -10,9 +10,9 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
status text not null,
|
status text not null,
|
||||||
current_draft_version integer not null default 1,
|
current_draft_version integer not null default 1,
|
||||||
latest_published_version integer null,
|
latest_published_version integer null,
|
||||||
created_at text not null,
|
created_at timestamptz not null,
|
||||||
updated_at text not null,
|
updated_at timestamptz not null,
|
||||||
published_at text null
|
published_at timestamptz null
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
@@ -20,24 +20,23 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
|
|
||||||
query(
|
query(
|
||||||
"create table if not exists operation_versions (
|
"create table if not exists operation_versions (
|
||||||
operation_id text not null,
|
operation_id text not null references operations(id) on delete cascade,
|
||||||
version integer not null,
|
version integer not null,
|
||||||
status text not null,
|
status text not null,
|
||||||
target_json text not null,
|
target_json jsonb not null,
|
||||||
input_schema_json text not null,
|
input_schema_json jsonb not null,
|
||||||
output_schema_json text not null,
|
output_schema_json jsonb not null,
|
||||||
input_mapping_json text not null,
|
input_mapping_json jsonb not null,
|
||||||
output_mapping_json text not null,
|
output_mapping_json jsonb not null,
|
||||||
execution_config_json text not null,
|
execution_config_json jsonb not null,
|
||||||
tool_description_json text not null,
|
tool_description_json jsonb not null,
|
||||||
samples_json text null,
|
samples_json jsonb null,
|
||||||
generated_draft_json text null,
|
generated_draft_json jsonb null,
|
||||||
config_export_json text null,
|
config_export_json jsonb null,
|
||||||
change_note text null,
|
change_note text null,
|
||||||
created_at text not null,
|
created_at timestamptz not null,
|
||||||
created_by text null,
|
created_by text null,
|
||||||
primary key (operation_id, version),
|
primary key (operation_id, version)
|
||||||
foreign key (operation_id) references operations(id) on delete cascade
|
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
@@ -45,11 +44,10 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
|
|
||||||
query(
|
query(
|
||||||
"create table if not exists published_operations (
|
"create table if not exists published_operations (
|
||||||
operation_id text primary key,
|
operation_id text primary key references operations(id) on delete cascade,
|
||||||
version integer not null,
|
version integer not null,
|
||||||
published_at text not null,
|
published_at timestamptz not null,
|
||||||
published_by text null,
|
published_by text null,
|
||||||
foreign key (operation_id) references operations(id) on delete cascade,
|
|
||||||
foreign key (operation_id, version) references operation_versions(operation_id, version) on delete cascade
|
foreign key (operation_id, version) references operation_versions(operation_id, version) on delete cascade
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
@@ -59,14 +57,13 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
query(
|
query(
|
||||||
"create table if not exists operation_samples (
|
"create table if not exists operation_samples (
|
||||||
id text primary key,
|
id text primary key,
|
||||||
operation_id text not null,
|
operation_id text not null references operations(id) on delete cascade,
|
||||||
version integer not null,
|
version integer not null,
|
||||||
sample_kind text not null,
|
sample_kind text not null,
|
||||||
storage_ref text not null,
|
storage_ref text not null,
|
||||||
content_type text not null,
|
content_type text not null,
|
||||||
file_name text null,
|
file_name text null,
|
||||||
created_at text not null,
|
created_at timestamptz not null,
|
||||||
foreign key (operation_id) references operations(id) on delete cascade,
|
|
||||||
foreign key (operation_id, version) references operation_versions(operation_id, version) on delete cascade
|
foreign key (operation_id, version) references operation_versions(operation_id, version) on delete cascade
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
@@ -76,14 +73,13 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
query(
|
query(
|
||||||
"create table if not exists descriptors (
|
"create table if not exists descriptors (
|
||||||
id text primary key,
|
id text primary key,
|
||||||
operation_id text null,
|
operation_id text null references operations(id) on delete cascade,
|
||||||
version integer null,
|
version integer null,
|
||||||
descriptor_kind text not null,
|
descriptor_kind text not null,
|
||||||
storage_ref text not null,
|
storage_ref text not null,
|
||||||
source_name text null,
|
source_name text null,
|
||||||
package_index_json text null,
|
package_index_json jsonb null,
|
||||||
created_at text not null,
|
created_at timestamptz not null,
|
||||||
foreign key (operation_id) references operations(id) on delete cascade,
|
|
||||||
foreign key (operation_id, version) references operation_versions(operation_id, version) on delete cascade
|
foreign key (operation_id, version) references operation_versions(operation_id, version) on delete cascade
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
@@ -95,9 +91,9 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
id text primary key,
|
id text primary key,
|
||||||
name text not null unique,
|
name text not null unique,
|
||||||
kind text not null,
|
kind text not null,
|
||||||
config_json text not null,
|
config_json jsonb not null,
|
||||||
created_at text not null,
|
created_at timestamptz not null,
|
||||||
updated_at text not null
|
updated_at timestamptz not null
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
@@ -106,17 +102,15 @@ pub async fn apply_sqlite(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
|||||||
query(
|
query(
|
||||||
"create table if not exists yaml_import_jobs (
|
"create table if not exists yaml_import_jobs (
|
||||||
id text primary key,
|
id text primary key,
|
||||||
source_sample_id text null,
|
source_sample_id text null references operation_samples(id) on delete set null,
|
||||||
status text not null,
|
status text not null,
|
||||||
format_version text not null,
|
format_version text not null,
|
||||||
mode text not null,
|
mode text not null,
|
||||||
result_operation_id text null,
|
result_operation_id text null references operations(id) on delete set null,
|
||||||
result_version integer null,
|
result_version integer null,
|
||||||
error_text text null,
|
error_text text null,
|
||||||
created_at text not null,
|
created_at timestamptz not null,
|
||||||
finished_at text null,
|
finished_at timestamptz null
|
||||||
foreign key (source_sample_id) references operation_samples(id) on delete set null,
|
|
||||||
foreign key (result_operation_id) references operations(id) on delete set null
|
|
||||||
)",
|
)",
|
||||||
)
|
)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
use mcpaas_core::{AuthProfile, OperationId, OperationStatus};
|
use mcpaas_core::{AuthProfile, OperationId, OperationStatus};
|
||||||
use serde::{Serialize, de::DeserializeOwned};
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use sqlx::{Row, SqlitePool, sqlite::SqlitePoolOptions};
|
use sqlx::{
|
||||||
|
PgPool, Postgres, Row, Transaction,
|
||||||
|
postgres::{PgPoolOptions, PgRow},
|
||||||
|
types::Json,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::RegistryError,
|
error::RegistryError,
|
||||||
@@ -16,35 +20,44 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SqliteRegistry {
|
pub struct PostgresRegistry {
|
||||||
pool: SqlitePool,
|
pool: PgPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SqliteRegistry {
|
impl PostgresRegistry {
|
||||||
pub async fn connect(database_url: &str) -> Result<Self, RegistryError> {
|
pub async fn connect(database_url: &str) -> Result<Self, RegistryError> {
|
||||||
let pool = SqlitePoolOptions::new()
|
Self::connect_in_schema(database_url, None).await
|
||||||
.max_connections(1)
|
|
||||||
.connect(database_url)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
sqlx::query("pragma foreign_keys = on")
|
|
||||||
.execute(&pool)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let registry = Self { pool };
|
|
||||||
registry.migrate().await?;
|
|
||||||
Ok(registry)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pool(&self) -> &SqlitePool {
|
pub fn pool(&self) -> &PgPool {
|
||||||
&self.pool
|
&self.pool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn migrate(&self) -> Result<(), RegistryError> {
|
pub async fn migrate(&self) -> Result<(), RegistryError> {
|
||||||
migrations::apply_sqlite(&self.pool).await?;
|
migrations::apply_postgres(&self.pool).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn connect_in_schema(
|
||||||
|
database_url: &str,
|
||||||
|
schema: Option<&str>,
|
||||||
|
) -> Result<Self, RegistryError> {
|
||||||
|
let pool = PgPoolOptions::new()
|
||||||
|
.max_connections(1)
|
||||||
|
.connect(database_url)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(schema) = schema {
|
||||||
|
sqlx::query(&format!("set search_path to {schema}"))
|
||||||
|
.execute(&pool)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let registry = Self { pool };
|
||||||
|
registry.migrate().await?;
|
||||||
|
Ok(registry)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_operation(
|
pub async fn create_operation(
|
||||||
&self,
|
&self,
|
||||||
snapshot: &RegistryOperation,
|
snapshot: &RegistryOperation,
|
||||||
@@ -77,7 +90,12 @@ impl SqliteRegistry {
|
|||||||
created_at,
|
created_at,
|
||||||
updated_at,
|
updated_at,
|
||||||
published_at
|
published_at
|
||||||
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
) values (
|
||||||
|
$1, $2, $3, $4, $5, $6, $7,
|
||||||
|
$8::timestamptz,
|
||||||
|
$9::timestamptz,
|
||||||
|
$10::timestamptz
|
||||||
|
)",
|
||||||
)
|
)
|
||||||
.bind(snapshot.id.as_str())
|
.bind(snapshot.id.as_str())
|
||||||
.bind(&snapshot.name)
|
.bind(&snapshot.name)
|
||||||
@@ -136,10 +154,10 @@ impl SqliteRegistry {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"update operations
|
"update operations
|
||||||
set status = ?,
|
set status = $1,
|
||||||
current_draft_version = ?,
|
current_draft_version = $2,
|
||||||
updated_at = ?
|
updated_at = $3::timestamptz
|
||||||
where id = ?",
|
where id = $4",
|
||||||
)
|
)
|
||||||
.bind(serialize_enum_text(&request.snapshot.status, "status")?)
|
.bind(serialize_enum_text(&request.snapshot.status, "status")?)
|
||||||
.bind(to_db_version(request.snapshot.version))
|
.bind(to_db_version(request.snapshot.version))
|
||||||
@@ -162,9 +180,9 @@ impl SqliteRegistry {
|
|||||||
status,
|
status,
|
||||||
current_draft_version,
|
current_draft_version,
|
||||||
latest_published_version,
|
latest_published_version,
|
||||||
created_at,
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
updated_at,
|
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at,
|
||||||
published_at
|
to_char(published_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as published_at
|
||||||
from operations
|
from operations
|
||||||
order by name asc",
|
order by name asc",
|
||||||
)
|
)
|
||||||
@@ -187,11 +205,11 @@ impl SqliteRegistry {
|
|||||||
status,
|
status,
|
||||||
current_draft_version,
|
current_draft_version,
|
||||||
latest_published_version,
|
latest_published_version,
|
||||||
created_at,
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
updated_at,
|
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at,
|
||||||
published_at
|
to_char(published_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as published_at
|
||||||
from operations
|
from operations
|
||||||
where id = ?",
|
where id = $1",
|
||||||
)
|
)
|
||||||
.bind(operation_id.as_str())
|
.bind(operation_id.as_str())
|
||||||
.fetch_optional(&self.pool)
|
.fetch_optional(&self.pool)
|
||||||
@@ -211,9 +229,9 @@ impl SqliteRegistry {
|
|||||||
o.name,
|
o.name,
|
||||||
o.display_name,
|
o.display_name,
|
||||||
o.protocol,
|
o.protocol,
|
||||||
o.created_at as operation_created_at,
|
to_char(o.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_created_at,
|
||||||
o.updated_at as operation_updated_at,
|
to_char(o.updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_updated_at,
|
||||||
o.published_at as operation_published_at,
|
to_char(o.published_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_published_at,
|
||||||
ov.version,
|
ov.version,
|
||||||
ov.status,
|
ov.status,
|
||||||
ov.target_json,
|
ov.target_json,
|
||||||
@@ -227,11 +245,11 @@ impl SqliteRegistry {
|
|||||||
ov.generated_draft_json,
|
ov.generated_draft_json,
|
||||||
ov.config_export_json,
|
ov.config_export_json,
|
||||||
ov.change_note,
|
ov.change_note,
|
||||||
ov.created_at,
|
to_char(ov.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
ov.created_by
|
ov.created_by
|
||||||
from operation_versions ov
|
from operation_versions ov
|
||||||
join operations o on o.id = ov.operation_id
|
join operations o on o.id = ov.operation_id
|
||||||
where ov.operation_id = ? and ov.version = ?",
|
where ov.operation_id = $1 and ov.version = $2",
|
||||||
)
|
)
|
||||||
.bind(operation_id.as_str())
|
.bind(operation_id.as_str())
|
||||||
.bind(to_db_version(version))
|
.bind(to_db_version(version))
|
||||||
@@ -251,9 +269,9 @@ impl SqliteRegistry {
|
|||||||
o.name,
|
o.name,
|
||||||
o.display_name,
|
o.display_name,
|
||||||
o.protocol,
|
o.protocol,
|
||||||
o.created_at as operation_created_at,
|
to_char(o.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_created_at,
|
||||||
o.updated_at as operation_updated_at,
|
to_char(o.updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_updated_at,
|
||||||
o.published_at as operation_published_at,
|
to_char(o.published_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_published_at,
|
||||||
ov.version,
|
ov.version,
|
||||||
ov.status,
|
ov.status,
|
||||||
ov.target_json,
|
ov.target_json,
|
||||||
@@ -267,11 +285,11 @@ impl SqliteRegistry {
|
|||||||
ov.generated_draft_json,
|
ov.generated_draft_json,
|
||||||
ov.config_export_json,
|
ov.config_export_json,
|
||||||
ov.change_note,
|
ov.change_note,
|
||||||
ov.created_at,
|
to_char(ov.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
ov.created_by
|
ov.created_by
|
||||||
from operation_versions ov
|
from operation_versions ov
|
||||||
join operations o on o.id = ov.operation_id
|
join operations o on o.id = ov.operation_id
|
||||||
where ov.operation_id = ?
|
where ov.operation_id = $1
|
||||||
order by ov.version asc",
|
order by ov.version asc",
|
||||||
)
|
)
|
||||||
.bind(operation_id.as_str())
|
.bind(operation_id.as_str())
|
||||||
@@ -304,7 +322,7 @@ impl SqliteRegistry {
|
|||||||
version,
|
version,
|
||||||
published_at,
|
published_at,
|
||||||
published_by
|
published_by
|
||||||
) values (?, ?, ?, ?)
|
) values ($1, $2, $3::timestamptz, $4)
|
||||||
on conflict(operation_id) do update set
|
on conflict(operation_id) do update set
|
||||||
version = excluded.version,
|
version = excluded.version,
|
||||||
published_at = excluded.published_at,
|
published_at = excluded.published_at,
|
||||||
@@ -319,8 +337,8 @@ impl SqliteRegistry {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"update operation_versions
|
"update operation_versions
|
||||||
set status = ?
|
set status = $1
|
||||||
where operation_id = ? and version = ?",
|
where operation_id = $2 and version = $3",
|
||||||
)
|
)
|
||||||
.bind(serialize_enum_text(&OperationStatus::Published, "status")?)
|
.bind(serialize_enum_text(&OperationStatus::Published, "status")?)
|
||||||
.bind(request.operation_id.as_str())
|
.bind(request.operation_id.as_str())
|
||||||
@@ -330,11 +348,11 @@ impl SqliteRegistry {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"update operations
|
"update operations
|
||||||
set status = ?,
|
set status = $1,
|
||||||
latest_published_version = ?,
|
latest_published_version = $2,
|
||||||
published_at = ?,
|
published_at = $3::timestamptz,
|
||||||
updated_at = ?
|
updated_at = $4::timestamptz
|
||||||
where id = ?",
|
where id = $5",
|
||||||
)
|
)
|
||||||
.bind(serialize_enum_text(&OperationStatus::Published, "status")?)
|
.bind(serialize_enum_text(&OperationStatus::Published, "status")?)
|
||||||
.bind(to_db_version(request.version))
|
.bind(to_db_version(request.version))
|
||||||
@@ -358,9 +376,9 @@ impl SqliteRegistry {
|
|||||||
o.name,
|
o.name,
|
||||||
o.display_name,
|
o.display_name,
|
||||||
o.protocol,
|
o.protocol,
|
||||||
o.created_at as operation_created_at,
|
to_char(o.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_created_at,
|
||||||
o.updated_at as operation_updated_at,
|
to_char(o.updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_updated_at,
|
||||||
o.published_at as operation_published_at,
|
to_char(o.published_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_published_at,
|
||||||
ov.version,
|
ov.version,
|
||||||
ov.status,
|
ov.status,
|
||||||
ov.target_json,
|
ov.target_json,
|
||||||
@@ -374,13 +392,13 @@ impl SqliteRegistry {
|
|||||||
ov.generated_draft_json,
|
ov.generated_draft_json,
|
||||||
ov.config_export_json,
|
ov.config_export_json,
|
||||||
ov.change_note,
|
ov.change_note,
|
||||||
ov.created_at,
|
to_char(ov.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
ov.created_by
|
ov.created_by
|
||||||
from published_operations po
|
from published_operations po
|
||||||
join operation_versions ov
|
join operation_versions ov
|
||||||
on ov.operation_id = po.operation_id and ov.version = po.version
|
on ov.operation_id = po.operation_id and ov.version = po.version
|
||||||
join operations o on o.id = po.operation_id
|
join operations o on o.id = po.operation_id
|
||||||
where po.operation_id = ?",
|
where po.operation_id = $1",
|
||||||
)
|
)
|
||||||
.bind(operation_id.as_str())
|
.bind(operation_id.as_str())
|
||||||
.fetch_optional(&self.pool)
|
.fetch_optional(&self.pool)
|
||||||
@@ -398,9 +416,9 @@ impl SqliteRegistry {
|
|||||||
o.name,
|
o.name,
|
||||||
o.display_name,
|
o.display_name,
|
||||||
o.protocol,
|
o.protocol,
|
||||||
o.created_at as operation_created_at,
|
to_char(o.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_created_at,
|
||||||
o.updated_at as operation_updated_at,
|
to_char(o.updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_updated_at,
|
||||||
o.published_at as operation_published_at,
|
to_char(o.published_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as operation_published_at,
|
||||||
ov.version,
|
ov.version,
|
||||||
ov.status,
|
ov.status,
|
||||||
ov.target_json,
|
ov.target_json,
|
||||||
@@ -414,7 +432,7 @@ impl SqliteRegistry {
|
|||||||
ov.generated_draft_json,
|
ov.generated_draft_json,
|
||||||
ov.config_export_json,
|
ov.config_export_json,
|
||||||
ov.change_note,
|
ov.change_note,
|
||||||
ov.created_at,
|
to_char(ov.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
ov.created_by
|
ov.created_by
|
||||||
from published_operations po
|
from published_operations po
|
||||||
join operation_versions ov
|
join operation_versions ov
|
||||||
@@ -442,7 +460,7 @@ impl SqliteRegistry {
|
|||||||
config_json,
|
config_json,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
) values (?, ?, ?, ?, ?, ?)
|
) values ($1, $2, $3, $4, $5::timestamptz, $6::timestamptz)
|
||||||
on conflict(id) do update set
|
on conflict(id) do update set
|
||||||
name = excluded.name,
|
name = excluded.name,
|
||||||
kind = excluded.kind,
|
kind = excluded.kind,
|
||||||
@@ -452,7 +470,7 @@ impl SqliteRegistry {
|
|||||||
.bind(request.profile.id.as_str())
|
.bind(request.profile.id.as_str())
|
||||||
.bind(&request.profile.name)
|
.bind(&request.profile.name)
|
||||||
.bind(serialize_enum_text(&request.profile.kind, "kind")?)
|
.bind(serialize_enum_text(&request.profile.kind, "kind")?)
|
||||||
.bind(serialize_json(&request.profile.config)?)
|
.bind(Json(serialize_json_value(&request.profile.config)?))
|
||||||
.bind(&request.profile.created_at)
|
.bind(&request.profile.created_at)
|
||||||
.bind(&request.profile.updated_at)
|
.bind(&request.profile.updated_at)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
@@ -466,9 +484,15 @@ impl SqliteRegistry {
|
|||||||
auth_profile_id: &mcpaas_core::AuthProfileId,
|
auth_profile_id: &mcpaas_core::AuthProfileId,
|
||||||
) -> Result<Option<AuthProfile>, RegistryError> {
|
) -> Result<Option<AuthProfile>, RegistryError> {
|
||||||
let row = sqlx::query(
|
let row = sqlx::query(
|
||||||
"select id, name, kind, config_json, created_at, updated_at
|
"select
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
kind,
|
||||||
|
config_json,
|
||||||
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
|
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at
|
||||||
from auth_profiles
|
from auth_profiles
|
||||||
where id = ?",
|
where id = $1",
|
||||||
)
|
)
|
||||||
.bind(auth_profile_id.as_str())
|
.bind(auth_profile_id.as_str())
|
||||||
.fetch_optional(&self.pool)
|
.fetch_optional(&self.pool)
|
||||||
@@ -479,7 +503,13 @@ impl SqliteRegistry {
|
|||||||
|
|
||||||
pub async fn list_auth_profiles(&self) -> Result<Vec<AuthProfile>, RegistryError> {
|
pub async fn list_auth_profiles(&self) -> Result<Vec<AuthProfile>, RegistryError> {
|
||||||
let rows = sqlx::query(
|
let rows = sqlx::query(
|
||||||
"select id, name, kind, config_json, created_at, updated_at
|
"select
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
kind,
|
||||||
|
config_json,
|
||||||
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
|
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at
|
||||||
from auth_profiles
|
from auth_profiles
|
||||||
order by name asc",
|
order by name asc",
|
||||||
)
|
)
|
||||||
@@ -503,7 +533,7 @@ impl SqliteRegistry {
|
|||||||
content_type,
|
content_type,
|
||||||
file_name,
|
file_name,
|
||||||
created_at
|
created_at
|
||||||
) values (?, ?, ?, ?, ?, ?, ?, ?)
|
) values ($1, $2, $3, $4, $5, $6, $7, $8::timestamptz)
|
||||||
on conflict(id) do update set
|
on conflict(id) do update set
|
||||||
operation_id = excluded.operation_id,
|
operation_id = excluded.operation_id,
|
||||||
version = excluded.version,
|
version = excluded.version,
|
||||||
@@ -544,9 +574,9 @@ impl SqliteRegistry {
|
|||||||
storage_ref,
|
storage_ref,
|
||||||
content_type,
|
content_type,
|
||||||
file_name,
|
file_name,
|
||||||
created_at
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at
|
||||||
from operation_samples
|
from operation_samples
|
||||||
where operation_id = ? and version = ?
|
where operation_id = $1 and version = $2
|
||||||
order by created_at asc",
|
order by created_at asc",
|
||||||
)
|
)
|
||||||
.bind(operation_id.as_str())
|
.bind(operation_id.as_str())
|
||||||
@@ -571,7 +601,7 @@ impl SqliteRegistry {
|
|||||||
source_name,
|
source_name,
|
||||||
package_index_json,
|
package_index_json,
|
||||||
created_at
|
created_at
|
||||||
) values (?, ?, ?, ?, ?, ?, ?, ?)
|
) values ($1, $2, $3, $4, $5, $6, $7, $8::timestamptz)
|
||||||
on conflict(id) do update set
|
on conflict(id) do update set
|
||||||
operation_id = excluded.operation_id,
|
operation_id = excluded.operation_id,
|
||||||
version = excluded.version,
|
version = excluded.version,
|
||||||
@@ -596,7 +626,7 @@ impl SqliteRegistry {
|
|||||||
)?)
|
)?)
|
||||||
.bind(&request.descriptor.storage_ref)
|
.bind(&request.descriptor.storage_ref)
|
||||||
.bind(request.descriptor.source_name.as_deref())
|
.bind(request.descriptor.source_name.as_deref())
|
||||||
.bind(serialize_option_json(&request.descriptor.package_index)?)
|
.bind(serialize_option_json_value(&request.descriptor.package_index)?.map(Json))
|
||||||
.bind(&request.descriptor.created_at)
|
.bind(&request.descriptor.created_at)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -618,9 +648,9 @@ impl SqliteRegistry {
|
|||||||
storage_ref,
|
storage_ref,
|
||||||
source_name,
|
source_name,
|
||||||
package_index_json,
|
package_index_json,
|
||||||
created_at
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at
|
||||||
from descriptors
|
from descriptors
|
||||||
where operation_id = ? and version = ?
|
where operation_id = $1 and version = $2
|
||||||
order by created_at asc",
|
order by created_at asc",
|
||||||
)
|
)
|
||||||
.bind(operation_id.as_str())
|
.bind(operation_id.as_str())
|
||||||
@@ -647,7 +677,7 @@ impl SqliteRegistry {
|
|||||||
error_text,
|
error_text,
|
||||||
created_at,
|
created_at,
|
||||||
finished_at
|
finished_at
|
||||||
) values (?, ?, ?, ?, ?, null, null, null, ?, null)",
|
) values ($1, $2, $3, $4, $5, null, null, null, $6::timestamptz, null)",
|
||||||
)
|
)
|
||||||
.bind(request.id.as_str())
|
.bind(request.id.as_str())
|
||||||
.bind(request.source_sample_id.map(|value| value.as_str()))
|
.bind(request.source_sample_id.map(|value| value.as_str()))
|
||||||
@@ -671,12 +701,12 @@ impl SqliteRegistry {
|
|||||||
) -> Result<(), RegistryError> {
|
) -> Result<(), RegistryError> {
|
||||||
let result = sqlx::query(
|
let result = sqlx::query(
|
||||||
"update yaml_import_jobs
|
"update yaml_import_jobs
|
||||||
set status = ?,
|
set status = $1,
|
||||||
result_operation_id = ?,
|
result_operation_id = $2,
|
||||||
result_version = ?,
|
result_version = $3,
|
||||||
error_text = ?,
|
error_text = $4,
|
||||||
finished_at = ?
|
finished_at = $5::timestamptz
|
||||||
where id = ?",
|
where id = $6",
|
||||||
)
|
)
|
||||||
.bind(serialize_enum_text(&completion.status, "status")?)
|
.bind(serialize_enum_text(&completion.status, "status")?)
|
||||||
.bind(
|
.bind(
|
||||||
@@ -715,10 +745,10 @@ impl SqliteRegistry {
|
|||||||
result_operation_id,
|
result_operation_id,
|
||||||
result_version,
|
result_version,
|
||||||
error_text,
|
error_text,
|
||||||
created_at,
|
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
|
||||||
finished_at
|
to_char(finished_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as finished_at
|
||||||
from yaml_import_jobs
|
from yaml_import_jobs
|
||||||
where id = ?",
|
where id = $1",
|
||||||
)
|
)
|
||||||
.bind(job_id.as_str())
|
.bind(job_id.as_str())
|
||||||
.fetch_optional(&self.pool)
|
.fetch_optional(&self.pool)
|
||||||
@@ -729,7 +759,7 @@ impl SqliteRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn insert_version_row(
|
async fn insert_version_row(
|
||||||
tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>,
|
tx: &mut Transaction<'_, Postgres>,
|
||||||
snapshot: &RegistryOperation,
|
snapshot: &RegistryOperation,
|
||||||
change_note: Option<&str>,
|
change_note: Option<&str>,
|
||||||
created_by: Option<&str>,
|
created_by: Option<&str>,
|
||||||
@@ -752,21 +782,24 @@ async fn insert_version_row(
|
|||||||
change_note,
|
change_note,
|
||||||
created_at,
|
created_at,
|
||||||
created_by
|
created_by
|
||||||
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
) values (
|
||||||
|
$1, $2, $3, $4, $5, $6, $7, $8,
|
||||||
|
$9, $10, $11, $12, $13, $14, $15::timestamptz, $16
|
||||||
|
)",
|
||||||
)
|
)
|
||||||
.bind(snapshot.id.as_str())
|
.bind(snapshot.id.as_str())
|
||||||
.bind(to_db_version(snapshot.version))
|
.bind(to_db_version(snapshot.version))
|
||||||
.bind(serialize_enum_text(&snapshot.status, "status")?)
|
.bind(serialize_enum_text(&snapshot.status, "status")?)
|
||||||
.bind(serialize_json(&snapshot.target)?)
|
.bind(Json(serialize_json_value(&snapshot.target)?))
|
||||||
.bind(serialize_json(&snapshot.input_schema)?)
|
.bind(Json(serialize_json_value(&snapshot.input_schema)?))
|
||||||
.bind(serialize_json(&snapshot.output_schema)?)
|
.bind(Json(serialize_json_value(&snapshot.output_schema)?))
|
||||||
.bind(serialize_json(&snapshot.input_mapping)?)
|
.bind(Json(serialize_json_value(&snapshot.input_mapping)?))
|
||||||
.bind(serialize_json(&snapshot.output_mapping)?)
|
.bind(Json(serialize_json_value(&snapshot.output_mapping)?))
|
||||||
.bind(serialize_json(&snapshot.execution_config)?)
|
.bind(Json(serialize_json_value(&snapshot.execution_config)?))
|
||||||
.bind(serialize_json(&snapshot.tool_description)?)
|
.bind(Json(serialize_json_value(&snapshot.tool_description)?))
|
||||||
.bind(serialize_option_json(&snapshot.samples)?)
|
.bind(serialize_option_json_value(&snapshot.samples)?.map(Json))
|
||||||
.bind(serialize_option_json(&snapshot.generated_draft)?)
|
.bind(serialize_option_json_value(&snapshot.generated_draft)?.map(Json))
|
||||||
.bind(serialize_option_json(&snapshot.config_export)?)
|
.bind(serialize_option_json_value(&snapshot.config_export)?.map(Json))
|
||||||
.bind(change_note)
|
.bind(change_note)
|
||||||
.bind(&snapshot.updated_at)
|
.bind(&snapshot.updated_at)
|
||||||
.bind(created_by)
|
.bind(created_by)
|
||||||
@@ -804,7 +837,7 @@ fn assert_immutable_fields(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_operation_summary(row: &sqlx::sqlite::SqliteRow) -> Result<OperationSummary, RegistryError> {
|
fn map_operation_summary(row: &PgRow) -> Result<OperationSummary, RegistryError> {
|
||||||
Ok(OperationSummary {
|
Ok(OperationSummary {
|
||||||
id: OperationId::new(row.try_get::<String, _>("id")?),
|
id: OperationId::new(row.try_get::<String, _>("id")?),
|
||||||
name: row.try_get("name")?,
|
name: row.try_get("name")?,
|
||||||
@@ -816,7 +849,7 @@ fn map_operation_summary(row: &sqlx::sqlite::SqliteRow) -> Result<OperationSumma
|
|||||||
"current_draft_version",
|
"current_draft_version",
|
||||||
)?,
|
)?,
|
||||||
latest_published_version: row
|
latest_published_version: row
|
||||||
.try_get::<Option<i64>, _>("latest_published_version")?
|
.try_get::<Option<i32>, _>("latest_published_version")?
|
||||||
.map(|value| from_db_version(value, "latest_published_version"))
|
.map(|value| from_db_version(value, "latest_published_version"))
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
created_at: row.try_get("created_at")?,
|
created_at: row.try_get("created_at")?,
|
||||||
@@ -825,9 +858,7 @@ fn map_operation_summary(row: &sqlx::sqlite::SqliteRow) -> Result<OperationSumma
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_operation_version_record(
|
fn map_operation_version_record(row: &PgRow) -> Result<OperationVersionRecord, RegistryError> {
|
||||||
row: &sqlx::sqlite::SqliteRow,
|
|
||||||
) -> Result<OperationVersionRecord, RegistryError> {
|
|
||||||
let operation_id = OperationId::new(row.try_get::<String, _>("id")?);
|
let operation_id = OperationId::new(row.try_get::<String, _>("id")?);
|
||||||
let version = from_db_version(row.try_get("version")?, "version")?;
|
let version = from_db_version(row.try_get("version")?, "version")?;
|
||||||
let status = deserialize_enum_text(&row.try_get::<String, _>("status")?, "status")?;
|
let status = deserialize_enum_text(&row.try_get::<String, _>("status")?, "status")?;
|
||||||
@@ -846,31 +877,36 @@ fn map_operation_version_record(
|
|||||||
protocol: deserialize_enum_text(&row.try_get::<String, _>("protocol")?, "protocol")?,
|
protocol: deserialize_enum_text(&row.try_get::<String, _>("protocol")?, "protocol")?,
|
||||||
status,
|
status,
|
||||||
version,
|
version,
|
||||||
target: deserialize_json(&row.try_get::<String, _>("target_json")?)?,
|
target: deserialize_json_value(row.try_get::<Json<Value>, _>("target_json")?.0)?,
|
||||||
input_schema: deserialize_json(&row.try_get::<String, _>("input_schema_json")?)?,
|
input_schema: deserialize_json_value(
|
||||||
output_schema: deserialize_json(&row.try_get::<String, _>("output_schema_json")?)?,
|
row.try_get::<Json<Value>, _>("input_schema_json")?.0,
|
||||||
input_mapping: deserialize_json(&row.try_get::<String, _>("input_mapping_json")?)?,
|
|
||||||
output_mapping: deserialize_json(&row.try_get::<String, _>("output_mapping_json")?)?,
|
|
||||||
execution_config: deserialize_json(
|
|
||||||
&row.try_get::<String, _>("execution_config_json")?,
|
|
||||||
)?,
|
)?,
|
||||||
tool_description: deserialize_json(
|
output_schema: deserialize_json_value(
|
||||||
&row.try_get::<String, _>("tool_description_json")?,
|
row.try_get::<Json<Value>, _>("output_schema_json")?.0,
|
||||||
|
)?,
|
||||||
|
input_mapping: deserialize_json_value(
|
||||||
|
row.try_get::<Json<Value>, _>("input_mapping_json")?.0,
|
||||||
|
)?,
|
||||||
|
output_mapping: deserialize_json_value(
|
||||||
|
row.try_get::<Json<Value>, _>("output_mapping_json")?.0,
|
||||||
|
)?,
|
||||||
|
execution_config: deserialize_json_value(
|
||||||
|
row.try_get::<Json<Value>, _>("execution_config_json")?.0,
|
||||||
|
)?,
|
||||||
|
tool_description: deserialize_json_value(
|
||||||
|
row.try_get::<Json<Value>, _>("tool_description_json")?.0,
|
||||||
)?,
|
)?,
|
||||||
samples: row
|
samples: row
|
||||||
.try_get::<Option<String>, _>("samples_json")?
|
.try_get::<Option<Json<Value>>, _>("samples_json")?
|
||||||
.as_deref()
|
.map(|value| deserialize_json_value(value.0))
|
||||||
.map(deserialize_json)
|
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
generated_draft: row
|
generated_draft: row
|
||||||
.try_get::<Option<String>, _>("generated_draft_json")?
|
.try_get::<Option<Json<Value>>, _>("generated_draft_json")?
|
||||||
.as_deref()
|
.map(|value| deserialize_json_value(value.0))
|
||||||
.map(deserialize_json)
|
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
config_export: row
|
config_export: row
|
||||||
.try_get::<Option<String>, _>("config_export_json")?
|
.try_get::<Option<Json<Value>>, _>("config_export_json")?
|
||||||
.as_deref()
|
.map(|value| deserialize_json_value(value.0))
|
||||||
.map(deserialize_json)
|
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
created_at: row.try_get("operation_created_at")?,
|
created_at: row.try_get("operation_created_at")?,
|
||||||
updated_at: row.try_get("operation_updated_at")?,
|
updated_at: row.try_get("operation_updated_at")?,
|
||||||
@@ -879,20 +915,18 @@ fn map_operation_version_record(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_auth_profile(row: &sqlx::sqlite::SqliteRow) -> Result<AuthProfile, RegistryError> {
|
fn map_auth_profile(row: &PgRow) -> Result<AuthProfile, RegistryError> {
|
||||||
Ok(AuthProfile {
|
Ok(AuthProfile {
|
||||||
id: mcpaas_core::AuthProfileId::new(row.try_get::<String, _>("id")?),
|
id: mcpaas_core::AuthProfileId::new(row.try_get::<String, _>("id")?),
|
||||||
name: row.try_get("name")?,
|
name: row.try_get("name")?,
|
||||||
kind: deserialize_enum_text(&row.try_get::<String, _>("kind")?, "kind")?,
|
kind: deserialize_enum_text(&row.try_get::<String, _>("kind")?, "kind")?,
|
||||||
config: deserialize_json(&row.try_get::<String, _>("config_json")?)?,
|
config: deserialize_json_value(row.try_get::<Json<Value>, _>("config_json")?.0)?,
|
||||||
created_at: row.try_get("created_at")?,
|
created_at: row.try_get("created_at")?,
|
||||||
updated_at: row.try_get("updated_at")?,
|
updated_at: row.try_get("updated_at")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_sample_metadata(
|
fn map_sample_metadata(row: &PgRow) -> Result<OperationSampleMetadata, RegistryError> {
|
||||||
row: &sqlx::sqlite::SqliteRow,
|
|
||||||
) -> Result<OperationSampleMetadata, RegistryError> {
|
|
||||||
Ok(OperationSampleMetadata {
|
Ok(OperationSampleMetadata {
|
||||||
id: mcpaas_core::SampleId::new(row.try_get::<String, _>("id")?),
|
id: mcpaas_core::SampleId::new(row.try_get::<String, _>("id")?),
|
||||||
operation_id: OperationId::new(row.try_get::<String, _>("operation_id")?),
|
operation_id: OperationId::new(row.try_get::<String, _>("operation_id")?),
|
||||||
@@ -908,16 +942,14 @@ fn map_sample_metadata(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_descriptor_metadata(
|
fn map_descriptor_metadata(row: &PgRow) -> Result<DescriptorMetadata, RegistryError> {
|
||||||
row: &sqlx::sqlite::SqliteRow,
|
|
||||||
) -> Result<DescriptorMetadata, RegistryError> {
|
|
||||||
Ok(DescriptorMetadata {
|
Ok(DescriptorMetadata {
|
||||||
id: mcpaas_core::DescriptorId::new(row.try_get::<String, _>("id")?),
|
id: mcpaas_core::DescriptorId::new(row.try_get::<String, _>("id")?),
|
||||||
operation_id: row
|
operation_id: row
|
||||||
.try_get::<Option<String>, _>("operation_id")?
|
.try_get::<Option<String>, _>("operation_id")?
|
||||||
.map(OperationId::new),
|
.map(OperationId::new),
|
||||||
version: row
|
version: row
|
||||||
.try_get::<Option<i64>, _>("version")?
|
.try_get::<Option<i32>, _>("version")?
|
||||||
.map(|value| from_db_version(value, "version"))
|
.map(|value| from_db_version(value, "version"))
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
descriptor_kind: deserialize_enum_text(
|
descriptor_kind: deserialize_enum_text(
|
||||||
@@ -927,15 +959,13 @@ fn map_descriptor_metadata(
|
|||||||
storage_ref: row.try_get("storage_ref")?,
|
storage_ref: row.try_get("storage_ref")?,
|
||||||
source_name: row.try_get("source_name")?,
|
source_name: row.try_get("source_name")?,
|
||||||
package_index: row
|
package_index: row
|
||||||
.try_get::<Option<String>, _>("package_index_json")?
|
.try_get::<Option<Json<Value>>, _>("package_index_json")?
|
||||||
.as_deref()
|
.map(|value| value.0),
|
||||||
.map(deserialize_json)
|
|
||||||
.transpose()?,
|
|
||||||
created_at: row.try_get("created_at")?,
|
created_at: row.try_get("created_at")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_yaml_import_job(row: &sqlx::sqlite::SqliteRow) -> Result<YamlImportJob, RegistryError> {
|
fn map_yaml_import_job(row: &PgRow) -> Result<YamlImportJob, RegistryError> {
|
||||||
Ok(YamlImportJob {
|
Ok(YamlImportJob {
|
||||||
id: YamlImportJobId::new(row.try_get::<String, _>("id")?),
|
id: YamlImportJobId::new(row.try_get::<String, _>("id")?),
|
||||||
source_sample_id: row
|
source_sample_id: row
|
||||||
@@ -948,7 +978,7 @@ fn map_yaml_import_job(row: &sqlx::sqlite::SqliteRow) -> Result<YamlImportJob, R
|
|||||||
.try_get::<Option<String>, _>("result_operation_id")?
|
.try_get::<Option<String>, _>("result_operation_id")?
|
||||||
.map(OperationId::new),
|
.map(OperationId::new),
|
||||||
result_version: row
|
result_version: row
|
||||||
.try_get::<Option<i64>, _>("result_version")?
|
.try_get::<Option<i32>, _>("result_version")?
|
||||||
.map(|value| from_db_version(value, "result_version"))
|
.map(|value| from_db_version(value, "result_version"))
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
error_text: row.try_get("error_text")?,
|
error_text: row.try_get("error_text")?,
|
||||||
@@ -957,16 +987,18 @@ fn map_yaml_import_job(row: &sqlx::sqlite::SqliteRow) -> Result<YamlImportJob, R
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_json<T: Serialize>(value: &T) -> Result<String, RegistryError> {
|
fn serialize_json_value<T: Serialize>(value: &T) -> Result<Value, RegistryError> {
|
||||||
Ok(serde_json::to_string(value)?)
|
Ok(serde_json::to_value(value)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_option_json<T: Serialize>(value: &Option<T>) -> Result<Option<String>, RegistryError> {
|
fn serialize_option_json_value<T: Serialize>(
|
||||||
value.as_ref().map(serialize_json).transpose()
|
value: &Option<T>,
|
||||||
|
) -> Result<Option<Value>, RegistryError> {
|
||||||
|
value.as_ref().map(serialize_json_value).transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_json<T: DeserializeOwned>(value: &str) -> Result<T, RegistryError> {
|
fn deserialize_json_value<T: DeserializeOwned>(value: Value) -> Result<T, RegistryError> {
|
||||||
Ok(serde_json::from_str(value)?)
|
Ok(serde_json::from_value(value)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_enum_text<T: Serialize>(
|
fn serialize_enum_text<T: Serialize>(
|
||||||
@@ -987,17 +1019,24 @@ fn deserialize_enum_text<T: DeserializeOwned>(
|
|||||||
.map_err(|_| RegistryError::InvalidEnumRepresentation { field })
|
.map_err(|_| RegistryError::InvalidEnumRepresentation { field })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_version(value: u32) -> i64 {
|
fn to_db_version(value: u32) -> i32 {
|
||||||
i64::from(value)
|
value as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_db_version(value: i64, field: &'static str) -> Result<u32, RegistryError> {
|
fn from_db_version(value: i32, field: &'static str) -> Result<u32, RegistryError> {
|
||||||
u32::try_from(value).map_err(|_| RegistryError::InvalidNumericValue { field, value })
|
u32::try_from(value).map_err(|_| RegistryError::InvalidNumericValue {
|
||||||
|
field,
|
||||||
|
value: i64::from(value),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::BTreeMap;
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
env,
|
||||||
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
|
};
|
||||||
|
|
||||||
use mcpaas_core::{
|
use mcpaas_core::{
|
||||||
ApiKeyHeaderAuthConfig, AuthConfig, AuthKind, AuthProfile, ConfigExport, ExecutionConfig,
|
ApiKeyHeaderAuthConfig, AuthConfig, AuthKind, AuthProfile, ConfigExport, ExecutionConfig,
|
||||||
@@ -1008,10 +1047,10 @@ mod tests {
|
|||||||
use mcpaas_mapping::{MappingRule, MappingSet};
|
use mcpaas_mapping::{MappingRule, MappingSet};
|
||||||
use mcpaas_schema::{Schema, SchemaKind};
|
use mcpaas_schema::{Schema, SchemaKind};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use sqlx::{Executor, PgPool, postgres::PgPoolOptions};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
SqliteRegistry,
|
PostgresRegistry, RegistryError,
|
||||||
error::RegistryError,
|
|
||||||
model::{
|
model::{
|
||||||
CreateVersionRequest, CreateYamlImportJobRequest, DescriptorKind, DescriptorMetadata,
|
CreateVersionRequest, CreateYamlImportJobRequest, DescriptorKind, DescriptorMetadata,
|
||||||
OperationSampleMetadata, PublishRequest, RegistryOperation, SampleKind,
|
OperationSampleMetadata, PublishRequest, RegistryOperation, SampleKind,
|
||||||
@@ -1022,7 +1061,8 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn stores_versions_and_published_operations() {
|
async fn stores_versions_and_published_operations() {
|
||||||
let registry = SqliteRegistry::connect("sqlite::memory:").await.unwrap();
|
let database = TestDatabase::new().await;
|
||||||
|
let registry = database.registry().await;
|
||||||
let operation_v1 = test_operation("op_rest_01", 1, OperationStatus::Draft);
|
let operation_v1 = test_operation("op_rest_01", 1, OperationStatus::Draft);
|
||||||
|
|
||||||
registry
|
registry
|
||||||
@@ -1076,11 +1116,14 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(published.version, 2);
|
assert_eq!(published.version, 2);
|
||||||
assert!(published.is_published());
|
assert!(published.is_published());
|
||||||
|
|
||||||
|
database.cleanup().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn rejects_out_of_order_versions() {
|
async fn rejects_out_of_order_versions() {
|
||||||
let registry = SqliteRegistry::connect("sqlite::memory:").await.unwrap();
|
let database = TestDatabase::new().await;
|
||||||
|
let registry = database.registry().await;
|
||||||
let operation = test_operation("op_rest_02", 1, OperationStatus::Draft);
|
let operation = test_operation("op_rest_02", 1, OperationStatus::Draft);
|
||||||
|
|
||||||
registry.create_operation(&operation, None).await.unwrap();
|
registry.create_operation(&operation, None).await.unwrap();
|
||||||
@@ -1103,11 +1146,14 @@ mod tests {
|
|||||||
..
|
..
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
database.cleanup().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn stores_auth_profiles_and_artifact_metadata() {
|
async fn stores_auth_profiles_and_artifact_metadata() {
|
||||||
let registry = SqliteRegistry::connect("sqlite::memory:").await.unwrap();
|
let database = TestDatabase::new().await;
|
||||||
|
let registry = database.registry().await;
|
||||||
let operation = test_operation("op_rest_03", 1, OperationStatus::Draft);
|
let operation = test_operation("op_rest_03", 1, OperationStatus::Draft);
|
||||||
|
|
||||||
registry.create_operation(&operation, None).await.unwrap();
|
registry.create_operation(&operation, None).await.unwrap();
|
||||||
@@ -1178,11 +1224,14 @@ mod tests {
|
|||||||
assert_eq!(auth_profiles, vec![auth_profile]);
|
assert_eq!(auth_profiles, vec![auth_profile]);
|
||||||
assert_eq!(samples, vec![input_sample]);
|
assert_eq!(samples, vec![input_sample]);
|
||||||
assert_eq!(descriptors, vec![descriptor]);
|
assert_eq!(descriptors, vec![descriptor]);
|
||||||
|
|
||||||
|
database.cleanup().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn stores_and_finishes_yaml_import_jobs() {
|
async fn stores_and_finishes_yaml_import_jobs() {
|
||||||
let registry = SqliteRegistry::connect("sqlite::memory:").await.unwrap();
|
let database = TestDatabase::new().await;
|
||||||
|
let registry = database.registry().await;
|
||||||
let job_id = YamlImportJobId::new("job_yaml_01");
|
let job_id = YamlImportJobId::new("job_yaml_01");
|
||||||
let operation = test_operation("op_rest_04", 1, OperationStatus::Draft);
|
let operation = test_operation("op_rest_04", 1, OperationStatus::Draft);
|
||||||
|
|
||||||
@@ -1222,6 +1271,61 @@ mod tests {
|
|||||||
assert_eq!(job.status, YamlImportJobStatus::Completed);
|
assert_eq!(job.status, YamlImportJobStatus::Completed);
|
||||||
assert_eq!(job.result_version, Some(2));
|
assert_eq!(job.result_version, Some(2));
|
||||||
assert_eq!(job.mode, ExportMode::Portable);
|
assert_eq!(job.mode, ExportMode::Portable);
|
||||||
|
|
||||||
|
database.cleanup().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestDatabase {
|
||||||
|
admin_pool: PgPool,
|
||||||
|
database_url: String,
|
||||||
|
schema: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestDatabase {
|
||||||
|
async fn new() -> Self {
|
||||||
|
let database_url = env::var("TEST_DATABASE_URL")
|
||||||
|
.expect("TEST_DATABASE_URL must point to a reachable PostgreSQL database");
|
||||||
|
let admin_pool = PgPoolOptions::new()
|
||||||
|
.max_connections(1)
|
||||||
|
.connect(&database_url)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let schema = format!(
|
||||||
|
"test_registry_{}_{}",
|
||||||
|
std::process::id(),
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_nanos()
|
||||||
|
);
|
||||||
|
|
||||||
|
admin_pool
|
||||||
|
.execute(sqlx::query(&format!("create schema {schema}")))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
admin_pool,
|
||||||
|
database_url,
|
||||||
|
schema,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn registry(&self) -> PostgresRegistry {
|
||||||
|
PostgresRegistry::connect_in_schema(&self.database_url, Some(&self.schema))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cleanup(&self) {
|
||||||
|
self.admin_pool
|
||||||
|
.execute(sqlx::query(&format!(
|
||||||
|
"drop schema if exists {} cascade",
|
||||||
|
self.schema
|
||||||
|
)))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_operation(id: &str, version: u32, status: OperationStatus) -> RegistryOperation {
|
fn test_operation(id: &str, version: u32, status: OperationStatus) -> RegistryOperation {
|
||||||
@@ -1344,7 +1448,7 @@ mod tests {
|
|||||||
export_mode: ExportMode::Portable,
|
export_mode: ExportMode::Portable,
|
||||||
}),
|
}),
|
||||||
created_at: "2026-03-25T11:58:00Z".to_owned(),
|
created_at: "2026-03-25T11:58:00Z".to_owned(),
|
||||||
updated_at: format!("2026-03-25T12:{:02}:00Z", version),
|
updated_at: format!("2026-03-25T12:{version:02}:00Z"),
|
||||||
published_at: None,
|
published_at: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,8 @@ services:
|
|||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-rmcp}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-rmcp}
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5432:5432"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-rmcp} -d ${POSTGRES_DB:-rmcp}"]
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-rmcp} -d ${POSTGRES_DB:-rmcp}"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ mcpaas/
|
|||||||
- `tokio` как async runtime
|
- `tokio` как async runtime
|
||||||
- `axum` для HTTP API
|
- `axum` для HTTP API
|
||||||
- `serde` и `serde_json`
|
- `serde` и `serde_json`
|
||||||
- `sqlx` для PostgreSQL или SQLite
|
- `sqlx` для PostgreSQL
|
||||||
- `reqwest` для REST и GraphQL транспорта
|
- `reqwest` для REST и GraphQL транспорта
|
||||||
- `tonic` и `prost` для работы с gRPC
|
- `tonic` и `prost` для работы с gRPC
|
||||||
- `tower` для middleware
|
- `tower` для middleware
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Этот документ фиксирует структуру хранения конфигураций, версий операций, загруженных артефактов и published runtime-view. Его цель - дать основу для SQL-миграций и для реализации `mcpaas-registry`.
|
Этот документ фиксирует структуру хранения конфигураций, версий операций, загруженных артефактов и published runtime-view. Его цель - дать основу для SQL-миграций и для реализации `mcpaas-registry`.
|
||||||
|
|
||||||
В документе предполагается реляционная модель, ориентированная на `PostgreSQL`. Для MVP допускается адаптация под `SQLite`, но канонической считается схема, совместимая с `PostgreSQL`.
|
В документе предполагается реляционная модель, ориентированная на `PostgreSQL`. Канонической считается схема, совместимая с `PostgreSQL`.
|
||||||
|
|
||||||
## 2. Общие принципы хранения
|
## 2. Общие принципы хранения
|
||||||
|
|
||||||
@@ -30,13 +30,13 @@
|
|||||||
|
|
||||||
Для MVP рекомендуется отдельная таблица `auth_profiles`, где metadata и secret refs отделены от operation versions.
|
Для MVP рекомендуется отдельная таблица `auth_profiles`, где metadata и secret refs отделены от operation versions.
|
||||||
|
|
||||||
### 2.5. SQLite-адаптация допустима
|
### 2.5. Тестовая изоляция
|
||||||
|
|
||||||
Канонической схемой остается PostgreSQL-совместимая модель, но MVP-реализация registry может использовать SQLite. В таком случае:
|
Integration tests для registry должны выполняться на реальной `PostgreSQL`, но без влияния на runtime-данные. Предпочтительный способ:
|
||||||
|
|
||||||
- `jsonb` хранится как `text` с JSON-сериализацией;
|
- отдельная test database;
|
||||||
- `timestamptz` хранится как `text`;
|
- либо отдельная временная schema на время теста;
|
||||||
- внешние ключи и version snapshot semantics сохраняются без изменения.
|
- обязательная очистка после завершения тестов.
|
||||||
|
|
||||||
## 3. Основные таблицы
|
## 3. Основные таблицы
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ flowchart LR
|
|||||||
REST[adapter-rest]
|
REST[adapter-rest]
|
||||||
GQL[adapter-graphql]
|
GQL[adapter-graphql]
|
||||||
GRPC[adapter-grpc]
|
GRPC[adapter-grpc]
|
||||||
DB[(PostgreSQL/SQLite)]
|
DB[(PostgreSQL)]
|
||||||
STORE[(Artifact Storage)]
|
STORE[(Artifact Storage)]
|
||||||
|
|
||||||
UI --> ADMIN
|
UI --> ADMIN
|
||||||
|
|||||||
@@ -311,7 +311,6 @@ mcpaas-registry/
|
|||||||
get_runtime_view.rs
|
get_runtime_view.rs
|
||||||
storage/
|
storage/
|
||||||
mod.rs
|
mod.rs
|
||||||
sqlite.rs
|
|
||||||
postgres.rs
|
postgres.rs
|
||||||
cache/
|
cache/
|
||||||
mod.rs
|
mod.rs
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
## 2. Базовые решения для MVP
|
## 2. Базовые решения для MVP
|
||||||
|
|
||||||
- каноническая БД: `PostgreSQL`
|
- каноническая БД: `PostgreSQL`
|
||||||
- допустимый упрощенный режим разработки: `SQLite`
|
- локальная разработка и тесты используют ту же `PostgreSQL`-модель хранения
|
||||||
- artifact storage: локальная файловая система
|
- artifact storage: локальная файловая система
|
||||||
- MCP transport: `Streamable HTTP`
|
- MCP transport: `Streamable HTTP`
|
||||||
- admin API и mcp-server запускаются как отдельные приложения
|
- admin API и mcp-server запускаются как отдельные приложения
|
||||||
@@ -100,7 +100,7 @@ var/mcpaas/
|
|||||||
|
|
||||||
Local development:
|
Local development:
|
||||||
|
|
||||||
- `SQLite` допустим;
|
- локальное окружение должно иметь доступ к `PostgreSQL`;
|
||||||
- локальный storage;
|
- локальный storage;
|
||||||
- упрощенная auth-модель admin-api.
|
- упрощенная auth-модель admin-api.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user