Skip to content

Commit

Permalink
feat(plus): user subscription transitions (#415)
Browse files Browse the repository at this point in the history
Record user subscription changes into pg table.
  • Loading branch information
argl authored Feb 19, 2024
1 parent 18d8fda commit 604b0e7
Show file tree
Hide file tree
Showing 23 changed files with 349 additions and 43 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 17 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,20 @@ actix-session = { version = "0.8", features = ["cookie-session"] }
actix-web-httpauth = "0.8"
actix-web-lab = "0.19"

diesel = { version = "2", features = ["postgres", "uuid", "r2d2", "chrono", "serde_json"] }
diesel = { version = "2", features = [
"postgres",
"uuid",
"r2d2",
"chrono",
"serde_json",
] }
diesel_migrations = "2"
diesel-derive-enum = { version = "2", features = ["postgres"] }
pgvector = { version = "0.2", features = ["sqlx"] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres"], default-features = false }
sqlx = { version = "0.7", features = [
"runtime-tokio-rustls",
"postgres",
], default-features = false }

elasticsearch = "7.17.7-alpha.1"
harsh = "0.2"
Expand All @@ -43,15 +52,19 @@ jsonwebtoken = "8"

serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_with = { version = "3", features = ["base64"]}
serde_with = { version = "3", features = ["base64"] }
serde_urlencoded = "0.7"
form_urlencoded = "1"
serde_path_to_error = "0.1"
percent-encoding = "2"

config = "0.13"
hostname = "0.3"
slog = { version = "2", features = ["max_level_trace", "release_max_level_info", "dynamic-keys"] }
slog = { version = "2", features = [
"max_level_trace",
"release_max_level_info",
"dynamic-keys",
] }
slog-async = "2"
slog-envlogger = "2"
slog-mozlog-json = "0.1"
Expand Down Expand Up @@ -90,4 +103,3 @@ sha2 = "0.10"
stubr = "0.6"
stubr-attributes = "0.6"
assert-json-diff = "2"
tokio = { version = "1", features = ["io-util"] }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE user_subscription_transitions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE user_subscription_transitions (
id BIGSERIAL PRIMARY KEY,
user_id BIGSERIAL REFERENCES users (id) ON DELETE CASCADE,
old_subscription_type subscription_type NOT NULL,
new_subscription_type subscription_type NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
20 changes: 18 additions & 2 deletions src/db/fxa_webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use diesel::prelude::*;
use diesel::ExpressionMethods;
use serde_json::json;

use super::model::SubscriptionChangeInsert;
use super::types::{FxaEventStatus, Subscription};

pub fn log_failed_webhook_event(
Expand Down Expand Up @@ -191,7 +192,7 @@ pub async fn update_subscription_state_from_webhook(
};
if subscription == Subscription::Core {
// drop permissions
if let Some(basket) = &**basket {
if let Some(basket) = basket.get_ref() {
if let Err(e) = newsletter::unsubscribe(&mut conn, &user, basket).await {
error!("error unsubscribing user: {}", e);
}
Expand All @@ -217,7 +218,7 @@ pub async fn update_subscription_state_from_webhook(
)
.set(schema::webhook_events::status.eq(FxaEventStatus::Processed))
.execute(&mut conn)?;
return Ok(());
// return Ok(());
}
Err(e) => {
diesel::update(
Expand All @@ -228,6 +229,21 @@ pub async fn update_subscription_state_from_webhook(
return Err(e.into());
}
}
// Record the subscription state change in its table.
let old_subscription = user.get_subscription_type();
if let Some(old_subscription) = old_subscription {
// We have the user id, the old and new subscription, store it.
let subscription_change = SubscriptionChangeInsert {
user_id: user.id,
old_subscription_type: old_subscription,
new_subscription_type: subscription,
created_at: update.change_time.naive_utc(),
};
insert_into(schema::user_subscription_transitions::table)
.values(subscription_change)
.execute(&mut conn)?;
}
return Ok(());
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/db/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,22 @@ pub struct AIHelpHistoryMessage {
pub request: Value,
pub response: Value,
}

#[derive(Insertable)]
#[diesel(table_name = user_subscription_transitions)]
pub struct SubscriptionChangeInsert {
pub user_id: i64,
pub old_subscription_type: Subscription,
pub new_subscription_type: Subscription,
pub created_at: NaiveDateTime,
}

#[derive(Queryable, Debug)]
#[diesel(table_name = user_subscription_transitions)]
pub struct SubscriptionChangeQuery {
pub id: i64,
pub user_id: i64,
pub old_subscription_type: Subscription,
pub new_subscription_type: Subscription,
pub created_at: NaiveDateTime,
}
16 changes: 16 additions & 0 deletions src/db/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,20 @@ diesel::table! {
}
}

diesel::table! {
use diesel::sql_types::*;
use crate::db::types::*;
use super::sql_types::SubscriptionType;

user_subscription_transitions (id) {
id -> Int8,
user_id -> Int8,
old_subscription_type -> SubscriptionType,
new_subscription_type -> SubscriptionType,
created_at -> Timestamp,
}
}

diesel::table! {
use diesel::sql_types::*;
use crate::db::types::*;
Expand Down Expand Up @@ -307,6 +321,7 @@ diesel::joinable!(collection_items -> users (user_id));
diesel::joinable!(multiple_collections -> users (user_id));
diesel::joinable!(playground -> users (user_id));
diesel::joinable!(settings -> users (user_id));
diesel::joinable!(user_subscription_transitions -> users (user_id));

diesel::allow_tables_to_appear_in_same_query!(
activity_pings,
Expand All @@ -324,6 +339,7 @@ diesel::allow_tables_to_appear_in_same_query!(
playground,
raw_webhook_events_tokens,
settings,
user_subscription_transitions,
users,
webhook_events,
);
Loading

0 comments on commit 604b0e7

Please sign in to comment.