Implement idempotency for insertion
This commit is contained in:
parent
e15c30fe06
commit
ea0c26a151
1 changed files with 94 additions and 38 deletions
|
|
@ -5,7 +5,11 @@ use uuid::Uuid;
|
||||||
use crate::votes::model::BestSlugs;
|
use crate::votes::model::BestSlugs;
|
||||||
|
|
||||||
pub async fn insert_new_vote(slug: &str, voter_id: &Uuid, db: &PgPool) -> Result<()> {
|
pub async fn insert_new_vote(slug: &str, voter_id: &Uuid, db: &PgPool) -> Result<()> {
|
||||||
query("insert into votes (slug, voter_id) values ($1, $2)")
|
query(
|
||||||
|
r#"insert into votes (slug, voter_id)
|
||||||
|
values ($1, $2)
|
||||||
|
on conflict (slug, voter_id) do nothing"#,
|
||||||
|
)
|
||||||
.bind(slug)
|
.bind(slug)
|
||||||
.bind(voter_id)
|
.bind(voter_id)
|
||||||
.execute(db)
|
.execute(db)
|
||||||
|
|
@ -56,26 +60,14 @@ mod postgres_tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
test_helpers::db::test_pool,
|
test_helpers::db::test_pool,
|
||||||
votes::repository::{delete_vote, get_top_n_slugs, get_vote_count_for_slug, insert_new_vote},
|
votes::repository::{
|
||||||
|
delete_vote, get_top_n_slugs, get_vote_count_for_slug, insert_new_vote,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn test_votes() -> [(&'static str, Uuid); 9] {
|
async fn cleanup(db: &PgPool, votes: &[(String, Uuid)]) {
|
||||||
[
|
for (slug, voter_id) in votes {
|
||||||
("blog_post1", Uuid::from_u128(0x1)),
|
delete_vote(slug, voter_id, db).await.unwrap()
|
||||||
("blog_post1", Uuid::from_u128(0x2)),
|
|
||||||
("blog_post2", Uuid::from_u128(0x3)),
|
|
||||||
("blog_post2", Uuid::from_u128(0x4)),
|
|
||||||
("blog_post3", Uuid::from_u128(0x5)),
|
|
||||||
("blog_post3", Uuid::from_u128(0x6)),
|
|
||||||
("blog_post1", Uuid::from_u128(0x7)),
|
|
||||||
("blog_post1", Uuid::from_u128(0x8)),
|
|
||||||
("blog_post3", Uuid::from_u128(0x9)),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn cleanup(db: &PgPool) {
|
|
||||||
for (slug, voter_id) in test_votes() {
|
|
||||||
delete_vote(slug, &voter_id, db).await.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,8 +75,18 @@ mod postgres_tests {
|
||||||
#[ignore]
|
#[ignore]
|
||||||
pub async fn postgres_tests() {
|
pub async fn postgres_tests() {
|
||||||
let db = test_pool().await;
|
let db = test_pool().await;
|
||||||
cleanup(&db).await;
|
let votes = vec![
|
||||||
let votes = test_votes();
|
("postgres_tests_blog_post1".to_string(), Uuid::from_u128(0x1)),
|
||||||
|
("postgres_tests_blog_post1".to_string(), Uuid::from_u128(0x2)),
|
||||||
|
("postgres_tests_blog_post2".to_string(), Uuid::from_u128(0x3)),
|
||||||
|
("postgres_tests_blog_post2".to_string(), Uuid::from_u128(0x4)),
|
||||||
|
("postgres_tests_blog_post3".to_string(), Uuid::from_u128(0x5)),
|
||||||
|
("postgres_tests_blog_post3".to_string(), Uuid::from_u128(0x6)),
|
||||||
|
("postgres_tests_blog_post1".to_string(), Uuid::from_u128(0x7)),
|
||||||
|
("postgres_tests_blog_post1".to_string(), Uuid::from_u128(0x8)),
|
||||||
|
("postgres_tests_blog_post3".to_string(), Uuid::from_u128(0x9)),
|
||||||
|
];
|
||||||
|
cleanup(&db, &votes).await;
|
||||||
|
|
||||||
for (slug, voter_id) in votes.iter() {
|
for (slug, voter_id) in votes.iter() {
|
||||||
insert_new_vote(slug, voter_id, &db)
|
insert_new_vote(slug, voter_id, &db)
|
||||||
|
|
@ -92,25 +94,79 @@ mod postgres_tests {
|
||||||
.expect("Insertions to db failed");
|
.expect("Insertions to db failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(get_vote_count_for_slug("blog_post1", &db).await.unwrap(), 4);
|
assert_eq!(
|
||||||
assert_eq!(get_vote_count_for_slug("blog_post2", &db).await.unwrap(), 2);
|
get_vote_count_for_slug("postgres_tests_blog_post1", &db)
|
||||||
assert_eq!(get_vote_count_for_slug("blog_post3", &db).await.unwrap(), 3);
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
4
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_vote_count_for_slug("postgres_tests_blog_post2", &db)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_vote_count_for_slug("postgres_tests_blog_post3", &db)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
3
|
||||||
|
);
|
||||||
|
|
||||||
let top_2 = get_top_n_slugs(2, &db).await.unwrap();
|
let top_2 = get_top_n_slugs(2, &db).await.unwrap();
|
||||||
assert_eq!(top_2[0].slug, "blog_post1");
|
assert_eq!(top_2[0].slug, "postgres_tests_blog_post1");
|
||||||
assert_eq!(top_2[1].slug, "blog_post3");
|
assert_eq!(top_2[1].slug, "postgres_tests_blog_post3");
|
||||||
|
|
||||||
delete_vote(votes[4].0, &votes[4].1, &db).await.unwrap();
|
delete_vote(&votes[4].0, &votes[4].1, &db).await.unwrap();
|
||||||
delete_vote(votes[5].0, &votes[5].1, &db).await.unwrap();
|
delete_vote(&votes[5].0, &votes[5].1, &db).await.unwrap();
|
||||||
|
|
||||||
assert_eq!(get_vote_count_for_slug("blog_post1", &db).await.unwrap(), 4);
|
assert_eq!(
|
||||||
assert_eq!(get_vote_count_for_slug("blog_post2", &db).await.unwrap(), 2);
|
get_vote_count_for_slug("postgres_tests_blog_post1", &db)
|
||||||
assert_eq!(get_vote_count_for_slug("blog_post3", &db).await.unwrap(), 1);
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
4
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_vote_count_for_slug("postgres_tests_blog_post2", &db)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_vote_count_for_slug("postgres_tests_blog_post3", &db)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
let top_2 = get_top_n_slugs(2, &db).await.unwrap();
|
let top_2 = get_top_n_slugs(2, &db).await.unwrap();
|
||||||
assert_eq!(top_2[0].slug, "blog_post1");
|
assert_eq!(top_2[0].slug, "postgres_tests_blog_post1");
|
||||||
assert_eq!(top_2[1].slug, "blog_post2");
|
assert_eq!(top_2[1].slug, "postgres_tests_blog_post2");
|
||||||
|
|
||||||
cleanup(&db).await;
|
cleanup(&db, &votes).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[ignore]
|
||||||
|
pub async fn insert_idempotency_test() {
|
||||||
|
let db = test_pool().await;
|
||||||
|
let votes = vec![(
|
||||||
|
"insert_idempotency_test_blog_post1".to_string(),
|
||||||
|
Uuid::from_u128(0x1),
|
||||||
|
)];
|
||||||
|
cleanup(&db, &votes).await;
|
||||||
|
|
||||||
|
insert_new_vote(&votes[0].0, &votes[0].1, &db).await.unwrap();
|
||||||
|
insert_new_vote(&votes[0].0, &votes[0].1, &db).await.unwrap();
|
||||||
|
insert_new_vote(&votes[0].0, &votes[0].1, &db).await.unwrap();
|
||||||
|
insert_new_vote(&votes[0].0, &votes[0].1, &db).await.unwrap();
|
||||||
|
insert_new_vote(&votes[0].0, &votes[0].1, &db).await.unwrap();
|
||||||
|
insert_new_vote(&votes[0].0, &votes[0].1, &db).await.unwrap();
|
||||||
|
|
||||||
|
let votes_count = get_vote_count_for_slug(&votes[0].0, &db).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(votes_count, 1);
|
||||||
|
|
||||||
|
cleanup(&db, &votes).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue