Add db migration support, change variables schema.

This is a bit of a large commit that adds basic database migration
support. It also alters the way user variables are stored in a way
requiring manual migration of existing data. The first automated
migration adds variable count in a new place.
This commit is contained in:
projectmoon 2020-10-24 13:46:06 +00:00 committed by ProjectMoon
parent 4d9ad42bdd
commit a53ce85f38
11 changed files with 619 additions and 126 deletions

398
Cargo.lock generated
View File

@ -70,9 +70,9 @@ 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 = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -81,9 +81,9 @@ version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -92,7 +92,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3410529e8288c463bedb5930f82833bc0c90e5d2fe639a56582a4d09220b281" checksum = "c3410529e8288c463bedb5930f82833bc0c90e5d2fe639a56582a4d09220b281"
dependencies = [ dependencies = [
"autocfg", "autocfg 1.0.1",
] ]
[[package]] [[package]]
@ -106,6 +106,12 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.1" version = "1.0.1"
@ -193,7 +199,8 @@ dependencies = [
"matrix-sdk", "matrix-sdk",
"nom", "nom",
"olm-sys", "olm-sys",
"rand", "phf",
"rand 0.7.3",
"serde", "serde",
"sled", "sled",
"tempfile", "tempfile",
@ -216,6 +223,15 @@ dependencies = [
"serde_json", "serde_json",
] ]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "cloudabi" name = "cloudabi"
version = "0.1.0" version = "0.1.0"
@ -308,7 +324,7 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
dependencies = [ dependencies = [
"autocfg", "autocfg 1.0.1",
"cfg-if 0.1.10", "cfg-if 0.1.10",
"crossbeam-utils", "crossbeam-utils",
"lazy_static", "lazy_static",
@ -334,7 +350,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [ dependencies = [
"autocfg", "autocfg 1.0.1",
"cfg-if 0.1.10", "cfg-if 0.1.10",
"lazy_static", "lazy_static",
] ]
@ -457,6 +473,12 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]] [[package]]
name = "fuchsia-zircon" name = "fuchsia-zircon"
version = "0.3.3" version = "0.3.3"
@ -536,9 +558,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36fccf3fc58563b4a14d265027c627c3b665d7fed489427e88e7cc929559efe" checksum = "e36fccf3fc58563b4a14d265027c627c3b665d7fed489427e88e7cc929559efe"
dependencies = [ dependencies = [
"proc-macro-hack", "proc-macro-hack",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -777,7 +799,7 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
dependencies = [ dependencies = [
"autocfg", "autocfg 1.0.1",
"hashbrown", "hashbrown",
] ]
@ -983,8 +1005,8 @@ name = "matrix-sdk-common-macros"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/matrix-org/matrix-rust-sdk?rev=master#6872cc717b8b7746ea4c4bec8d143e8653f965ed" source = "git+https://github.com/matrix-org/matrix-rust-sdk?rev=master#6872cc717b8b7746ea4c4bec8d143e8653f965ed"
dependencies = [ dependencies = [
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1027,7 +1049,7 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
dependencies = [ dependencies = [
"autocfg", "autocfg 1.0.1",
] ]
[[package]] [[package]]
@ -1213,7 +1235,7 @@ version = "0.9.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
dependencies = [ dependencies = [
"autocfg", "autocfg 1.0.1",
"cc", "cc",
"libc", "libc",
"pkg-config", "pkg-config",
@ -1238,7 +1260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 0.1.10",
"cloudabi", "cloudabi 0.1.0",
"instant", "instant",
"libc", "libc",
"redox_syscall", "redox_syscall",
@ -1252,6 +1274,48 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "phf"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
dependencies = [
"phf_macros",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
dependencies = [
"phf_shared",
"rand 0.6.5",
]
[[package]]
name = "phf_macros"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdb45e833315153371697760dad1831da99ce41884162320305e4f123ca3fe37"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.15.44",
]
[[package]]
name = "phf_shared"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "0.4.27" version = "0.4.27"
@ -1276,9 +1340,9 @@ version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1287,9 +1351,9 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1337,13 +1401,22 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid 0.1.0",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
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 = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid 0.2.1",
] ]
[[package]] [[package]]
@ -1352,13 +1425,41 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.7" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.7",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc 0.1.0",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi 0.3.9",
] ]
[[package]] [[package]]
@ -1369,9 +1470,19 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [ dependencies = [
"getrandom 0.1.15", "getrandom 0.1.15",
"libc", "libc",
"rand_chacha", "rand_chacha 0.2.2",
"rand_core", "rand_core 0.5.1",
"rand_hc", "rand_hc 0.2.0",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.3.1",
] ]
[[package]] [[package]]
@ -1381,9 +1492,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core", "rand_core 0.5.1",
] ]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.5.1" version = "0.5.1"
@ -1393,13 +1519,84 @@ dependencies = [
"getrandom 0.1.15", "getrandom 0.1.15",
] ]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]] [[package]]
name = "rand_hc" name = "rand_hc"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [ dependencies = [
"rand_core", "rand_core 0.5.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi 0.3.9",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi 0.0.3",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi 0.3.9",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
] ]
[[package]] [[package]]
@ -1515,9 +1712,9 @@ version = "0.17.0-alpha.1"
source = "git+https://github.com/ruma/ruma?rev=409fbcc9d745fb7290327cb7f5defc714229ab30#409fbcc9d745fb7290327cb7f5defc714229ab30" source = "git+https://github.com/ruma/ruma?rev=409fbcc9d745fb7290327cb7f5defc714229ab30#409fbcc9d745fb7290327cb7f5defc714229ab30"
dependencies = [ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1574,9 +1771,9 @@ version = "0.22.0-alpha.1"
source = "git+https://github.com/ruma/ruma?rev=409fbcc9d745fb7290327cb7f5defc714229ab30#409fbcc9d745fb7290327cb7f5defc714229ab30" source = "git+https://github.com/ruma/ruma?rev=409fbcc9d745fb7290327cb7f5defc714229ab30#409fbcc9d745fb7290327cb7f5defc714229ab30"
dependencies = [ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1595,10 +1792,10 @@ name = "ruma-identifiers-macros"
version = "0.17.4" version = "0.17.4"
source = "git+https://github.com/ruma/ruma?rev=409fbcc9d745fb7290327cb7f5defc714229ab30#409fbcc9d745fb7290327cb7f5defc714229ab30" source = "git+https://github.com/ruma/ruma?rev=409fbcc9d745fb7290327cb7f5defc714229ab30#409fbcc9d745fb7290327cb7f5defc714229ab30"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"ruma-identifiers-validation", "ruma-identifiers-validation",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1724,9 +1921,9 @@ version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1768,6 +1965,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "siphasher"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.2" version = "0.4.2"
@ -1865,10 +2068,10 @@ dependencies = [
"futures", "futures",
"heck", "heck",
"lazy_static", "lazy_static",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"sqlx-core", "sqlx-core",
"syn", "syn 1.0.48",
"tokio", "tokio",
"url", "url",
] ]
@ -1908,11 +2111,11 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"serde", "serde",
"serde_derive", "serde_derive",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1922,13 +2125,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
dependencies = [ dependencies = [
"base-x", "base-x",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"sha1", "sha1",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -1953,9 +2156,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e61bb0be289045cb80bfce000512e32d09f8337e54c186725da381377ad1f8d5" checksum = "e61bb0be289045cb80bfce000512e32d09f8337e54c186725da381377ad1f8d5"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
]
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"unicode-xid 0.1.0",
] ]
[[package]] [[package]]
@ -1964,9 +2178,9 @@ version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"unicode-xid", "unicode-xid 0.2.1",
] ]
[[package]] [[package]]
@ -1975,10 +2189,10 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
"unicode-xid", "unicode-xid 0.2.1",
] ]
[[package]] [[package]]
@ -1989,7 +2203,7 @@ checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 0.1.10",
"libc", "libc",
"rand", "rand 0.7.3",
"redox_syscall", "redox_syscall",
"remove_dir_all", "remove_dir_all",
"winapi 0.3.9", "winapi 0.3.9",
@ -2019,9 +2233,9 @@ version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -2065,10 +2279,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
dependencies = [ dependencies = [
"proc-macro-hack", "proc-macro-hack",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"standback", "standback",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -2107,9 +2321,9 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -2170,9 +2384,9 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
] ]
[[package]] [[package]]
@ -2233,6 +2447,12 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.1" version = "0.2.1"
@ -2262,7 +2482,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
dependencies = [ dependencies = [
"rand", "rand 0.7.3",
] ]
[[package]] [[package]]
@ -2314,9 +2534,9 @@ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
"log", "log",
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2338,7 +2558,7 @@ version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
dependencies = [ dependencies = [
"quote", "quote 1.0.7",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
] ]
@ -2348,9 +2568,9 @@ version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2449,8 +2669,8 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"syn", "syn 1.0.48",
"synstructure", "synstructure",
] ]
@ -2469,8 +2689,8 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.24",
"quote", "quote 1.0.7",
"syn", "syn 1.0.48",
"synstructure", "synstructure",
] ]

