mirror of
https://github.com/LukeMathWalker/zero-to-production.git
synced 2024-12-18 05:56:35 +00:00
Update sqlx to 0.7
This commit is contained in:
parent
7cf5f86ba4
commit
09d928a13a
19 changed files with 1132 additions and 1005 deletions
4
.github/workflows/general.yml
vendored
4
.github/workflows/general.yml
vendored
|
@ -14,7 +14,7 @@ on:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
SQLX_VERSION: 0.6.2
|
SQLX_VERSION: 0.7.1
|
||||||
SQLX_FEATURES: "rustls,postgres"
|
SQLX_FEATURES: "rustls,postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -53,7 +53,7 @@ jobs:
|
||||||
SKIP_DOCKER=true ./scripts/init_db.sh
|
SKIP_DOCKER=true ./scripts/init_db.sh
|
||||||
- name: Check sqlx-data.json is up-to-date
|
- name: Check sqlx-data.json is up-to-date
|
||||||
run: |
|
run: |
|
||||||
cargo sqlx prepare --check -- --bin zero2prod
|
cargo sqlx prepare --workspace --check
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test
|
run: cargo test
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n UPDATE users\n SET password_hash = $1\n WHERE user_id = $2\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "2880480077b654e38b63f423ab40680697a500ffe1af1d1b39108910594b581b"
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT username\n FROM users\n WHERE user_id = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "username",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "33b11051e779866db9aeb86d28a59db07a94323ffdc59a5a2c1da694ebe9a65f"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n INSERT INTO subscriptions (id, email, name, subscribed_at, status)\n VALUES ($1, $2, $3, $4, 'pending_confirmation')\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Text",
|
||||||
|
"Text",
|
||||||
|
"Timestamptz"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "51c9c995452d3359e3da7e2f2ff8a6e68690f740a36d2a32ec7c40b08931ebdb"
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n INSERT INTO subscription_tokens (subscription_token, subscriber_id)\n VALUES ($1, $2)\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "753c8ecfac0ea7d052e60cb582e3b3ebac5e50eb133152712ca18ab5d5e202f3"
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT email\n FROM subscriptions\n WHERE status = 'confirmed'\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "email",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "7b57e2776a245ba1602f638121550485e2219a6ccaaa62b5ec3e4683e33a3b5f"
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "UPDATE subscriptions SET status = 'confirmed' WHERE id = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "a71a1932b894572106460ca2e34a63dc0cb8c1ba7a70547add1cddbb68133c2b"
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT user_id, password_hash\n FROM users\n WHERE username = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "user_id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "password_hash",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "acf1b96c82ddf18db02e71a0e297c822b46f10add52c54649cf599b883165e58"
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT subscriber_id FROM subscription_tokens WHERE subscription_token = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "subscriber_id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "ad120337ee606be7b8d87238e2bb765d0da8ee61b1a3bc142414c4305ec5e17f"
|
||||||
|
}
|
1575
Cargo.lock
generated
1575
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ actix-web = "4"
|
||||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||||
serde = "1.0.115"
|
serde = "1.0.115"
|
||||||
config = { version = "0.13", default-features = false, features = ["yaml"] }
|
config = { version = "0.13", default-features = false, features = ["yaml"] }
|
||||||
sqlx = { version = "0.6", default-features = false, features = ["runtime-actix-rustls", "macros", "postgres", "uuid", "chrono", "migrate", "offline"] }
|
sqlx = { version = "0.7", default-features = false, features = ["runtime-tokio-rustls", "macros", "postgres", "uuid", "chrono", "migrate"] }
|
||||||
uuid = { version = "1", features = ["v4", "serde"] }
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
chrono = { version = "0.4.22", default-features = false, features = ["clock"] }
|
chrono = { version = "0.4.22", default-features = false, features = ["clock"] }
|
||||||
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls", "cookies"] }
|
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls", "cookies"] }
|
||||||
|
|
|
@ -10,7 +10,7 @@ fi
|
||||||
if ! [ -x "$(command -v sqlx)" ]; then
|
if ! [ -x "$(command -v sqlx)" ]; then
|
||||||
echo >&2 "Error: sqlx is not installed."
|
echo >&2 "Error: sqlx is not installed."
|
||||||
echo >&2 "Use:"
|
echo >&2 "Use:"
|
||||||
echo >&2 " cargo install --version='~0.6' sqlx-cli --no-default-features --features rustls,postgres"
|
echo >&2 " cargo install --version='~0.7' sqlx-cli --no-default-features --features rustls,postgres"
|
||||||
echo >&2 "to install it."
|
echo >&2 "to install it."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
326
sqlx-data.json
326
sqlx-data.json
|
@ -1,326 +0,0 @@
|
||||||
{
|
|
||||||
"db": "PostgreSQL",
|
|
||||||
"06f83a51e9d2ca842dc0d6947ad39d9be966636700de58d404d8e1471a260c9a": {
|
|
||||||
"query": "\n SELECT newsletter_issue_id, subscriber_email\n FROM issue_delivery_queue\n FOR UPDATE\n SKIP LOCKED\n LIMIT 1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "newsletter_issue_id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "subscriber_email",
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"0b93f6f4f1bc59e7ee597ef6df52bbee1233d98e0a4cf53e29c153ccdae0537b": {
|
|
||||||
"query": "\n INSERT INTO newsletter_issues (\n newsletter_issue_id, \n title, \n text_content, \n html_content,\n published_at\n )\n VALUES ($1, $2, $3, $4, now())\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Text",
|
|
||||||
"Text",
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"1bb5d1c15161a276262535134c306bc392dda0fa1d7bb7deddcd544583a19fc8": {
|
|
||||||
"query": "\n INSERT INTO idempotency (\n user_id, \n idempotency_key,\n created_at\n ) \n VALUES ($1, $2, now()) \n ON CONFLICT DO NOTHING\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"21f0f4c2ae0e88b99684823b83ce6126c218cec3badc8126492aab8fc7042109": {
|
|
||||||
"query": "\n UPDATE idempotency\n SET \n response_status_code = $3, \n response_headers = $4,\n response_body = $5\n WHERE\n user_id = $1 AND\n idempotency_key = $2\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Text",
|
|
||||||
"Int2",
|
|
||||||
{
|
|
||||||
"Custom": {
|
|
||||||
"name": "_header_pair",
|
|
||||||
"kind": {
|
|
||||||
"Array": {
|
|
||||||
"Custom": {
|
|
||||||
"name": "header_pair",
|
|
||||||
"kind": {
|
|
||||||
"Composite": [
|
|
||||||
[
|
|
||||||
"name",
|
|
||||||
"Text"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"value",
|
|
||||||
"Bytea"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Bytea"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"2880480077b654e38b63f423ab40680697a500ffe1af1d1b39108910594b581b": {
|
|
||||||
"query": "\n UPDATE users\n SET password_hash = $1\n WHERE user_id = $2\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text",
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"33b11051e779866db9aeb86d28a59db07a94323ffdc59a5a2c1da694ebe9a65f": {
|
|
||||||
"query": "\n SELECT username\n FROM users\n WHERE user_id = $1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "username",
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"38d1a12165ad4f50d8fbd4fc92376d9cc243dcc344c67b37f7fef13c6589e1eb": {
|
|
||||||
"query": "\n SELECT title, text_content, html_content\n FROM newsletter_issues\n WHERE\n newsletter_issue_id = $1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "title",
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "text_content",
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "html_content",
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"51c9c995452d3359e3da7e2f2ff8a6e68690f740a36d2a32ec7c40b08931ebdb": {
|
|
||||||
"query": "\n INSERT INTO subscriptions (id, email, name, subscribed_at, status)\n VALUES ($1, $2, $3, $4, 'pending_confirmation')\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Text",
|
|
||||||
"Text",
|
|
||||||
"Timestamptz"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"753c8ecfac0ea7d052e60cb582e3b3ebac5e50eb133152712ca18ab5d5e202f3": {
|
|
||||||
"query": "\n INSERT INTO subscription_tokens (subscription_token, subscriber_id)\n VALUES ($1, $2)\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text",
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"9f103f7d6dfa569bafce4546e6e610f3d31b95fe81f96ea72575b27ddfea796e": {
|
|
||||||
"query": "\n SELECT \n response_status_code as \"response_status_code!\", \n response_headers as \"response_headers!: Vec<HeaderPairRecord>\",\n response_body as \"response_body!\"\n FROM idempotency\n WHERE \n user_id = $1 AND\n idempotency_key = $2\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "response_status_code!",
|
|
||||||
"type_info": "Int2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "response_headers!: Vec<HeaderPairRecord>",
|
|
||||||
"type_info": {
|
|
||||||
"Custom": {
|
|
||||||
"name": "_header_pair",
|
|
||||||
"kind": {
|
|
||||||
"Array": {
|
|
||||||
"Custom": {
|
|
||||||
"name": "header_pair",
|
|
||||||
"kind": {
|
|
||||||
"Composite": [
|
|
||||||
[
|
|
||||||
"name",
|
|
||||||
"Text"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"value",
|
|
||||||
"Bytea"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "response_body!",
|
|
||||||
"type_info": "Bytea"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"a71a1932b894572106460ca2e34a63dc0cb8c1ba7a70547add1cddbb68133c2b": {
|
|
||||||
"query": "UPDATE subscriptions SET status = 'confirmed' WHERE id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"aa682ff5c6485c4faa8168322413294a282ddcc0ef4e38ca3980e6fc7c00c87c": {
|
|
||||||
"query": "\n INSERT INTO issue_delivery_queue (\n newsletter_issue_id, \n subscriber_email\n )\n SELECT $1, email\n FROM subscriptions\n WHERE status = 'confirmed'\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"acf1b96c82ddf18db02e71a0e297c822b46f10add52c54649cf599b883165e58": {
|
|
||||||
"query": "\n SELECT user_id, password_hash\n FROM users\n WHERE username = $1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "user_id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "password_hash",
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ad120337ee606be7b8d87238e2bb765d0da8ee61b1a3bc142414c4305ec5e17f": {
|
|
||||||
"query": "SELECT subscriber_id FROM subscription_tokens WHERE subscription_token = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "subscriber_id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c00b32b331e0444b4bb0cd823b71a8c7ed3a3c8f2b8db3b12c6fbc434aa4d34b": {
|
|
||||||
"query": "\n DELETE FROM issue_delivery_queue\n WHERE \n newsletter_issue_id = $1 AND\n subscriber_email = $2 \n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@ use crate::email_client::EmailClient;
|
||||||
use secrecy::{ExposeSecret, Secret};
|
use secrecy::{ExposeSecret, Secret};
|
||||||
use serde_aux::field_attributes::deserialize_number_from_string;
|
use serde_aux::field_attributes::deserialize_number_from_string;
|
||||||
use sqlx::postgres::{PgConnectOptions, PgSslMode};
|
use sqlx::postgres::{PgConnectOptions, PgSslMode};
|
||||||
use sqlx::ConnectOptions;
|
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Clone)]
|
#[derive(serde::Deserialize, Clone)]
|
||||||
|
@ -50,9 +49,7 @@ impl DatabaseSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_db(&self) -> PgConnectOptions {
|
pub fn with_db(&self) -> PgConnectOptions {
|
||||||
let mut options = self.without_db().database(&self.database_name);
|
self.without_db().database(&self.database_name)
|
||||||
options.log_statements(tracing::log::LevelFilter::Trace);
|
|
||||||
options
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::body::to_bytes;
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
use sqlx::postgres::PgHasArrayType;
|
use sqlx::postgres::PgHasArrayType;
|
||||||
use sqlx::PgPool;
|
use sqlx::{Executor, PgPool};
|
||||||
use sqlx::{Postgres, Transaction};
|
use sqlx::{Postgres, Transaction};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -71,8 +71,9 @@ pub async fn save_response(
|
||||||
}
|
}
|
||||||
h
|
h
|
||||||
};
|
};
|
||||||
sqlx::query_unchecked!(
|
transaction
|
||||||
r#"
|
.execute(sqlx::query_unchecked!(
|
||||||
|
r#"
|
||||||
UPDATE idempotency
|
UPDATE idempotency
|
||||||
SET
|
SET
|
||||||
response_status_code = $3,
|
response_status_code = $3,
|
||||||
|
@ -82,14 +83,13 @@ pub async fn save_response(
|
||||||
user_id = $1 AND
|
user_id = $1 AND
|
||||||
idempotency_key = $2
|
idempotency_key = $2
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
user_id,
|
||||||
idempotency_key.as_ref(),
|
idempotency_key.as_ref(),
|
||||||
status_code,
|
status_code,
|
||||||
headers,
|
headers,
|
||||||
body.as_ref()
|
body.as_ref()
|
||||||
)
|
))
|
||||||
.execute(&mut transaction)
|
.await?;
|
||||||
.await?;
|
|
||||||
transaction.commit().await?;
|
transaction.commit().await?;
|
||||||
|
|
||||||
let http_response = response_head.set_body(body).map_into_boxed_body();
|
let http_response = response_head.set_body(body).map_into_boxed_body();
|
||||||
|
@ -109,7 +109,7 @@ pub async fn try_processing(
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<NextAction, anyhow::Error> {
|
) -> Result<NextAction, anyhow::Error> {
|
||||||
let mut transaction = pool.begin().await?;
|
let mut transaction = pool.begin().await?;
|
||||||
let n_inserted_rows = sqlx::query!(
|
let query = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO idempotency (
|
INSERT INTO idempotency (
|
||||||
user_id,
|
user_id,
|
||||||
|
@ -121,10 +121,8 @@ pub async fn try_processing(
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
user_id,
|
||||||
idempotency_key.as_ref()
|
idempotency_key.as_ref()
|
||||||
)
|
);
|
||||||
.execute(&mut transaction)
|
let n_inserted_rows = transaction.execute(query).await?.rows_affected();
|
||||||
.await?
|
|
||||||
.rows_affected();
|
|
||||||
if n_inserted_rows > 0 {
|
if n_inserted_rows > 0 {
|
||||||
Ok(NextAction::StartProcessing(transaction))
|
Ok(NextAction::StartProcessing(transaction))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -99,7 +99,7 @@ async fn dequeue_task(
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_optional(&mut transaction)
|
.fetch_optional(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
if let Some(r) = r {
|
if let Some(r) = r {
|
||||||
Ok(Some((
|
Ok(Some((
|
||||||
|
@ -128,7 +128,7 @@ async fn delete_task(
|
||||||
issue_id,
|
issue_id,
|
||||||
email
|
email
|
||||||
)
|
)
|
||||||
.execute(&mut transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
transaction.commit().await?;
|
transaction.commit().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::utils::{e500, see_other};
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use actix_web_flash_messages::FlashMessage;
|
use actix_web_flash_messages::FlashMessage;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use sqlx::{PgPool, Postgres, Transaction};
|
use sqlx::{Executor, PgPool, Postgres, Transaction};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
|
@ -75,7 +75,7 @@ async fn insert_newsletter_issue(
|
||||||
html_content: &str,
|
html_content: &str,
|
||||||
) -> Result<Uuid, sqlx::Error> {
|
) -> Result<Uuid, sqlx::Error> {
|
||||||
let newsletter_issue_id = Uuid::new_v4();
|
let newsletter_issue_id = Uuid::new_v4();
|
||||||
sqlx::query!(
|
let query = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO newsletter_issues (
|
INSERT INTO newsletter_issues (
|
||||||
newsletter_issue_id,
|
newsletter_issue_id,
|
||||||
|
@ -90,9 +90,8 @@ async fn insert_newsletter_issue(
|
||||||
title,
|
title,
|
||||||
text_content,
|
text_content,
|
||||||
html_content
|
html_content
|
||||||
)
|
);
|
||||||
.execute(transaction)
|
transaction.execute(query).await?;
|
||||||
.await?;
|
|
||||||
Ok(newsletter_issue_id)
|
Ok(newsletter_issue_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ async fn enqueue_delivery_tasks(
|
||||||
transaction: &mut Transaction<'_, Postgres>,
|
transaction: &mut Transaction<'_, Postgres>,
|
||||||
newsletter_issue_id: Uuid,
|
newsletter_issue_id: Uuid,
|
||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
let query = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO issue_delivery_queue (
|
INSERT INTO issue_delivery_queue (
|
||||||
newsletter_issue_id,
|
newsletter_issue_id,
|
||||||
|
@ -112,8 +111,7 @@ async fn enqueue_delivery_tasks(
|
||||||
WHERE status = 'confirmed'
|
WHERE status = 'confirmed'
|
||||||
"#,
|
"#,
|
||||||
newsletter_issue_id,
|
newsletter_issue_id,
|
||||||
)
|
);
|
||||||
.execute(transaction)
|
transaction.execute(query).await?;
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use anyhow::Context;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use rand::distributions::Alphanumeric;
|
use rand::distributions::Alphanumeric;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use sqlx::{PgPool, Postgres, Transaction};
|
use sqlx::{Executor, PgPool, Postgres, Transaction};
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ pub async fn insert_subscriber(
|
||||||
new_subscriber: &NewSubscriber,
|
new_subscriber: &NewSubscriber,
|
||||||
) -> Result<Uuid, sqlx::Error> {
|
) -> Result<Uuid, sqlx::Error> {
|
||||||
let subscriber_id = Uuid::new_v4();
|
let subscriber_id = Uuid::new_v4();
|
||||||
sqlx::query!(
|
let query = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO subscriptions (id, email, name, subscribed_at, status)
|
INSERT INTO subscriptions (id, email, name, subscribed_at, status)
|
||||||
VALUES ($1, $2, $3, $4, 'pending_confirmation')
|
VALUES ($1, $2, $3, $4, 'pending_confirmation')
|
||||||
|
@ -144,9 +144,8 @@ pub async fn insert_subscriber(
|
||||||
new_subscriber.email.as_ref(),
|
new_subscriber.email.as_ref(),
|
||||||
new_subscriber.name.as_ref(),
|
new_subscriber.name.as_ref(),
|
||||||
Utc::now()
|
Utc::now()
|
||||||
)
|
);
|
||||||
.execute(transaction)
|
transaction.execute(query).await?;
|
||||||
.await?;
|
|
||||||
Ok(subscriber_id)
|
Ok(subscriber_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,17 +158,15 @@ pub async fn store_token(
|
||||||
subscriber_id: Uuid,
|
subscriber_id: Uuid,
|
||||||
subscription_token: &str,
|
subscription_token: &str,
|
||||||
) -> Result<(), StoreTokenError> {
|
) -> Result<(), StoreTokenError> {
|
||||||
sqlx::query!(
|
let query = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO subscription_tokens (subscription_token, subscriber_id)
|
INSERT INTO subscription_tokens (subscription_token, subscriber_id)
|
||||||
VALUES ($1, $2)
|
VALUES ($1, $2)
|
||||||
"#,
|
"#,
|
||||||
subscription_token,
|
subscription_token,
|
||||||
subscriber_id
|
subscriber_id
|
||||||
)
|
);
|
||||||
.execute(transaction)
|
transaction.execute(query).await.map_err(StoreTokenError)?;
|
||||||
.await
|
|
||||||
.map_err(StoreTokenError)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use actix_web::{web, App, HttpServer};
|
||||||
use actix_web_flash_messages::storage::CookieMessageStore;
|
use actix_web_flash_messages::storage::CookieMessageStore;
|
||||||
use actix_web_flash_messages::FlashMessagesFramework;
|
use actix_web_flash_messages::FlashMessagesFramework;
|
||||||
use actix_web_lab::middleware::from_fn;
|
use actix_web_lab::middleware::from_fn;
|
||||||
use secrecy::{ExposeSecret, Secret};
|
use secrecy::{Secret, ExposeSecret};
|
||||||
use sqlx::postgres::PgPoolOptions;
|
use sqlx::postgres::PgPoolOptions;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
|
@ -60,7 +60,6 @@ impl Application {
|
||||||
|
|
||||||
pub fn get_connection_pool(configuration: &DatabaseSettings) -> PgPool {
|
pub fn get_connection_pool(configuration: &DatabaseSettings) -> PgPool {
|
||||||
PgPoolOptions::new()
|
PgPoolOptions::new()
|
||||||
.acquire_timeout(std::time::Duration::from_secs(2))
|
|
||||||
.connect_lazy_with(configuration.with_db())
|
.connect_lazy_with(configuration.with_db())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue