Skip to content

Commit

Permalink
fix(propdefs): insert actual seen_at, floor less aggressively (#24865)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverb123 authored Sep 10, 2024
1 parent 40d96f0 commit dc1b9f8
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 20 deletions.
24 changes: 21 additions & 3 deletions rust/property-defs-rs/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@ impl From<&Event> for EventDefinition {
EventDefinition {
name: sanitize_event_name(&event.event),
team_id: event.team_id,
// We round last seen to the nearest day, as per the TS impl. Unwrap is safe here because we
// We round last seen to the nearest hour. Unwrap is safe here because we
// the duration is positive, non-zero, and smaller than time since epoch. We use this
// in the hash value, so updates which would modify this in the DB are issued even
// if another otherwise-identical event definition is in the cache
last_seen_at: floor_datetime(Utc::now(), Duration::days(1)).unwrap(),
last_seen_at: floor_datetime(Utc::now(), Duration::hours(1)).unwrap(),
}
}
}
Expand Down Expand Up @@ -427,7 +427,7 @@ impl EventDefinition {
Uuid::now_v7(),
self.name,
self.team_id,
self.last_seen_at
Utc::now() // We floor the update datetime to the nearest day for cache purposes, but can insert the exact time we see the event
).execute(executor).await.map(|_| ())
}
}
Expand Down Expand Up @@ -479,3 +479,21 @@ impl EventProperty {
.map(|_| ())
}
}

#[cfg(test)]
mod test {
use chrono::{Timelike, Utc};

use crate::types::floor_datetime;

#[test]
fn test_date_flooring() {
let timestamp = Utc::now();
let rounded = floor_datetime(timestamp, chrono::Duration::days(1)).unwrap();
assert_eq!(rounded.hour(), 0);
assert_eq!(rounded.minute(), 0);
assert_eq!(rounded.second(), 0);
assert_eq!(rounded.nanosecond(), 0);
assert!(rounded <= timestamp);
}
}
56 changes: 39 additions & 17 deletions rust/property-defs-rs/tests/updates.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use chrono::{DateTime, Duration, Utc};
use property_defs_rs::types::{floor_datetime, Event, PropertyParentType, PropertyValueType};
use property_defs_rs::types::{Event, PropertyParentType, PropertyValueType};
use serde_json::json;
use sqlx::PgPool;

Expand Down Expand Up @@ -32,14 +32,16 @@ async fn test_updates(db: PgPool) {
let updates = event.into_updates(1000);
assert!(updates.len() == 13);

let before = Utc::now();

// issue them, and then query the database to see that everthing we expect to exist does
for update in updates {
update.issue(&db).await.unwrap();
}

let today = floor_datetime(Utc::now(), Duration::days(1)).unwrap();

assert_eventdefinition_exists(&db, "update", 1, today).await;
assert_eventdefinition_exists(&db, "update", 1, before, Duration::seconds(1))
.await
.unwrap();
assert_propertydefinition_exists(
&db,
"TIMESTAMP",
Expand All @@ -48,7 +50,8 @@ async fn test_updates(db: PgPool) {
1,
PropertyValueType::DateTime,
)
.await;
.await
.unwrap();
assert_propertydefinition_exists(
&db,
"some_string",
Expand All @@ -57,7 +60,8 @@ async fn test_updates(db: PgPool) {
1,
PropertyValueType::String,
)
.await;
.await
.unwrap();
assert_propertydefinition_exists(
&db,
"some_int",
Expand All @@ -66,7 +70,8 @@ async fn test_updates(db: PgPool) {
1,
PropertyValueType::Numeric,
)
.await;
.await
.unwrap();
assert_propertydefinition_exists(
&db,
"some_float",
Expand All @@ -75,7 +80,8 @@ async fn test_updates(db: PgPool) {
1,
PropertyValueType::Numeric,
)
.await;
.await
.unwrap();
assert_propertydefinition_exists(
&db,
"some_bool",
Expand All @@ -84,7 +90,8 @@ async fn test_updates(db: PgPool) {
1,
PropertyValueType::Boolean,
)
.await;
.await
.unwrap();
assert_propertydefinition_exists(
&db,
"some_bool_as_string",
Expand All @@ -93,30 +100,41 @@ async fn test_updates(db: PgPool) {
1,
PropertyValueType::Boolean,
)
.await;
.await
.unwrap();
}

async fn assert_eventdefinition_exists(
db: &PgPool,
name: &str,
team_id: i32,
last_seen_at: DateTime<Utc>,
) {
before: DateTime<Utc>,
last_seen_range: Duration,
) -> Result<(), ()> {
// Event definitions are inserted with a last_seen that's exactly when the insert is done. We check if an entry exists in the
// database with a last_seen that's in the right range to ensure that the event definition was inserted correctly.
let after = before + last_seen_range;

let count: Option<i64> = sqlx::query_scalar(
r#"
SELECT COUNT(*)
FROM posthog_eventdefinition
WHERE name = $1 AND team_id = $2 AND last_seen_at = $3
WHERE name = $1 AND team_id = $2 AND last_seen_at >= $3 AND last_seen_at <= $4
"#,
)
.bind(name)
.bind(team_id)
.bind(last_seen_at)
.bind(before)
.bind(after)
.fetch_one(db)
.await
.unwrap();

assert_eq!(count, Some(1));
if count == Some(1) {
Ok(())
} else {
Err(())
}
}

async fn assert_propertydefinition_exists(
Expand All @@ -126,7 +144,7 @@ async fn assert_propertydefinition_exists(
is_numerical: bool,
team_id: i32,
property_type: PropertyValueType,
) {
) -> Result<(), ()> {
println!("Checking property definition for {}", name);
let count: Option<i64> = sqlx::query_scalar(
r#"
Expand All @@ -144,5 +162,9 @@ async fn assert_propertydefinition_exists(
.await
.unwrap();

assert_eq!(count, Some(1));
if count == Some(1) {
Ok(())
} else {
Err(())
}
}

0 comments on commit dc1b9f8

Please sign in to comment.