View File

@ -27,6 +27,7 @@ sled = "0.34"
zerocopy = "0.3" zerocopy = "0.3"
byteorder = "1.3" byteorder = "1.3"
futures = "0.3" futures = "0.3"
phf = { version = "0.7", features = ["macros"] }
olm-sys = "1.0" olm-sys = "1.0"
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "master" } matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "master" }

View File

@ -29,6 +29,8 @@ async fn run() -> Result<(), BotError> {
let db = Database::new(&cfg.database_path())?; let db = Database::new(&cfg.database_path())?;
let state = Arc::new(RwLock::new(DiceBotState::new(&cfg))); let state = Arc::new(RwLock::new(DiceBotState::new(&cfg)));
db.migrate(cfg.migration_version())?;
match DiceBot::new(&cfg, &state, &db) { match DiceBot::new(&cfg, &state, &db) {
Ok(bot) => bot.run().await?, Ok(bot) => bot.run().await?,
Err(e) => println!("Error connecting: {:?}", e), Err(e) => println!("Error connecting: {:?}", e),

View File

@ -4,6 +4,10 @@ use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use thiserror::Error; use thiserror::Error;
/// Shortcut to defining db migration versions. Will probably
/// eventually be moved to a config file.
const MIGRATION_VERSION: u32 = 1;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ConfigError { pub enum ConfigError {
#[error("i/o error: {0}")] #[error("i/o error: {0}")]
@ -124,6 +128,15 @@ impl Config {
.unwrap_or_else(|| db_path_from_env()) .unwrap_or_else(|| db_path_from_env())
} }
/// The current migration version we expect of the database. If
/// this number is higher than the one in the database, we will
/// execute migrations to update the data.
#[inline]
#[must_use]
pub fn migration_version(&self) -> u32 {
MIGRATION_VERSION
}
/// Figure out the allowed oldest message age, in seconds. This will /// Figure out the allowed oldest message age, in seconds. This will
/// be the defined oldest message age in the bot config, if the bot /// be the defined oldest message age in the bot config, if the bot
/// configuration and associated "oldest_message_age" setting are /// configuration and associated "oldest_message_age" setting are

View File

@ -1,9 +1,13 @@
use crate::db::errors::DataError; use crate::db::errors::{DataError, MigrationError};
use crate::db::migrations::{get_migration_version, Migrations};
use crate::db::variables::Variables; use crate::db::variables::Variables;
use log::info;
use sled::Db; use sled::Db;
use std::path::Path; use std::path::Path;
pub mod data_migrations;
pub mod errors; pub mod errors;
pub mod migrations;
pub mod schema; pub mod schema;
pub mod variables; pub mod variables;
@ -11,19 +15,59 @@ pub mod variables;
pub struct Database { pub struct Database {
db: Db, db: Db,
pub(crate) variables: Variables, pub(crate) variables: Variables,
//rooms: Tree, pub(crate) migrations: Migrations,
} }
impl Database { impl Database {
pub fn new<P: AsRef<Path>>(path: P) -> Result<Database, DataError> { pub fn new<P: AsRef<Path>>(path: P) -> Result<Database, DataError> {
let db = sled::open(path)?; let db = sled::open(path)?;
let variables = db.open_tree("variables")?; let variables = db.open_tree("variables")?;
//let rooms = db.open_tree("rooms")?; let migrations = db.open_tree("migrations")?;
Ok(Database { Ok(Database {
db: db.clone(), db: db.clone(),
variables: Variables(variables), variables: Variables(variables),
//rooms: rooms, migrations: Migrations(migrations),
}) })
} }
pub fn migrate(&self, to_version: u32) -> Result<(), DataError> {
//get version from db
let db_version = get_migration_version(&self)?;
if db_version < to_version {
info!(
"Migrating database from version {} to version {}",
db_version, to_version
);
//if db version < to_version, proceed
//produce range of db_version+1 .. to_version (inclusive)
let versions_to_run: Vec<u32> = ((db_version + 1)..=to_version).collect();
let migrations = data_migrations::get_migrations(&versions_to_run)?;
//execute each closure.
for (version, migration_func) in versions_to_run.iter().zip(migrations) {
//This needs to be transactional on migrations
//keyspace. abort on migration func error.
info!("Applying migration: {}", version);
match migration_func(&self) {
Ok(_) => Ok(()),
Err(e) => Err(e),
}?;
self.migrations.set_migration_version(*version)?;
}
info!("Done applying migrations.");
Ok(())
} else if db_version > to_version {
//if db version > to_version, cannot downgrade error
Err(MigrationError::CannotDowngrade.into())
} else {
//if db version == to_version, do nothing
info!("No database migrations needed.");
Ok(())
}
}
} }

22
src/db/data_migrations.rs Normal file
View File

@ -0,0 +1,22 @@
use crate::db::errors::{DataError, MigrationError};
use crate::db::Database;
use phf::phf_map;
pub(super) type DataMigration = fn(&Database) -> Result<(), DataError>;
static MIGRATIONS: phf::Map<u32, DataMigration> = phf_map! {
1u32 => super::variables::migrations::migration1,
};
pub fn get_migrations(versions: &[u32]) -> Result<Vec<DataMigration>, MigrationError> {
let mut migrations: Vec<DataMigration> = vec![];
for version in versions {
match MIGRATIONS.get(version) {
Some(func) => migrations.push(*func),
None => return Err(MigrationError::MigrationNotFound(*version)),
}
}
Ok(migrations)
}

View File

@ -1,6 +1,18 @@
use sled::transaction::{TransactionError, UnabortableTransactionError}; use sled::transaction::{TransactionError, UnabortableTransactionError};
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)]
pub enum MigrationError {
#[error("cannot downgrade to an older database version")]
CannotDowngrade,
#[error("migration for version {0} not defined")]
MigrationNotFound(u32),
#[error("migration failed: {0}")]
MigrationFailed(String),
}
//TODO better combining of key and value in certain errors (namely //TODO better combining of key and value in certain errors (namely
//I32SchemaViolation). //I32SchemaViolation).
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -22,6 +34,9 @@ pub enum DataError {
#[error("unabortable transaction error: {0}")] #[error("unabortable transaction error: {0}")]
UnabortableTransactionError(#[from] UnabortableTransactionError), UnabortableTransactionError(#[from] UnabortableTransactionError),
#[error("data migration error: {0}")]
MigrationError(#[from] MigrationError),
} }
/// This From implementation is necessary to deal with the recursive /// This From implementation is necessary to deal with the recursive
@ -40,3 +55,14 @@ impl From<TransactionError<DataError>> for DataError {
} }
} }
} }
// impl From<ConflictableTransactionError<DataError>> for DataError {
// fn from(error: ConflictableTransactionError<DataError>) -> Self {
// match error {
// ConflictableTransactionError::Abort(data_err) => data_err,
// ConflictableTransactionError::Storage(storage_err) => {
// DataError::TransactionError(TransactionError::Storage(storage_err))
// }
// }
// }
// }

