-
Notifications
You must be signed in to change notification settings - Fork 248
feat: use groupmq instead of bullmq for incoming events #206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cfee58d
a5cfadd
123e380
6936dcc
43918a9
2d73e83
470aab9
4fd163e
462d253
41c6423
fffaf83
d3d86a3
2776603
0c16b41
07e9c13
21a6b8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ import * as faker from '@faker-js/faker'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { generateId } from '@openpanel/common'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { hashPassword } from '@openpanel/common/server'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ClientType, db } from '@openpanel/db'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getRedisCache } from '@openpanel/redis'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { v4 as uuidv4 } from 'uuid'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const DOMAIN_COUNT = 5; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -260,6 +261,8 @@ function insertFakeEvents(events: Event[]) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async function simultaneousRequests() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await getRedisCache().flushdb(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await new Promise((resolve) => setTimeout(resolve, 1000)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const sessions: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ip: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| referrer: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -272,9 +275,11 @@ async function simultaneousRequests() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userAgent: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| track: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/home' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'button_click', element: 'signup' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/pricing' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/home', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'button_click', element: 'signup', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'article_viewed', articleId: '123', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/pricing', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -361,8 +366,9 @@ async function simultaneousRequests() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/landing' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/pricing' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog/post-1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog/post-2' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog/post-1', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog/post-2', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'button_click', element: 'learn_more', parallel: '1' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog/post-3' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'screen_view', path: '/blog/post-4' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -396,21 +402,85 @@ async function simultaneousRequests() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const session of sessions) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Group tracks by parallel flag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const trackGroups: { parallel?: string; tracks: any[] }[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let currentGroup: { parallel?: string; tracks: any[] } = { tracks: [] }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const track of session.track) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { name, ...properties } = track; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.name = name ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.properties.__referrer = session.referrer ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (name === 'screen_view') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.properties.__path = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (screenView.headers.origin ?? '') + (properties.path ?? ''); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (track.parallel) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // If this track has a parallel flag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentGroup.parallel === track.parallel) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Same parallel group, add to current group | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentGroup.tracks.push(track); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Different parallel group, finish current group and start new one | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentGroup.tracks.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trackGroups.push(currentGroup); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentGroup = { parallel: track.parallel, tracks: [track] }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.name = track.name ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.properties = properties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // No parallel flag, finish any parallel group and start individual track | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentGroup.tracks.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trackGroups.push(currentGroup); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentGroup = { tracks: [track] }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.headers['x-client-ip'] = session.ip; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.headers['user-agent'] = session.userAgent; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await trackit(screenView); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Add the last group | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentGroup.tracks.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trackGroups.push(currentGroup); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Process each group | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const group of trackGroups) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (group.parallel && group.tracks.length > 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Parallel execution for same-flagged tracks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `Firing ${group.tracks.length} parallel requests with flag '${group.parallel}'`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const promises = group.tracks.map(async (track) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { name, parallel, ...properties } = track; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const event = JSON.parse(JSON.stringify(screenView)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.track.payload.name = name ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.track.payload.properties.__referrer = session.referrer ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (name === 'screen_view') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.track.payload.properties.__path = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (event.headers.origin ?? '') + (properties.path ?? ''); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.track.payload.name = track.name ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.track.payload.properties = properties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.headers['x-client-ip'] = session.ip; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event.headers['user-agent'] = session.userAgent; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return trackit(event); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await Promise.all(promises); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`Completed ${group.tracks.length} parallel requests`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Sequential execution for individual tracks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const track of group.tracks) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { name, parallel, ...properties } = track; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.name = name ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.properties.__referrer = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| session.referrer ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (name === 'screen_view') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.properties.__path = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (screenView.headers.origin ?? '') + (properties.path ?? ''); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.name = track.name ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.track.payload.properties = properties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.headers['x-client-ip'] = session.ip; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| screenView.headers['user-agent'] = session.userAgent; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await trackit(screenView); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+463
to
+479
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reset event payload per sequential track. The sequential path keeps mutating the shared - for (const track of group.tracks) {
- const { name, parallel, ...properties } = track;
- screenView.track.payload.name = name ?? '';
- screenView.track.payload.properties.__referrer =
- session.referrer ?? '';
- if (name === 'screen_view') {
- screenView.track.payload.properties.__path =
- (screenView.headers.origin ?? '') + (properties.path ?? '');
- } else {
- screenView.track.payload.name = track.name ?? '';
- screenView.track.payload.properties = properties;
- }
- screenView.headers['x-client-ip'] = session.ip;
- screenView.headers['user-agent'] = session.userAgent;
- await trackit(screenView);
- }
+ for (const track of group.tracks) {
+ const { name, parallel: _parallel, ...properties } = track;
+ const event = JSON.parse(JSON.stringify(screenView));
+ event.track.payload.name = name ?? '';
+ event.track.payload.properties.__referrer = session.referrer ?? '';
+ if (name === 'screen_view') {
+ event.track.payload.properties.__path =
+ (event.headers.origin ?? '') + (properties.path ?? '');
+ } else {
+ event.track.payload.properties = properties;
+ }
+ event.headers['x-client-ip'] = session.ip;
+ event.headers['user-agent'] = session.userAgent;
+ await trackit(event);
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Add delay between groups (not within parallel groups) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // await new Promise((resolve) => setTimeout(resolve, Math.random() * 100)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't flush the shared Redis by default.
flushdb()wipes every key in the selected Redis database. Running this helper script against a shared dev/staging instance would erase caches, queues, rate limits—everything—before the mock traffic even starts. Please gate the flush behind an explicit opt-in (env flag or CLI switch) so we cannot accidentally destroy state.📝 Committable suggestion
🤖 Prompt for AI Agents