Create Google datastore adaptor

This commit is contained in:
Ben Grant 2023-05-15 15:28:17 +10:00
parent 2da5ba107f
commit 4abb538db7
7 changed files with 621 additions and 21 deletions

412
backend/Cargo.lock generated
View file

@ -60,6 +60,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anyhow"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.7.2" version = "0.7.2"
@ -296,6 +302,12 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "base64"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.13.1" version = "0.13.1"
@ -333,7 +345,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa"
dependencies = [ dependencies = [
"num-bigint", "num-bigint 0.4.3",
"num-integer", "num-integer",
"num-traits", "num-traits",
] ]
@ -669,6 +681,15 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "ct-logs"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8"
dependencies = [
"sct",
]
[[package]] [[package]]
name = "ctor" name = "ctor"
version = "0.1.26" version = "0.1.26"
@ -736,6 +757,19 @@ dependencies = [
"parking_lot_core 0.9.7", "parking_lot_core 0.9.7",
] ]
[[package]]
name = "datastore-adaptor"
version = "0.1.0"
dependencies = [
"async-trait",
"chrono",
"common",
"google-cloud",
"serde",
"serde_json",
"tokio",
]
[[package]] [[package]]
name = "der" name = "der"
version = "0.5.1" version = "0.5.1"
@ -832,6 +866,12 @@ dependencies = [
"instant", "instant",
] ]
[[package]]
name = "fixedbitset"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.26" version = "1.0.26"
@ -1048,6 +1088,28 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "google-cloud"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a517f0235af652d334a021b81aa2e8f18a77512c26be18722debb7d405912f80"
dependencies = [
"chrono",
"futures",
"http",
"hyper",
"hyper-rustls",
"jsonwebtoken",
"prost",
"prost-types",
"serde",
"serde_json",
"thiserror",
"tokio",
"tonic",
"tonic-build",
]
[[package]] [[package]]
name = "governor" name = "governor"
version = "0.5.1" version = "0.5.1"
@ -1066,6 +1128,25 @@ dependencies = [
"smallvec", "smallvec",
] ]
[[package]]
name = "h2"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util 0.7.8",
"tracing",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -1225,6 +1306,7 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
@ -1238,6 +1320,23 @@ dependencies = [
"want", "want",
] ]
[[package]]
name = "hyper-rustls"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64"
dependencies = [
"ct-logs",
"futures-util",
"hyper",
"log",
"rustls",
"rustls-native-certs",
"tokio",
"tokio-rustls",
"webpki",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.56" version = "0.1.56"
@ -1312,6 +1411,15 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -1336,6 +1444,20 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "jsonwebtoken"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afabcc15e437a6484fc4f12d0fd63068fe457bf93f1c148d3d9649c60b103f32"
dependencies = [
"base64 0.12.3",
"pem",
"ring",
"serde",
"serde_json",
"simple_asn1",
]
[[package]] [[package]]
name = "kv-log-macro" name = "kv-log-macro"
version = "1.0.7" version = "1.0.7"
@ -1494,6 +1616,12 @@ dependencies = [
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
[[package]]
name = "multimap"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.11" version = "0.2.11"
@ -1550,6 +1678,17 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.3" version = "0.4.3"
@ -1764,6 +1903,17 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pem"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
dependencies = [
"base64 0.13.1",
"once_cell",
"regex",
]
[[package]] [[package]]
name = "pem-rfc7468" name = "pem-rfc7468"
version = "0.3.1" version = "0.3.1"
@ -1779,6 +1929,16 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "petgraph"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.0.12" version = "1.0.12"
@ -1903,6 +2063,57 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "prost"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-build"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d3ebd75ac2679c2af3a92246639f9fcc8a442ee420719cc4fe195b98dd5fa3"
dependencies = [
"bytes",
"heck 0.3.3",
"itertools 0.9.0",
"log",
"multimap",
"petgraph",
"prost",
"prost-types",
"tempfile",
"which",
]
[[package]]
name = "prost-derive"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4"
dependencies = [
"anyhow",
"itertools 0.9.0",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "prost-types"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b518d7cdd93dab1d1122cf07fa9a60771836c668dde9d9e2a139f957f0d9f1bb"
dependencies = [
"bytes",
"prost",
]
[[package]] [[package]]
name = "ptr_meta" name = "ptr_meta"
version = "0.1.4" version = "0.1.4"
@ -2063,6 +2274,21 @@ dependencies = [
"bytecheck", "bytecheck",
] ]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin 0.5.2",
"untrusted",
"web-sys",
"winapi",
]
[[package]] [[package]]
name = "rkyv" name = "rkyv"
version = "0.7.41" version = "0.7.41"
@ -2175,6 +2401,31 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "rustls"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
dependencies = [
"base64 0.13.1",
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "rustls-native-certs"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092"
dependencies = [
"openssl-probe",
"rustls",
"schannel",
"security-framework",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.12" version = "1.0.12"
@ -2217,6 +2468,16 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]]
name = "sct"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "sea-orm" name = "sea-orm"
version = "0.11.3" version = "0.11.3"
@ -2411,18 +2672,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.162" version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.162" version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2516,6 +2777,17 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
[[package]]
name = "simple_asn1"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
dependencies = [
"chrono",
"num-bigint 0.2.6",
"num-traits",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.8" version = "0.4.8"
@ -2586,7 +2858,7 @@ 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 = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e"
dependencies = [ dependencies = [
"itertools", "itertools 0.10.5",
"nom", "nom",
"unicode_categories", "unicode_categories",
] ]
@ -2639,7 +2911,7 @@ dependencies = [
"log", "log",
"md-5", "md-5",
"memchr", "memchr",
"num-bigint", "num-bigint 0.4.3",
"once_cell", "once_cell",
"paste", "paste",
"percent-encoding", "percent-encoding",
@ -2850,9 +3122,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.28.0" version = "1.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"bytes", "bytes",
@ -2888,6 +3160,17 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-rustls"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
dependencies = [
"rustls",
"tokio",
"webpki",
]
[[package]] [[package]]
name = "tokio-stream" name = "tokio-stream"
version = "0.1.14" version = "0.1.14"
@ -2899,6 +3182,34 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-util"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.5.11"
@ -2908,6 +3219,48 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "tonic"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ac42cd97ac6bd2339af5bcabf105540e21e45636ec6fa6aae5e85d44db31be0"
dependencies = [
"async-stream",
"async-trait",
"base64 0.13.1",
"bytes",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"percent-encoding",
"pin-project",
"prost",
"prost-derive",
"tokio",
"tokio-rustls",
"tokio-stream",
"tokio-util 0.6.10",
"tower",
"tower-service",
"tracing",
"tracing-futures",
]
[[package]]
name = "tonic-build"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c695de27302f4697191dda1c7178131a8cb805463dda02864acb80fe1322fdcf"
dependencies = [
"proc-macro2",
"prost-build",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "tower" name = "tower"
version = "0.4.13" version = "0.4.13"
@ -2916,9 +3269,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-util", "futures-util",
"indexmap",
"pin-project", "pin-project",
"pin-project-lite", "pin-project-lite",
"rand",
"slab",
"tokio", "tokio",
"tokio-util 0.7.8",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"tracing", "tracing",
@ -3009,6 +3366,16 @@ dependencies = [
"valuable", "valuable",
] ]
[[package]]
name = "tracing-futures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
dependencies = [
"pin-project",
"tracing",
]
[[package]] [[package]]
name = "tracing-log" name = "tracing-log"
version = "0.1.3" version = "0.1.3"
@ -3098,6 +3465,12 @@ 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 = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "url" name = "url"
version = "2.3.1" version = "2.3.1"
@ -3300,6 +3673,27 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "webpki"
version = "0.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "which"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [
"either",
"libc",
"once_cell",
]
[[package]] [[package]]
name = "whoami" name = "whoami"
version = "1.4.0" version = "1.4.0"

View file

@ -0,0 +1,13 @@
[package]
name = "datastore-adaptor"
version = "0.1.0"
edition = "2021"
[dependencies]
async-trait = "0.1.68"
chrono = "0.4.24"
common = { path = "../../common" }
google-cloud = { version = "0.2.1", features = ["datastore"] }
serde = "1.0.163"
serde_json = "1.0.96"
tokio = { version = "1.28.1", features = ["rt-multi-thread"] }

View file

@ -0,0 +1,193 @@
use std::{collections::HashMap, env, error::Error, fmt::Display};
use async_trait::async_trait;
use chrono::{DateTime, NaiveDateTime, Utc};
use common::{
adaptor::Adaptor,
event::{Event, EventDeletion},
person::Person,
stats::Stats,
};
use google_cloud::{
authorize::ApplicationCredentials,
datastore::{Client, Filter, FromValue, IntoValue, Key, Query, Value},
error::ConvertError,
};
use tokio::sync::Mutex;
pub struct DatastoreAdaptor {
client: Mutex<Client>,
}
// Keys
const STATS_KIND: &str = "Stats";
const EVENT_KIND: &str = "Event";
const PERSON_KIND: &str = "Person";
const STATS_EVENTS_ID: &str = "eventCount";
const STATS_PEOPLE_ID: &str = "personCount";
#[async_trait]
impl Adaptor for DatastoreAdaptor {
type Error = DatastoreAdaptorError;
async fn get_stats(&self) -> Result<Stats, Self::Error> {
let mut client = self.client.lock().await;
let key = Key::new(STATS_KIND);
let event_count = client
.get(key.clone().id(STATS_EVENTS_ID))
.await?
.unwrap_or(0);
let person_count = client.get(key.id(STATS_PEOPLE_ID)).await?.unwrap_or(0);
Ok(Stats {
event_count,
person_count,
})
}
async fn increment_stat_event_count(&self) -> Result<i64, Self::Error> {
let mut client = self.client.lock().await;
let key = Key::new(STATS_KIND).id(STATS_EVENTS_ID);
let event_count = client.get(key.clone()).await?.unwrap_or(0) + 1;
client.put((key, event_count)).await?;
Ok(event_count)
}
async fn increment_stat_person_count(&self) -> Result<i64, Self::Error> {
let mut client = self.client.lock().await;
let key = Key::new(STATS_KIND).id(STATS_PEOPLE_ID);
let person_count = client.get(key.clone()).await?.unwrap_or(0) + 1;
client.put((key, person_count)).await?;
Ok(person_count)
}
async fn get_people(&self, event_id: String) -> Result<Option<Vec<Person>>, Self::Error> {
let mut client = self.client.lock().await;
// Check the event exists
if client
.get::<Value, _>(Key::new(EVENT_KIND).id(event_id.clone()))
.await?
.is_none()
{
return Ok(None);
}
Ok(Some(
client
.query(
Query::new(PERSON_KIND)
.filter(Filter::Equal("eventId".into(), event_id.into_value())),
)
.await?
.into_iter()
.filter_map(|entity| parse_into_person(entity.properties().clone()).ok())
.collect(),
))
}
async fn upsert_person(&self, event_id: String, person: Person) -> Result<Person, Self::Error> {
let mut client = self.client.lock().await;
todo!()
}
async fn get_event(&self, id: String) -> Result<Option<Event>, Self::Error> {
let mut client = self.client.lock().await;
todo!()
}
async fn create_event(&self, event: Event) -> Result<Event, Self::Error> {
let mut client = self.client.lock().await;
todo!()
}
async fn delete_event(&self, id: String) -> Result<EventDeletion, Self::Error> {
let mut client = self.client.lock().await;
todo!()
}
}
impl DatastoreAdaptor {
pub async fn new() -> Self {
let project_name = env::var("GCP_PROJECT_NAME").unwrap();
// Load credentials
let credentials: ApplicationCredentials =
serde_json::from_str(&env::var("GCP_CREDENTIALS").unwrap()).unwrap();
// Connect to datastore
let client = Client::from_credentials(project_name.clone(), credentials)
.await
.unwrap();
let client = Mutex::new(client);
println!("🎛️ Connected to datastore in project {}", project_name);
Self { client }
}
}
fn parse_into_person(value: Value) -> Result<Person, DatastoreAdaptorError> {
let person: HashMap<String, Value> = HashMap::from_value(value)?;
Ok(Person {
name: String::from_value(
person
.get("name")
.ok_or(ConvertError::MissingProperty("name".to_owned()))?
.clone(),
)?,
password_hash: person
.get("password")
.map(|p| String::from_value(p.clone()))
.transpose()?,
created_at: DateTime::from_utc(
NaiveDateTime::from_timestamp_opt(
i64::from_value(
person
.get("created")
.ok_or(ConvertError::MissingProperty("created".to_owned()))?
.clone(),
)?,
0,
)
.unwrap(),
Utc,
),
availability: Vec::from_value(
person
.get("availability")
.ok_or(ConvertError::MissingProperty("availability".to_owned()))?
.clone(),
)?,
})
}
#[derive(Debug)]
pub enum DatastoreAdaptorError {
DatastoreError(google_cloud::error::Error),
}
impl Display for DatastoreAdaptorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DatastoreAdaptorError::DatastoreError(e) => write!(f, "Datastore Error: {}", e),
}
}
}
impl Error for DatastoreAdaptorError {}
impl From<google_cloud::error::Error> for DatastoreAdaptorError {
fn from(value: google_cloud::error::Error) -> Self {
Self::DatastoreError(value)
}
}
impl From<google_cloud::error::ConvertError> for DatastoreAdaptorError {
fn from(value: google_cloud::error::ConvertError) -> Self {
Self::DatastoreError(google_cloud::error::Error::Convert(value))
}
}

