Use a SQL transaction.

This commit is contained in:
LukeMathWalker 2021-03-13 10:08:54 +00:00
parent b21e9cc99c
commit c58675a5a0

View file

@ -5,7 +5,7 @@ use actix_web::{web, HttpResponse};
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; use sqlx::{PgPool, Transaction, Postgres};
use std::convert::TryInto; use std::convert::TryInto;
use uuid::Uuid; use uuid::Uuid;
@ -43,14 +43,16 @@ pub async fn subscribe(
.0 .0
.try_into() .try_into()
.map_err(|_| HttpResponse::BadRequest().finish())?; .map_err(|_| HttpResponse::BadRequest().finish())?;
let subscriber_id = insert_subscriber(&pool, &new_subscriber) let mut transaction = pool.begin().await.map_err(|_| HttpResponse::InternalServerError().finish())?;
let subscriber_id = insert_subscriber(&mut transaction, &new_subscriber)
.await .await
.map_err(|_| HttpResponse::InternalServerError().finish())?; .map_err(|_| HttpResponse::InternalServerError().finish())?;
// We are swallowing the error for the time being. // We are swallowing the error for the time being.
let subscription_token = generate_subscription_token(); let subscription_token = generate_subscription_token();
store_token(&pool, subscriber_id, &subscription_token) store_token(&mut transaction, subscriber_id, &subscription_token)
.await .await
.map_err(|_| HttpResponse::InternalServerError().finish())?; .map_err(|_| HttpResponse::InternalServerError().finish())?;
transaction.commit().await.map_err(|_| HttpResponse::InternalServerError().finish())?;
let _ = send_confirmation_email( let _ = send_confirmation_email(
&email_client, &email_client,
new_subscriber, new_subscriber,
@ -98,10 +100,10 @@ pub async fn send_confirmation_email(
#[tracing::instrument( #[tracing::instrument(
name = "Saving new subscriber details in the database", name = "Saving new subscriber details in the database",
skip(new_subscriber, pool) skip(new_subscriber, transaction)
)] )]
pub async fn insert_subscriber( pub async fn insert_subscriber(
pool: &PgPool, transaction: &mut Transaction<'_, Postgres>,
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();
@ -115,7 +117,7 @@ pub async fn insert_subscriber(
new_subscriber.name.as_ref(), new_subscriber.name.as_ref(),
Utc::now() Utc::now()
) )
.execute(pool) .execute(transaction)
.await .await
.map_err(|e| { .map_err(|e| {
tracing::error!("Failed to execute query: {:?}", e); tracing::error!("Failed to execute query: {:?}", e);
@ -126,10 +128,10 @@ pub async fn insert_subscriber(
#[tracing::instrument( #[tracing::instrument(
name = "Store subscription token in the database", name = "Store subscription token in the database",
skip(subscription_token, pool) skip(subscription_token, transaction)
)] )]
pub async fn store_token( pub async fn store_token(
pool: &PgPool, transaction: &mut Transaction<'_, Postgres>,
subscriber_id: Uuid, subscriber_id: Uuid,
subscription_token: &str, subscription_token: &str,
) -> Result<(), sqlx::Error> { ) -> Result<(), sqlx::Error> {
@ -141,7 +143,7 @@ pub async fn store_token(
subscription_token, subscription_token,
subscriber_id subscriber_id
) )
.execute(pool) .execute(transaction)
.await .await
.map_err(|e| { .map_err(|e| {
tracing::error!("Failed to execute query: {:?}", e); tracing::error!("Failed to execute query: {:?}", e);