54
src/db/migrations.rs Normal file
View File

@ -0,0 +1,54 @@
use crate::db::errors::DataError;
use crate::db::schema::convert_u32;
use crate::db::Database;
use byteorder::LittleEndian;
use sled::Tree;
use zerocopy::byteorder::U32;
use zerocopy::AsBytes;
//This file is for controlling the migration info stored in the
//database, not actually running migrations.
#[derive(Clone)]
pub struct Migrations(pub(super) Tree);
const COLON: &'static [u8] = b":";
const METADATA_SPACE: &'static str = "metadata";
const MIGRATION_KEY: &'static str = "migration_version";
fn to_key(keyspace: &str, key_name: &str) -> Vec<u8> {
let mut key = vec![];
key.extend_from_slice(keyspace.as_bytes());
key.extend_from_slice(COLON);
key.extend_from_slice(key_name.as_bytes());
key
}
fn metadata_key(key_name: &str) -> Vec<u8> {
to_key(METADATA_SPACE, key_name)
}
impl Migrations {
pub(super) fn set_migration_version(&self, version: u32) -> Result<(), DataError> {
//Rust cannot type infer this transaction
let result: Result<_, sled::transaction::TransactionError<DataError>> =
self.0.transaction(|tx| {
let key = metadata_key(MIGRATION_KEY);
let db_value: U32<LittleEndian> = U32::new(version);
tx.insert(key, db_value.as_bytes())?;
Ok(())
});
result?;
Ok(())
}
}
pub(super) fn get_migration_version(db: &Database) -> Result<u32, DataError> {
let key = metadata_key(MIGRATION_KEY);
match db.migrations.0.get(key)? {
Some(bytes) => convert_u32(&bytes),
None => Ok(0),
}
}

