11import { PluginEvent , Properties } from '@posthog/plugin-scaffold'
22import * as Sentry from '@sentry/node'
3- import equal from 'fast-deep-equal'
43import { StatsD } from 'hot-shots'
54import { ProducerRecord } from 'kafkajs'
65import { 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,
0 commit comments