2022-06-21 08:18:22 +02:00
|
|
|
import * as IORedis from 'ioredis'
|
|
|
|
import { DateTime } from 'luxon'
|
|
|
|
|
2022-10-25 20:35:47 +02:00
|
|
|
import { Hub, ISOTimestamp, PreIngestionEvent } from '../../../src/types'
|
2022-06-21 08:18:22 +02:00
|
|
|
import { createHub } from '../../../src/utils/db/hub'
|
|
|
|
import { UUIDT } from '../../../src/utils/utils'
|
2022-08-04 08:57:43 +02:00
|
|
|
import { LazyPersonContainer } from '../../../src/worker/ingestion/lazy-person-container'
|
2022-06-21 08:18:22 +02:00
|
|
|
import { EventsProcessor } from '../../../src/worker/ingestion/process-event'
|
|
|
|
import { delayUntilEventIngested, resetTestDatabaseClickhouse } from '../../helpers/clickhouse'
|
|
|
|
import { resetKafka } from '../../helpers/kafka'
|
|
|
|
import { resetTestDatabase } from '../../helpers/sql'
|
|
|
|
|
|
|
|
jest.mock('../../../src/utils/status')
|
|
|
|
jest.setTimeout(600000) // 600 sec timeout.
|
|
|
|
|
|
|
|
let hub: Hub
|
|
|
|
let closeHub: () => Promise<void>
|
|
|
|
let redis: IORedis.Redis
|
|
|
|
let eventsProcessor: EventsProcessor
|
|
|
|
|
|
|
|
beforeAll(async () => {
|
|
|
|
await resetKafka()
|
|
|
|
})
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
await resetTestDatabase()
|
|
|
|
await resetTestDatabaseClickhouse()
|
|
|
|
;[hub, closeHub] = await createHub()
|
|
|
|
redis = await hub.redisPool.acquire()
|
|
|
|
await redis.flushdb()
|
|
|
|
|
|
|
|
eventsProcessor = new EventsProcessor(hub)
|
|
|
|
})
|
|
|
|
|
|
|
|
afterEach(async () => {
|
|
|
|
await hub.redisPool.release(redis)
|
|
|
|
await closeHub?.()
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('EventsProcessor#createEvent()', () => {
|
2022-08-04 08:57:43 +02:00
|
|
|
let personContainer: LazyPersonContainer
|
|
|
|
|
2022-06-21 08:18:22 +02:00
|
|
|
const eventUuid = new UUIDT().toString()
|
|
|
|
const personUuid = new UUIDT().toString()
|
2022-10-25 20:35:47 +02:00
|
|
|
const timestamp = '2020-02-23T02:15:00.000Z' as ISOTimestamp
|
2022-06-21 08:18:22 +02:00
|
|
|
|
|
|
|
const preIngestionEvent: PreIngestionEvent = {
|
|
|
|
eventUuid,
|
2022-10-25 20:35:47 +02:00
|
|
|
timestamp,
|
2022-06-21 08:18:22 +02:00
|
|
|
distinctId: 'my_id',
|
|
|
|
ip: '127.0.0.1',
|
|
|
|
teamId: 2,
|
|
|
|
event: '$pageview',
|
|
|
|
properties: { event: 'property' },
|
|
|
|
elementsList: [],
|
2022-08-04 08:57:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
personContainer = new LazyPersonContainer(2, 'my_id', hub, {
|
2022-06-21 08:18:22 +02:00
|
|
|
uuid: personUuid,
|
|
|
|
properties: { foo: 'bar' },
|
|
|
|
team_id: 1,
|
|
|
|
id: 1,
|
|
|
|
created_at: DateTime.fromISO(timestamp).toUTC(),
|
2022-08-04 08:57:43 +02:00
|
|
|
} as any)
|
|
|
|
})
|
2022-06-21 08:18:22 +02:00
|
|
|
|
|
|
|
it('emits event with person columns, re-using event properties', async () => {
|
|
|
|
jest.spyOn(eventsProcessor.db, 'getPersonData')
|
|
|
|
|
2023-05-04 13:25:56 +02:00
|
|
|
await eventsProcessor.createEvent(preIngestionEvent, personContainer)
|
2022-06-21 08:18:22 +02:00
|
|
|
|
|
|
|
await eventsProcessor.kafkaProducer.flush()
|
|
|
|
|
|
|
|
const events = await delayUntilEventIngested(() => hub.db.fetchEvents())
|
|
|
|
expect(events.length).toEqual(1)
|
|
|
|
expect(events[0]).toEqual(
|
|
|
|
expect.objectContaining({
|
|
|
|
uuid: eventUuid,
|
|
|
|
event: '$pageview',
|
|
|
|
properties: { event: 'property' },
|
2022-08-15 09:54:09 +02:00
|
|
|
timestamp: expect.any(DateTime),
|
2022-06-21 08:18:22 +02:00
|
|
|
team_id: 2,
|
|
|
|
distinct_id: 'my_id',
|
2022-08-15 09:54:09 +02:00
|
|
|
elements_chain: null,
|
|
|
|
created_at: expect.any(DateTime),
|
2022-06-21 08:18:22 +02:00
|
|
|
person_id: personUuid,
|
|
|
|
person_properties: { foo: 'bar' },
|
2022-08-15 09:54:09 +02:00
|
|
|
group0_properties: {},
|
|
|
|
group1_properties: {},
|
|
|
|
group2_properties: {},
|
|
|
|
group3_properties: {},
|
|
|
|
group4_properties: {},
|
2022-06-21 08:18:22 +02:00
|
|
|
$group_0: '',
|
|
|
|
$group_1: '',
|
|
|
|
$group_2: '',
|
|
|
|
$group_3: '',
|
|
|
|
$group_4: '',
|
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(jest.mocked(eventsProcessor.db.getPersonData)).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('emits event with group columns', async () => {
|
2023-03-14 17:36:44 +01:00
|
|
|
await eventsProcessor.db.insertGroup(
|
|
|
|
2,
|
|
|
|
0,
|
|
|
|
'group_key',
|
|
|
|
{ group_prop: 'value' },
|
|
|
|
DateTime.fromISO(timestamp),
|
|
|
|
{},
|
|
|
|
{},
|
|
|
|
1
|
|
|
|
)
|
2022-06-21 08:18:22 +02:00
|
|
|
|
2022-08-04 08:57:43 +02:00
|
|
|
await eventsProcessor.createEvent(
|
|
|
|
{ ...preIngestionEvent, properties: { $group_0: 'group_key' } },
|
|
|
|
personContainer
|
|
|
|
)
|
2022-06-21 08:18:22 +02:00
|
|
|
|
|
|
|
const events = await delayUntilEventIngested(() => hub.db.fetchEvents())
|
|
|
|
expect(events.length).toEqual(1)
|
|
|
|
expect(events[0]).toEqual(
|
|
|
|
expect.objectContaining({
|
|
|
|
$group_0: 'group_key',
|
|
|
|
$group_1: '',
|
|
|
|
$group_2: '',
|
|
|
|
$group_3: '',
|
|
|
|
$group_4: '',
|
|
|
|
group0_properties: {
|
|
|
|
group_prop: 'value',
|
|
|
|
},
|
2022-08-15 09:54:09 +02:00
|
|
|
group1_properties: {},
|
|
|
|
group2_properties: {},
|
|
|
|
group3_properties: {},
|
|
|
|
group4_properties: {},
|
2022-06-21 08:18:22 +02:00
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('emits event with person columns if not previously fetched', async () => {
|
|
|
|
jest.spyOn(eventsProcessor.db, 'getPersonData')
|
|
|
|
await eventsProcessor.db.createPerson(
|
|
|
|
DateTime.fromISO(timestamp).toUTC(),
|
|
|
|
{ foo: 'bar', a: 2 },
|
2023-03-14 17:36:44 +01:00
|
|
|
{},
|
|
|
|
{},
|
2022-06-21 08:18:22 +02:00
|
|
|
2,
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
personUuid,
|
|
|
|
['my_id']
|
|
|
|
)
|
|
|
|
|
2022-08-04 08:57:43 +02:00
|
|
|
await eventsProcessor.createEvent(
|
|
|
|
{
|
|
|
|
...preIngestionEvent,
|
|
|
|
properties: { $set: { a: 1 } },
|
|
|
|
},
|
2022-06-21 08:18:22 +02:00
|
|
|
// :TRICKY: We pretend the person has been updated in-between processing and creating the event
|
2022-08-04 08:57:43 +02:00
|
|
|
new LazyPersonContainer(2, 'my_id', hub)
|
|
|
|
)
|
2022-06-21 08:18:22 +02:00
|
|
|
|
|
|
|
await eventsProcessor.kafkaProducer.flush()
|
|
|
|
|
|
|
|
const events = await delayUntilEventIngested(() => hub.db.fetchEvents())
|
|
|
|
expect(events.length).toEqual(1)
|
|
|
|
expect(events[0]).toEqual(
|
|
|
|
expect.objectContaining({
|
|
|
|
uuid: eventUuid,
|
|
|
|
distinct_id: 'my_id',
|
|
|
|
person_id: personUuid,
|
|
|
|
person_properties: { foo: 'bar', a: 1 },
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('handles the person no longer existing', async () => {
|
2022-08-04 08:57:43 +02:00
|
|
|
await eventsProcessor.createEvent(preIngestionEvent, new LazyPersonContainer(2, 'my_id', hub))
|
2022-06-21 08:18:22 +02:00
|
|
|
await eventsProcessor.kafkaProducer.flush()
|
|
|
|
|
|
|
|
const events = await delayUntilEventIngested(() => hub.db.fetchEvents())
|
|
|
|
expect(events.length).toEqual(1)
|
|
|
|
expect(events[0]).toEqual(
|
|
|
|
expect.objectContaining({
|
|
|
|
uuid: eventUuid,
|
|
|
|
distinct_id: 'my_id',
|
|
|
|
person_id: '00000000-0000-0000-0000-000000000000',
|
2022-08-15 09:54:09 +02:00
|
|
|
person_properties: {},
|
2022-06-21 08:18:22 +02:00
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|