Return the metrics id from the signup-creation API

Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-09-22 14:37:25 -07:00
parent 7a049f1404
commit dac0ce10e5
3 changed files with 37 additions and 22 deletions

View file

@ -396,12 +396,17 @@ async fn get_user_for_invite_code(
Ok(Json(app.db.get_user_for_invite_code(&code).await?)) Ok(Json(app.db.get_user_for_invite_code(&code).await?))
} }
#[derive(Serialize)]
struct CreateSignupResponse {
metrics_id: i32,
}
async fn create_signup( async fn create_signup(
Json(params): Json<Signup>, Json(params): Json<Signup>,
Extension(app): Extension<Arc<AppState>>, Extension(app): Extension<Arc<AppState>>,
) -> Result<()> { ) -> Result<Json<CreateSignupResponse>> {
app.db.create_signup(params).await?; let metrics_id = app.db.create_signup(params).await?;
Ok(()) Ok(Json(CreateSignupResponse { metrics_id }))
} }
async fn get_waitlist_summary( async fn get_waitlist_summary(

View file

@ -37,7 +37,7 @@ pub trait Db: Send + Sync {
async fn get_user_for_invite_code(&self, code: &str) -> Result<User>; async fn get_user_for_invite_code(&self, code: &str) -> Result<User>;
async fn create_invite_from_code(&self, code: &str, email_address: &str) -> Result<Invite>; async fn create_invite_from_code(&self, code: &str, email_address: &str) -> Result<Invite>;
async fn create_signup(&self, signup: Signup) -> Result<()>; async fn create_signup(&self, signup: Signup) -> Result<i32>;
async fn get_waitlist_summary(&self) -> Result<WaitlistSummary>; async fn get_waitlist_summary(&self) -> Result<WaitlistSummary>;
async fn get_unsent_invites(&self, count: usize) -> Result<Vec<Invite>>; async fn get_unsent_invites(&self, count: usize) -> Result<Vec<Invite>>;
async fn record_sent_invites(&self, invites: &[Invite]) -> Result<()>; async fn record_sent_invites(&self, invites: &[Invite]) -> Result<()>;
@ -364,8 +364,8 @@ impl Db for PostgresDb {
// signups // signups
async fn create_signup(&self, signup: Signup) -> Result<()> { async fn create_signup(&self, signup: Signup) -> Result<i32> {
sqlx::query( Ok(sqlx::query_scalar(
" "
INSERT INTO signups INSERT INTO signups
( (
@ -381,6 +381,7 @@ impl Db for PostgresDb {
) )
VALUES VALUES
($1, $2, 'f', $3, $4, $5, 'f', $6, $7) ($1, $2, 'f', $3, $4, $5, 'f', $6, $7)
RETURNING id
", ",
) )
.bind(&signup.email_address) .bind(&signup.email_address)
@ -390,9 +391,8 @@ impl Db for PostgresDb {
.bind(&signup.platform_windows) .bind(&signup.platform_windows)
.bind(&signup.editor_features) .bind(&signup.editor_features)
.bind(&signup.programming_languages) .bind(&signup.programming_languages)
.execute(&self.pool) .fetch_one(&self.pool)
.await?; .await?)
Ok(())
} }
async fn get_waitlist_summary(&self) -> Result<WaitlistSummary> { async fn get_waitlist_summary(&self) -> Result<WaitlistSummary> {
@ -479,7 +479,10 @@ impl Db for PostgresDb {
.ok_or_else(|| Error::Http(StatusCode::NOT_FOUND, "no such invite".to_string()))?; .ok_or_else(|| Error::Http(StatusCode::NOT_FOUND, "no such invite".to_string()))?;
if existing_user_id.is_some() { if existing_user_id.is_some() {
Err(Error::Http(StatusCode::UNPROCESSABLE_ENTITY, "invitation already redeemed".to_string()))?; Err(Error::Http(
StatusCode::UNPROCESSABLE_ENTITY,
"invitation already redeemed".to_string(),
))?;
} }
let user_id: UserId = sqlx::query_scalar( let user_id: UserId = sqlx::query_scalar(
@ -1564,6 +1567,7 @@ pub struct User {
pub id: UserId, pub id: UserId,
pub github_login: String, pub github_login: String,
pub github_user_id: Option<i32>, pub github_user_id: Option<i32>,
pub metrics_id: i32,
pub email_address: Option<String>, pub email_address: Option<String>,
pub admin: bool, pub admin: bool,
pub invite_code: Option<String>, pub invite_code: Option<String>,
@ -1789,7 +1793,8 @@ mod test {
{ {
Ok(user.id) Ok(user.id)
} else { } else {
let user_id = UserId(post_inc(&mut *self.next_user_id.lock())); let id = post_inc(&mut *self.next_user_id.lock());
let user_id = UserId(id);
users.insert( users.insert(
user_id, user_id,
User { User {
@ -1797,6 +1802,7 @@ mod test {
github_login: params.github_login, github_login: params.github_login,
github_user_id: Some(params.github_user_id), github_user_id: Some(params.github_user_id),
email_address: Some(email_address.to_string()), email_address: Some(email_address.to_string()),
metrics_id: id + 100,
admin, admin,
invite_code: None, invite_code: None,
invite_count: 0, invite_count: 0,
@ -1878,7 +1884,7 @@ mod test {
// signups // signups
async fn create_signup(&self, _signup: Signup) -> Result<()> { async fn create_signup(&self, _signup: Signup) -> Result<i32> {
unimplemented!() unimplemented!()
} }

View file

@ -1139,17 +1139,20 @@ async fn test_signups() {
let db = postgres.db(); let db = postgres.db();
// people sign up on the waitlist // people sign up on the waitlist
let mut signup_metric_ids = Vec::new();
for i in 0..8 { for i in 0..8 {
db.create_signup(Signup { signup_metric_ids.push(
email_address: format!("person-{i}@example.com"), db.create_signup(Signup {
platform_mac: true, email_address: format!("person-{i}@example.com"),
platform_linux: i % 2 == 0, platform_mac: true,
platform_windows: i % 4 == 0, platform_linux: i % 2 == 0,
editor_features: vec!["speed".into()], platform_windows: i % 4 == 0,
programming_languages: vec!["rust".into(), "c".into()], editor_features: vec!["speed".into()],
}) programming_languages: vec!["rust".into(), "c".into()],
.await })
.unwrap(); .await
.unwrap(),
);
} }
assert_eq!( assert_eq!(
@ -1235,6 +1238,7 @@ async fn test_signups() {
assert_eq!(user.github_login, "person-0"); assert_eq!(user.github_login, "person-0");
assert_eq!(user.email_address.as_deref(), Some("person-0@example.com")); assert_eq!(user.email_address.as_deref(), Some("person-0@example.com"));
assert_eq!(user.invite_count, 5); assert_eq!(user.invite_count, 5);
assert_eq!(user.metrics_id, signup_metric_ids[0]);
// cannot redeem the same signup again. // cannot redeem the same signup again.
db.create_user_from_invite( db.create_user_from_invite(