View File

@ -1,6 +1,6 @@
use crate::db::errors::DataError; use crate::db::errors::DataError;
use byteorder::LittleEndian; use byteorder::LittleEndian;
use zerocopy::byteorder::I32; use zerocopy::byteorder::{I32, U32};
use zerocopy::LayoutVerified; use zerocopy::LayoutVerified;
/// User variables are stored as little-endian 32-bit integers in the /// User variables are stored as little-endian 32-bit integers in the
@ -8,6 +8,8 @@ use zerocopy::LayoutVerified;
/// read. /// read.
type LittleEndianI32Layout<'a> = LayoutVerified<&'a [u8], I32<LittleEndian>>; type LittleEndianI32Layout<'a> = LayoutVerified<&'a [u8], I32<LittleEndian>>;
type LittleEndianU32Layout<'a> = LayoutVerified<&'a [u8], U32<LittleEndian>>;
/// Convert bytes to an i32 with zero-copy deserialization. An error /// Convert bytes to an i32 with zero-copy deserialization. An error
/// is returned if the bytes do not represent an i32. /// is returned if the bytes do not represent an i32.
pub(super) fn convert_i32(raw_value: &[u8]) -> Result<i32, DataError> { pub(super) fn convert_i32(raw_value: &[u8]) -> Result<i32, DataError> {
@ -20,3 +22,14 @@ pub(super) fn convert_i32(raw_value: &[u8]) -> Result<i32, DataError> {
Err(DataError::I32SchemaViolation) Err(DataError::I32SchemaViolation)
} }
} }
pub(super) fn convert_u32(raw_value: &[u8]) -> Result<u32, DataError> {
let layout = LittleEndianU32Layout::new_unaligned(raw_value.as_ref());
if let Some(layout) = layout {
let value: U32<LittleEndian> = *layout;
Ok(value.get())
} else {
Err(DataError::I32SchemaViolation)
}
}

