Skip to content

Commit 11e4eaf

Browse files
authored
fix(plugin-server): applyEventPropertyUpdates returns whether it did … (#17825)
fix(plugin-server): applyEventPropertyUpdates returns whether it did an update, rather than needing to use deep-equals
1 parent 9787385 commit 11e4eaf

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

plugin-server/src/worker/ingestion/person-state.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { PluginEvent, Properties } from '@posthog/plugin-scaffold'
22
import * as Sentry from '@sentry/node'
3-
import equal from 'fast-deep-equal'
43
import { StatsD } from 'hot-shots'
54
import { ProducerRecord } from 'kafkajs'
65
import { DateTime } from 'luxon'
@@ -214,11 +213,11 @@ export class PersonState {
214213
}
215214

216215
private async updatePersonProperties(person: Person): Promise<Person> {
217-
const update: Partial<Person> = {}
218-
const updatedProperties = this.applyEventPropertyUpdates(person.properties || {})
216+
person.properties ||= {}
219217

220-
if (!equal(person.properties, updatedProperties)) {
221-
update.properties = updatedProperties
218+
const update: Partial<Person> = {}
219+
if (this.applyEventPropertyUpdates(person.properties)) {
220+
update.properties = person.properties
222221
}
223222
if (this.updateIsIdentified && !person.is_identified) {
224223
update.is_identified = true
@@ -231,33 +230,39 @@ export class PersonState {
231230
return person
232231
}
233232

234-
private applyEventPropertyUpdates(personProperties: Properties): Properties {
235-
const updatedProperties = { ...personProperties }
236-
233+
/**
234+
* @param personProperties Properties of the person to be updated, these are updated in place.
235+
* @returns true if the properties were changed, false if they were not
236+
*/
237+
private applyEventPropertyUpdates(personProperties: Properties): boolean {
237238
const properties: Properties = this.eventProperties['$set'] || {}
238239
const propertiesOnce: Properties = this.eventProperties['$set_once'] || {}
239240
const unsetProps = this.eventProperties['$unset']
240241
const unsetProperties: Array<string> = Array.isArray(unsetProps)
241242
? unsetProps
242243
: Object.keys(unsetProps || {}) || []
243244

244-
// Figure out which properties we are actually setting
245+
let updated = false
245246
Object.entries(propertiesOnce).map(([key, value]) => {
246247
if (typeof personProperties[key] === 'undefined') {
247-
updatedProperties[key] = value
248+
updated = true
249+
personProperties[key] = value
248250
}
249251
})
250252
Object.entries(properties).map(([key, value]) => {
251253
if (personProperties[key] !== value) {
252-
updatedProperties[key] = value
254+
updated = true
255+
personProperties[key] = value
253256
}
254257
})
255-
256258
unsetProperties.forEach((propertyKey) => {
257-
delete updatedProperties[propertyKey]
259+
if (propertyKey in personProperties) {
260+
updated = true
261+
delete personProperties[propertyKey]
262+
}
258263
})
259264

260-
return updatedProperties
265+
return updated
261266
}
262267

263268
// Alias & merge
@@ -439,8 +444,8 @@ export class PersonState {
439444
// that guarantees consistency of how properties are processed regardless of persons created_at timestamps and rollout state
440445
// we're calling aliasDeprecated as we need to refresh the persons info completely first
441446

442-
let properties: Properties = { ...otherPerson.properties, ...mergeInto.properties }
443-
properties = this.applyEventPropertyUpdates(properties)
447+
const properties: Properties = { ...otherPerson.properties, ...mergeInto.properties }
448+
this.applyEventPropertyUpdates(properties)
444449

445450
if (this.poEEmbraceJoin) {
446451
// Optimize merging persons to keep using the person id that has longer history,

plugin-server/tests/worker/ingestion/person-state.test.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,24 @@ describe('PersonState.update()', () => {
244244

245245
describe('on person update', () => {
246246
it('updates person properties', async () => {
247-
await hub.db.createPerson(timestamp, { b: 3, c: 4 }, {}, {}, teamId, null, false, uuid.toString(), [
248-
'new-user',
249-
])
247+
await hub.db.createPerson(
248+
timestamp,
249+
{ b: 3, c: 4, toString: {} },
250+
{},
251+
{},
252+
teamId,
253+
null,
254+
false,
255+
uuid.toString(),
256+
['new-user']
257+
)
250258

251259
const person = await personState({
252260
event: '$pageview',
253261
distinct_id: 'new-user',
254262
properties: {
255263
$set_once: { c: 3, e: 4 },
256-
$set: { b: 4 },
264+
$set: { b: 4, toString: 1 },
257265
},
258266
}).updateProperties()
259267
await hub.db.kafkaProducer.flush()
@@ -262,7 +270,7 @@ describe('PersonState.update()', () => {
262270
expect.objectContaining({
263271
id: expect.any(Number),
264272
uuid: uuid.toString(),
265-
properties: { b: 4, c: 4, e: 4 },
273+
properties: { b: 4, c: 4, e: 4, toString: 1 },
266274
created_at: timestamp,
267275
version: 1,
268276
is_identified: false,

0 commit comments

Comments
 (0)