View file

@ -33,23 +33,23 @@ impl Adaptor for SqlAdaptor {
async fn get_stats(&self) -> Result<Stats, Self::Error> { async fn get_stats(&self) -> Result<Stats, Self::Error> {
let stats_row = get_stats_row(&self.db).await?; let stats_row = get_stats_row(&self.db).await?;
Ok(Stats { Ok(Stats {
event_count: stats_row.event_count.unwrap(), event_count: stats_row.event_count.unwrap() as i64,
person_count: stats_row.person_count.unwrap(), person_count: stats_row.person_count.unwrap() as i64,
}) })
} }
async fn increment_stat_event_count(&self) -> Result<i32, Self::Error> { async fn increment_stat_event_count(&self) -> Result<i64, Self::Error> {
let mut current_stats = get_stats_row(&self.db).await?; let mut current_stats = get_stats_row(&self.db).await?;
current_stats.event_count = Set(current_stats.event_count.unwrap() + 1); current_stats.event_count = Set(current_stats.event_count.unwrap() + 1);
Ok(current_stats.save(&self.db).await?.event_count.unwrap()) Ok(current_stats.save(&self.db).await?.event_count.unwrap() as i64)
} }
async fn increment_stat_person_count(&self) -> Result<i32, Self::Error> { async fn increment_stat_person_count(&self) -> Result<i64, Self::Error> {
let mut current_stats = get_stats_row(&self.db).await?; let mut current_stats = get_stats_row(&self.db).await?;
current_stats.person_count = Set(current_stats.person_count.unwrap() + 1); current_stats.person_count = Set(current_stats.person_count.unwrap() + 1);
Ok(current_stats.save(&self.db).await?.person_count.unwrap()) Ok(current_stats.save(&self.db).await?.person_count.unwrap() as i64)
} }
async fn get_people(&self, event_id: String) -> Result<Option<Vec<Person>>, Self::Error> { async fn get_people(&self, event_id: String) -> Result<Option<Vec<Person>>, Self::Error> {

View file

@ -15,8 +15,8 @@ pub trait Adaptor: Send + Sync {
type Error: Error; type Error: Error;
async fn get_stats(&self) -> Result<Stats, Self::Error>; async fn get_stats(&self) -> Result<Stats, Self::Error>;
async fn increment_stat_event_count(&self) -> Result<i32, Self::Error>; async fn increment_stat_event_count(&self) -> Result<i64, Self::Error>;
async fn increment_stat_person_count(&self) -> Result<i32, Self::Error>; async fn increment_stat_person_count(&self) -> Result<i64, Self::Error>;
async fn get_people(&self, event_id: String) -> Result<Option<Vec<Person>>, Self::Error>; async fn get_people(&self, event_id: String) -> Result<Option<Vec<Person>>, Self::Error>;
async fn upsert_person(&self, event_id: String, person: Person) -> Result<Person, Self::Error>; async fn upsert_person(&self, event_id: String, person: Person) -> Result<Person, Self::Error>;

View file

@ -1,4 +1,4 @@
pub struct Stats { pub struct Stats {
pub event_count: i32, pub event_count: i64,
pub person_count: i32, pub person_count: i64,
} }

View file

@ -37,8 +37,8 @@ impl From<Event> for EventResponse {
#[derive(Serialize, ToSchema)] #[derive(Serialize, ToSchema)]
pub struct StatsResponse { pub struct StatsResponse {
pub event_count: i32, pub event_count: i64,
pub person_count: i32, pub person_count: i64,
pub version: String, pub version: String,
} }