View File

@ -1,46 +1,71 @@
use crate::db::errors::DataError; use crate::db::errors::DataError;
use crate::db::schema::convert_i32; use crate::db::schema::convert_i32;
use byteorder::LittleEndian; use byteorder::LittleEndian;
use sled::transaction::abort; use sled::transaction::{abort, TransactionalTree};
use sled::transaction::TransactionalTree;
use sled::Tree; use sled::Tree;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From;
use std::str; use std::str;
use zerocopy::byteorder::I32; use zerocopy::byteorder::I32;
use zerocopy::AsBytes; use zerocopy::AsBytes;
const METADATA_KEY: &'static str = "metadata"; pub(super) mod migrations;
const METADATA_SPACE: &'static [u8] = b"metadata";
const VARIABLE_SPACE: &'static [u8] = b"variables";
const VARIABLE_COUNT_KEY: &'static str = "variable_count"; const VARIABLE_COUNT_KEY: &'static str = "variable_count";
#[derive(Clone)] #[derive(Clone)]
pub struct Variables(pub(crate) Tree); pub struct Variables(pub(super) Tree);
fn to_key(room_id: &str, username: &str, variable_name: &str) -> Vec<u8> { //TODO at least some of these will probalby move elsewhere.
let mut key = vec![];
key.extend_from_slice(room_id.as_bytes()); fn space_prefix<D: Into<Vec<u8>>>(space: &[u8], delineator: D) -> Vec<u8> {
key.extend_from_slice(username.as_bytes()); let mut metadata_prefix = vec![];
key.extend_from_slice(variable_name.as_bytes()); metadata_prefix.extend_from_slice(space);
key metadata_prefix.push(0xff);
let delineator = delineator.into();
if delineator.len() > 0 {
metadata_prefix.extend_from_slice(delineator.as_bytes());
metadata_prefix.push(0xff);
}
metadata_prefix
} }
fn metadata_key(room_id: &str, username: &str, metadata_key: &str) -> Vec<u8> { fn metadata_space_prefix<D: Into<Vec<u8>>>(delineator: D) -> Vec<u8> {
let mut key = vec![]; space_prefix(METADATA_SPACE, delineator)
key.extend_from_slice(room_id.as_bytes());
key.extend_from_slice(METADATA_KEY.as_bytes());
key.extend_from_slice(username.as_bytes());
key.extend_from_slice(metadata_key.as_bytes());
key
} }
fn room_variable_count_key(room_id: &str, username: &str) -> Vec<u8> { fn metadata_space_key<D: Into<Vec<u8>>>(delineator: D, key_name: &str) -> Vec<u8> {
metadata_key(room_id, username, VARIABLE_COUNT_KEY) let mut metadata_key = metadata_space_prefix(delineator);
metadata_key.extend_from_slice(key_name.as_bytes());
metadata_key
} }
fn to_prefix(room_id: &str, username: &str) -> Vec<u8> { fn variables_space_prefix<D: Into<Vec<u8>>>(delineator: D) -> Vec<u8> {
let mut prefix = vec![]; space_prefix(VARIABLE_SPACE, delineator)
prefix.extend_from_slice(room_id.as_bytes()); }
prefix.extend_from_slice(username.as_bytes());
prefix fn variables_space_key<D: Into<Vec<u8>>>(delineator: D, key_name: &str) -> Vec<u8> {
let mut metadata_key = variables_space_prefix(delineator);
metadata_key.extend_from_slice(key_name.as_bytes());
metadata_key
}
/// Delineator for keeping track of a key by room ID and username.
struct RoomAndUser<'a>(&'a str, &'a str);
impl<'a> From<RoomAndUser<'a>> for Vec<u8> {
fn from(value: RoomAndUser<'a>) -> Vec<u8> {
let mut bytes = vec![];
bytes.extend_from_slice(value.0.as_bytes());
bytes.push(0xff);
bytes.extend_from_slice(value.1.as_bytes());
bytes
}
} }
/// Use a transaction to atomically alter the count of variables in /// Use a transaction to atomically alter the count of variables in
@ -51,7 +76,8 @@ fn alter_room_variable_count(
username: &str, username: &str,
amount: i32, amount: i32,
) -> Result<i32, DataError> { ) -> Result<i32, DataError> {
let key = room_variable_count_key(room_id, username); let key = metadata_space_key(RoomAndUser(room_id, username), VARIABLE_COUNT_KEY);
let mut new_count = match variables.get(&key)? { let mut new_count = match variables.get(&key)? {
Some(bytes) => convert_i32(&bytes)? + amount, Some(bytes) => convert_i32(&bytes)? + amount,
None => amount, None => amount,
@ -72,7 +98,7 @@ impl Variables {
room_id: &str, room_id: &str,
username: &str, username: &str,
) -> Result<HashMap<String, i32>, DataError> { ) -> Result<HashMap<String, i32>, DataError> {
let prefix = to_prefix(&room_id, &username); let prefix = variables_space_prefix(RoomAndUser(room_id, username));
let prefix_len: usize = prefix.len(); let prefix_len: usize = prefix.len();
let variables: Result<Vec<_>, DataError> = self let variables: Result<Vec<_>, DataError> = self
@ -94,7 +120,9 @@ impl Variables {
} }
pub fn get_variable_count(&self, room_id: &str, username: &str) -> Result<i32, DataError> { pub fn get_variable_count(&self, room_id: &str, username: &str) -> Result<i32, DataError> {
let key = room_variable_count_key(room_id, username); let delineator = RoomAndUser(room_id, username);
let key = metadata_space_key(delineator, VARIABLE_COUNT_KEY);
if let Some(raw_value) = self.0.get(&key)? { if let Some(raw_value) = self.0.get(&key)? {
convert_i32(&raw_value) convert_i32(&raw_value)
} else { } else {
@ -108,12 +136,12 @@ impl Variables {
username: &str, username: &str,
variable_name: &str, variable_name: &str,
) -> Result<i32, DataError> { ) -> Result<i32, DataError> {
let key = to_key(room_id, username, variable_name); let key = variables_space_key(RoomAndUser(room_id, username), variable_name);
if let Some(raw_value) = self.0.get(&key)? { if let Some(raw_value) = self.0.get(&key)? {
convert_i32(&raw_value) convert_i32(&raw_value)
} else { } else {
Err(DataError::KeyDoesNotExist(String::from_utf8(key).unwrap())) Err(DataError::KeyDoesNotExist(variable_name.to_owned()))
} }
} }
@ -126,7 +154,7 @@ impl Variables {
) -> Result<(), DataError> { ) -> Result<(), DataError> {
self.0 self.0
.transaction(|tx| { .transaction(|tx| {
let key = to_key(room_id, username, variable_name); let key = variables_space_key(RoomAndUser(room_id, username), variable_name);
let db_value: I32<LittleEndian> = I32::new(value); let db_value: I32<LittleEndian> = I32::new(value);
let old_value = tx.insert(key, db_value.as_bytes())?; let old_value = tx.insert(key, db_value.as_bytes())?;
@ -151,14 +179,16 @@ impl Variables {
) -> Result<(), DataError> { ) -> Result<(), DataError> {
self.0 self.0
.transaction(|tx| { .transaction(|tx| {
let key = to_key(room_id, username, variable_name); let key = variables_space_key(RoomAndUser(room_id, username), variable_name);
//TODO why does tx.remove require moving the key?
if let Some(_) = tx.remove(key.clone())? { if let Some(_) = tx.remove(key.clone())? {
match alter_room_variable_count(&tx, room_id, username, -1) { match alter_room_variable_count(&tx, room_id, username, -1) {
Err(e) => abort(e), Err(e) => abort(e),
_ => Ok(()), _ => Ok(()),
} }
} else { } else {
abort(DataError::KeyDoesNotExist(String::from_utf8(key).unwrap())) abort(DataError::KeyDoesNotExist(variable_name.to_owned()))
} }
}) })
.map_err(|e| e.into()) .map_err(|e| e.into())

View File

@ -0,0 +1,68 @@
use super::*;
use crate::db::errors::{DataError, MigrationError};
use crate::db::Database;
use byteorder::LittleEndian;
use sled::transaction::TransactionError;
use sled::Batch;
use zerocopy::byteorder::U32;
use zerocopy::AsBytes;
//TODO we will make this set variable count properly.
pub(in crate::db) fn migration1(db: &Database) -> Result<(), DataError> {
let tree = &db.variables.0;
let prefix = variables_space_prefix("");
//Extract a vec of tuples, consisting of room id + username.
let results: Vec<(String, String)> = tree
.scan_prefix(prefix)
.map(|entry| {
if let Ok((key, _)) = entry {
let keys: Vec<Result<&str, _>> = key
.split(|&b| b == 0xff)
.map(|b| str::from_utf8(b))
.collect();
if let &[_, Ok(room_id), Ok(username), Ok(_variable)] = keys.as_slice() {
Ok((room_id.to_owned(), username.to_owned()))
} else {
Err(MigrationError::MigrationFailed(
"a key violates utf8 schema".to_string(),
))
}
} else {
Err(MigrationError::MigrationFailed(
"encountered unexpected key".to_string(),
))
}
})
.collect::<Result<Vec<_>, MigrationError>>()?;
let counts: HashMap<(String, String), u32> =
results
.into_iter()
.fold(HashMap::new(), |mut count_map, room_and_user| {
let count = count_map.entry(room_and_user).or_insert(0);
*count += 1;
count_map
});
//Start a transaction on the variables tree.
//Delete the old variable_count variable if exists.
//Add variable count according to new schema.
let tx_result: Result<_, TransactionError<DataError>> = db.variables.0.transaction(|tx_vars| {
let batch = counts.iter().fold(Batch::default(), |mut batch, entry| {
let key =
variables_space_key(RoomAndUser(&(entry.0).0, &(entry.0).1), VARIABLE_COUNT_KEY);
let db_value: U32<LittleEndian> = U32::new(*entry.1);
batch.insert(key, db_value.as_bytes());
batch
});
tx_vars.apply_batch(&batch)?;
Ok(())
});
tx_result?; //For some reason, it cannot infer the type
Ok(())
}