From db1b785b868778d6dca94e6115aee08ac043d4de Mon Sep 17 00:00:00 2001 From: Brett Hoerner Date: Thu, 25 Apr 2024 09:22:00 -0600 Subject: [PATCH] chore(plugin-server): set 'force_upgrade' for 'person_mode' when applicable --- plugin-server/src/types.ts | 10 ++++++++-- plugin-server/src/worker/ingestion/person-state.ts | 9 +++++++-- plugin-server/src/worker/ingestion/process-event.ts | 10 +++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 331fc52f2e696f..f3106fe62dd24c 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -619,6 +619,7 @@ interface BaseEvent { export type ISOTimestamp = Brand export type ClickHouseTimestamp = Brand export type ClickHouseTimestampSecondPrecision = Brand +export type PersonMode = 'full' | 'propertyless' | 'force_upgrade' /** Raw event row from ClickHouse. */ export interface RawClickHouseEvent extends BaseEvent { @@ -638,7 +639,7 @@ export interface RawClickHouseEvent extends BaseEvent { group2_created_at?: ClickHouseTimestamp group3_created_at?: ClickHouseTimestamp group4_created_at?: ClickHouseTimestamp - person_mode: 'full' | 'propertyless' + person_mode: PersonMode } /** Parsed event row from ClickHouse. */ @@ -659,7 +660,7 @@ export interface ClickHouseEvent extends BaseEvent { group2_created_at?: DateTime | null group3_created_at?: DateTime | null group4_created_at?: DateTime | null - person_mode: 'full' | 'propertyless' + person_mode: PersonMode } /** Event in a database-agnostic shape, AKA an ingestion event. @@ -746,6 +747,11 @@ export interface Person { properties: Properties uuid: string created_at: DateTime + + // Set to `true` when an existing person row was found for this `distinct_id`, but the event was + // sent with `$process_person_profile=false`. This is an unexpected branch that we want to flag + // for debugging and billing purposes, and typically means a misconfigured SDK. + force_upgrade?: boolean } /** Clickhouse Person model. */ diff --git a/plugin-server/src/worker/ingestion/person-state.ts b/plugin-server/src/worker/ingestion/person-state.ts index e7f3652b2ef250..ca250aa3d52da9 100644 --- a/plugin-server/src/worker/ingestion/person-state.ts +++ b/plugin-server/src/worker/ingestion/person-state.ts @@ -114,11 +114,16 @@ export class PersonState { async update(): Promise { if (!this.processPerson) { if (this.lazyPersonCreation) { - const person = await this.db.fetchPerson(this.teamId, this.distinctId, { useReadReplica: true }) - if (person) { + const existingPerson = await this.db.fetchPerson(this.teamId, this.distinctId, { useReadReplica: true }) + if (existingPerson) { + const person = existingPerson as Person + // Ensure person properties don't propagate elsewhere, such as onto the event itself. person.properties = {} + // See documentation on the field. + person.force_upgrade = true + return person } diff --git a/plugin-server/src/worker/ingestion/process-event.ts b/plugin-server/src/worker/ingestion/process-event.ts index 8b57e261900466..d3f49b85cfd717 100644 --- a/plugin-server/src/worker/ingestion/process-event.ts +++ b/plugin-server/src/worker/ingestion/process-event.ts @@ -11,6 +11,7 @@ import { Hub, ISOTimestamp, Person, + PersonMode, PreIngestionEvent, RawClickHouseEvent, Team, @@ -239,6 +240,13 @@ export class EventsProcessor { // TODO: Remove Redis caching for person that's not used anymore + let personMode: PersonMode = 'full' + if (person.force_upgrade) { + personMode = 'force_upgrade' + } else if (!processPerson) { + personMode = 'propertyless' + } + const rawEvent: RawClickHouseEvent = { uuid, event: safeClickhouseString(event), @@ -251,7 +259,7 @@ export class EventsProcessor { person_id: person.uuid, person_properties: eventPersonProperties, person_created_at: castTimestampOrNow(person.created_at, TimestampFormat.ClickHouseSecondPrecision), - person_mode: processPerson ? 'full' : 'propertyless', + person_mode: personMode, ...groupsColumns, }