Skip to content

Conversation

@pauldambra
Copy link
Member

@pauldambra pauldambra commented Nov 15, 2025

we tested yielding processing to the main thread periodically and it worked well

reducing variability of INP on pages using that mode

let's abstract the task queue processing approach and use it in a few more places where we might be running over large arrays and cause a long task

@vercel
Copy link

vercel bot commented Nov 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
posthog-js Ready Ready Preview Nov 15, 2025 5:18pm

Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@pauldambra pauldambra marked this pull request as ready for review November 15, 2025 12:49
@pauldambra pauldambra requested a review from a team November 15, 2025 12:49
@github-actions
Copy link
Contributor

github-actions bot commented Nov 15, 2025

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

@github-actions
Copy link
Contributor

github-actions bot commented Nov 15, 2025

Size Change: +19.5 kB (+0.39%)

Total Size: 5.04 MB

Filename Size Change
packages/browser/dist/all-external-dependencies.js 227 kB +1.02 kB (+0.45%)
packages/browser/dist/array.full.es5.js 301 kB +2.12 kB (+0.71%)
packages/browser/dist/array.full.js 366 kB +1.27 kB (+0.35%)
packages/browser/dist/array.full.no-external.js 381 kB +1.46 kB (+0.38%)
packages/browser/dist/array.js 163 kB +1.31 kB (+0.81%)
packages/browser/dist/array.no-external.js 175 kB +1.43 kB (+0.82%)
packages/browser/dist/lazy-recorder.js 150 kB +1.06 kB (+0.71%)
packages/browser/dist/main.js 164 kB +1.31 kB (+0.81%)
packages/browser/dist/module.full.js 367 kB +1.27 kB (+0.35%)
packages/browser/dist/module.full.no-external.js 381 kB +1.46 kB (+0.38%)
packages/browser/dist/module.js 164 kB +1.31 kB (+0.81%)
packages/browser/dist/module.no-external.js 176 kB +1.43 kB (+0.82%)
packages/browser/dist/posthog-recorder.js 247 kB +1.06 kB (+0.43%)
packages/browser/dist/recorder-v2.js 114 kB +1.02 kB (+0.9%)
packages/browser/dist/recorder.js 114 kB +1.02 kB (+0.9%)
ℹ️ View Unchanged
Filename Size Change
packages/ai/dist/anthropic/index.cjs 17.3 kB 0 B
packages/ai/dist/anthropic/index.mjs 17.2 kB 0 B
packages/ai/dist/gemini/index.cjs 21.2 kB 0 B
packages/ai/dist/gemini/index.mjs 21 kB 0 B
packages/ai/dist/index.cjs 137 kB 0 B
packages/ai/dist/index.mjs 136 kB 0 B
packages/ai/dist/langchain/index.cjs 40.2 kB 0 B
packages/ai/dist/langchain/index.mjs 39.7 kB 0 B
packages/ai/dist/openai/index.cjs 41.6 kB 0 B
packages/ai/dist/openai/index.mjs 41.3 kB 0 B
packages/ai/dist/vercel/index.cjs 29.6 kB 0 B
packages/ai/dist/vercel/index.mjs 29.6 kB 0 B
packages/browser/dist/crisp-chat-integration.js 1.97 kB 0 B
packages/browser/dist/customizations.full.js 19 kB 0 B
packages/browser/dist/dead-clicks-autocapture.js 12.6 kB 0 B
packages/browser/dist/exception-autocapture.js 11.6 kB 0 B
packages/browser/dist/external-scripts-loader.js 2.81 kB 0 B
packages/browser/dist/intercom-integration.js 2.02 kB 0 B
packages/browser/dist/surveys-preview.js 71.1 kB 0 B
packages/browser/dist/surveys.js 83 kB 0 B
packages/browser/dist/tracing-headers.js 1.84 kB 0 B
packages/browser/dist/web-vitals.js 10.4 kB 0 B
packages/browser/react/dist/esm/index.js 18.8 kB 0 B
packages/browser/react/dist/umd/index.js 21.9 kB 0 B
packages/core/dist/error-tracking/chunk-ids.js 2.54 kB 0 B
packages/core/dist/error-tracking/chunk-ids.mjs 1.31 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.js 2.3 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.mjs 993 B 0 B
packages/core/dist/error-tracking/coercers/error-coercer.js 2.02 kB 0 B
packages/core/dist/error-tracking/coercers/error-coercer.mjs 794 B 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.js 1.76 kB 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.mjs 513 B 0 B
packages/core/dist/error-tracking/coercers/event-coercer.js 1.82 kB 0 B
packages/core/dist/error-tracking/coercers/event-coercer.mjs 548 B 0 B
packages/core/dist/error-tracking/coercers/index.js 6.79 kB 0 B
packages/core/dist/error-tracking/coercers/index.mjs 326 B 0 B
packages/core/dist/error-tracking/coercers/object-coercer.js 3.46 kB 0 B
packages/core/dist/error-tracking/coercers/object-coercer.mjs 2.07 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.js 1.67 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.mjs 419 B 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.js 2.25 kB 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.mjs 904 B 0 B
packages/core/dist/error-tracking/coercers/string-coercer.js 2.01 kB 0 B
packages/core/dist/error-tracking/coercers/string-coercer.mjs 820 B 0 B
packages/core/dist/error-tracking/coercers/utils.js 2.06 kB 0 B
packages/core/dist/error-tracking/coercers/utils.mjs 716 B 0 B
packages/core/dist/error-tracking/error-properties-builder.js 5.64 kB 0 B
packages/core/dist/error-tracking/error-properties-builder.mjs 4.24 kB 0 B
packages/core/dist/error-tracking/index.js 4.11 kB 0 B
packages/core/dist/error-tracking/index.mjs 152 B 0 B
packages/core/dist/error-tracking/parsers/base.js 1.84 kB 0 B
packages/core/dist/error-tracking/parsers/base.mjs 472 B 0 B
packages/core/dist/error-tracking/parsers/chrome.js 2.7 kB 0 B
packages/core/dist/error-tracking/parsers/chrome.mjs 1.29 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.js 2.45 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.mjs 1.11 kB 0 B
packages/core/dist/error-tracking/parsers/index.js 4.36 kB 0 B
packages/core/dist/error-tracking/parsers/index.mjs 1.92 kB 0 B
packages/core/dist/error-tracking/parsers/node.js 3.95 kB 0 B
packages/core/dist/error-tracking/parsers/node.mjs 2.68 kB 0 B
packages/core/dist/error-tracking/parsers/opera.js 2.22 kB 0 B
packages/core/dist/error-tracking/parsers/opera.mjs 706 B 0 B
packages/core/dist/error-tracking/parsers/react-native.js 203 B 0 B
packages/core/dist/error-tracking/parsers/react-native.mjs 0 B 0 B 🆕
packages/core/dist/error-tracking/parsers/safari.js 1.88 kB 0 B
packages/core/dist/error-tracking/parsers/safari.mjs 574 B 0 B
packages/core/dist/error-tracking/parsers/winjs.js 1.7 kB 0 B
packages/core/dist/error-tracking/parsers/winjs.mjs 406 B 0 B
packages/core/dist/error-tracking/types.js 1.33 kB 0 B
packages/core/dist/error-tracking/types.mjs 131 B 0 B
packages/core/dist/error-tracking/utils.js 1.8 kB 0 B
packages/core/dist/error-tracking/utils.mjs 604 B 0 B
packages/core/dist/eventemitter.js 1.78 kB 0 B
packages/core/dist/eventemitter.mjs 571 B 0 B
packages/core/dist/featureFlagUtils.js 6.5 kB 0 B
packages/core/dist/featureFlagUtils.mjs 4.28 kB 0 B
packages/core/dist/gzip.js 1.88 kB 0 B
packages/core/dist/gzip.mjs 577 B 0 B
packages/core/dist/index.js 5.7 kB 0 B
packages/core/dist/index.mjs 485 B 0 B
packages/core/dist/logger.js 2.46 kB 0 B
packages/core/dist/logger.mjs 1.17 kB 0 B
packages/core/dist/posthog-core-stateless.js 29.7 kB 0 B
packages/core/dist/posthog-core-stateless.mjs 27.1 kB 0 B
packages/core/dist/posthog-core.js 28 kB 0 B
packages/core/dist/posthog-core.mjs 24 kB 0 B
packages/core/dist/process/index.js 2.77 kB 0 B
packages/core/dist/process/index.mjs 114 B 0 B
packages/core/dist/process/spawn-local.js 1.82 kB 0 B
packages/core/dist/process/spawn-local.mjs 568 B 0 B
packages/core/dist/process/utils.js 3.12 kB 0 B
packages/core/dist/process/utils.mjs 1.15 kB 0 B
packages/core/dist/testing/index.js 2.93 kB 0 B
packages/core/dist/testing/index.mjs 79 B 0 B
packages/core/dist/testing/PostHogCoreTestClient.js 3.15 kB 0 B
packages/core/dist/testing/PostHogCoreTestClient.mjs 1.74 kB 0 B
packages/core/dist/testing/test-utils.js 2.77 kB 0 B
packages/core/dist/testing/test-utils.mjs 1.09 kB 0 B
packages/core/dist/types.js 8.2 kB 0 B
packages/core/dist/types.mjs 5.93 kB 0 B
packages/core/dist/utils/bot-detection.js 3.28 kB 0 B
packages/core/dist/utils/bot-detection.mjs 1.95 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.js 3 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.mjs 1.62 kB 0 B
packages/core/dist/utils/index.js 10.2 kB 0 B
packages/core/dist/utils/index.mjs 1.91 kB 0 B
packages/core/dist/utils/number-utils.js 2 kB 0 B
packages/core/dist/utils/number-utils.mjs 735 B 0 B
packages/core/dist/utils/promise-queue.js 2 kB 0 B
packages/core/dist/utils/promise-queue.mjs 768 B 0 B
packages/core/dist/utils/string-utils.js 1.91 kB 0 B
packages/core/dist/utils/string-utils.mjs 414 B 0 B
packages/core/dist/utils/type-utils.js 6.93 kB 0 B
packages/core/dist/utils/type-utils.mjs 3.03 kB 0 B
packages/core/dist/vendor/uuidv7.js 8.29 kB 0 B
packages/core/dist/vendor/uuidv7.mjs 6.72 kB 0 B
packages/nextjs-config/dist/config.js 5.98 kB 0 B
packages/nextjs-config/dist/config.mjs 4.68 kB 0 B
packages/nextjs-config/dist/index.js 2.24 kB 0 B
packages/nextjs-config/dist/index.mjs 30 B 0 B
packages/nextjs-config/dist/utils.js 3.83 kB 0 B
packages/nextjs-config/dist/utils.mjs 1.72 kB 0 B
packages/nextjs-config/dist/webpack-plugin.js 3.66 kB 0 B
packages/nextjs-config/dist/webpack-plugin.mjs 1.95 kB 0 B
packages/node/dist/client.js 23.1 kB 0 B
packages/node/dist/client.mjs 21.3 kB 0 B
packages/node/dist/entrypoints/index.edge.js 4.14 kB 0 B
packages/node/dist/entrypoints/index.edge.mjs 652 B 0 B
packages/node/dist/entrypoints/index.node.js 5.08 kB 0 B
packages/node/dist/entrypoints/index.node.mjs 901 B 0 B
packages/node/dist/exports.js 3.6 kB 0 B
packages/node/dist/exports.mjs 124 B 0 B
packages/node/dist/extensions/error-tracking/autocapture.js 2.65 kB 0 B
packages/node/dist/extensions/error-tracking/autocapture.mjs 1.23 kB 0 B
packages/node/dist/extensions/error-tracking/index.js 3.88 kB 0 B
packages/node/dist/extensions/error-tracking/index.mjs 2.61 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.js 8.81 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs 7.15 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.js 2.78 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.mjs 1.45 kB 0 B
packages/node/dist/extensions/express.js 2.17 kB 0 B
packages/node/dist/extensions/express.mjs 548 B 0 B
packages/node/dist/extensions/feature-flags/crypto.js 1.57 kB 0 B
packages/node/dist/extensions/feature-flags/crypto.mjs 395 B 0 B
packages/node/dist/extensions/feature-flags/feature-flags.js 27.7 kB 0 B
packages/node/dist/extensions/feature-flags/feature-flags.mjs 25.7 kB 0 B
packages/node/dist/extensions/sentry-integration.js 4.66 kB 0 B
packages/node/dist/extensions/sentry-integration.mjs 3.17 kB 0 B
packages/node/dist/storage-memory.js 1.52 kB 0 B
packages/node/dist/storage-memory.mjs 297 B 0 B
packages/node/dist/types.js 603 B 0 B
packages/node/dist/types.mjs 0 B 0 B 🆕
packages/node/dist/version.js 1.21 kB 0 B
packages/node/dist/version.mjs 46 B 0 B
packages/nuxt/dist/module.mjs 4.19 kB 0 B
packages/nuxt/dist/runtime/nitro-plugin.js 1.08 kB 0 B
packages/nuxt/dist/runtime/vue-plugin.js 1.14 kB 0 B
packages/react-native/dist/autocapture.js 4.68 kB 0 B
packages/react-native/dist/error-tracking/index.js 6.65 kB 0 B
packages/react-native/dist/error-tracking/utils.js 2.58 kB 0 B
packages/react-native/dist/frameworks/wix-navigation.js 1.3 kB 0 B
packages/react-native/dist/hooks/useFeatureFlag.js 1.49 kB 0 B
packages/react-native/dist/hooks/useFeatureFlags.js 821 B 0 B
packages/react-native/dist/hooks/useNavigationTracker.js 2.46 kB 0 B
packages/react-native/dist/hooks/usePostHog.js 467 B 0 B
packages/react-native/dist/index.js 3.12 kB 0 B
packages/react-native/dist/native-deps.js 13.9 kB 0 B
packages/react-native/dist/optional/OptionalAsyncStorage.js 299 B 0 B
packages/react-native/dist/optional/OptionalExpoApplication.js 377 B 0 B
packages/react-native/dist/optional/OptionalExpoDevice.js 347 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystem.js 386 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystemLegacy.js 423 B 0 B
packages/react-native/dist/optional/OptionalExpoLocalization.js 383 B 0 B
packages/react-native/dist/optional/OptionalReactNativeDeviceInfo.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeLocalize.js 303 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigation.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigationWix.js 443 B 0 B
packages/react-native/dist/optional/OptionalReactNativeSafeArea.js 644 B 0 B
packages/react-native/dist/optional/OptionalSessionReplay.js 455 B 0 B
packages/react-native/dist/posthog-rn.js 37 kB 0 B
packages/react-native/dist/PostHogContext.js 329 B 0 B
packages/react-native/dist/PostHogProvider.js 4.77 kB 0 B
packages/react-native/dist/storage.js 3.39 kB 0 B
packages/react-native/dist/surveys/components/BottomSection.js 1.34 kB 0 B
packages/react-native/dist/surveys/components/Cancel.js 909 B 0 B
packages/react-native/dist/surveys/components/ConfirmationMessage.js 1.58 kB 0 B
packages/react-native/dist/surveys/components/QuestionHeader.js 1.11 kB 0 B
packages/react-native/dist/surveys/components/QuestionTypes.js 10.1 kB 0 B
packages/react-native/dist/surveys/components/SurveyModal.js 3.86 kB 0 B
packages/react-native/dist/surveys/components/Surveys.js 7.18 kB 0 B
packages/react-native/dist/surveys/getActiveMatchingSurveys.js 3.69 kB 0 B
packages/react-native/dist/surveys/icons.js 7.76 kB 0 B
packages/react-native/dist/surveys/index.js 600 B 0 B
packages/react-native/dist/surveys/PostHogSurveyProvider.js 5.66 kB 0 B
packages/react-native/dist/surveys/surveys-utils.js 9.31 kB 0 B
packages/react-native/dist/surveys/useActivatedSurveys.js 3.38 kB 0 B
packages/react-native/dist/surveys/useSurveyStorage.js 2.16 kB 0 B
packages/react-native/dist/types.js 70 B 0 B
packages/react-native/dist/utils.js 539 B 0 B
packages/react-native/dist/version.js 130 B 0 B
packages/react/dist/esm/index.js 18.8 kB 0 B
packages/react/dist/umd/index.js 21.9 kB 0 B
packages/web/dist/index.cjs 13.8 kB 0 B
packages/web/dist/index.mjs 13.7 kB 0 B
tooling/rollup-utils/dist/index.js 1.17 kB 0 B

compressed-size-action

@pauldambra pauldambra requested a review from Copilot November 15, 2025 13:01
Copilot finished reviewing on behalf of pauldambra November 15, 2025 13:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new TaskQueue utility to improve page responsiveness by breaking up CPU-intensive operations and yielding to the main thread periodically. This helps reduce Interaction to Next Paint (INP) variability on pages with heavy processing.

  • Adds a reusable TaskQueue class with time-budgeting (default 30ms) to avoid blocking the main thread
  • Implements helper functions processWithYield and processAsyncWithYield for common array processing patterns
  • Integrates the task queue into request queue flushing, extension initialization, performance entry processing, and session recording event handling

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/browser/src/utils/task-queue.ts New task queue implementation with time-slicing support and helper functions for processing arrays with yielding
packages/browser/src/utils/tests/task-queue.test.ts Comprehensive test suite covering task queue functionality, error handling, and yielding behavior
packages/browser/src/request-queue.ts Updates flush callback to use processWithYield for processing request batches
packages/browser/src/posthog-core.ts Refactors extension initialization to use TaskQueue class, removing custom time-slicing logic
packages/browser/src/extensions/replay/external/network-plugin.ts Applies yielding to initial performance entry processing
packages/browser/src/extensions/replay/external/lazy-loaded-session-recorder.ts Adds yielding to queued event processing
.changeset/smooth-wolves-mix.md Changeset documenting the new feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,5 +1,5 @@
module.exports = {
testPathIgnorePatterns: ['/node_modules/', '/cypress/', '/react/', '/test_data/', '/testcafe/'],
testPathIgnorePatterns: ['/node_modules/', '/cypress/', '/react/', '/test_data/', '/testcafe/', '\\.d\\.ts$'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right, you're escaping the slash rather than the dot?

Shouldn't it be \.d'\.ts$?

logger.error('Error initializing extension:', error)
},
})
taskQueue.enqueueAll(initTasks)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not need to call a method to actually start the processing?

@@ -0,0 +1,210 @@
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't exactly like how we need to use this class, but it works, so please just merge if you think this is good.

IMO the way we should consume this is new AsyncProcessor(iterator, { timeBudgetMs: 30 }).processEach(item => doSomething(item))

This is definitely different from your idea where each item in the array is a function and you're just calling those functions, BUT it does align more with how you're using this class (list of items that need to be processed iwth the same function everytime). It basically means to me you're trying to use the wrong abstraction for the job, hence why you had to add those 2 helper functions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list of items that need to be processed iwth the same function everytime

hmmm, that's not the abstraction though

this is

list of tasks that need to be processed

they could be the same task many times but they don't have to be

right now, there's no shared task queue, but we could end up with a shared task queue, so i tried to keep it that way

(all replaceable though so 🙈)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that's exactly my point: the abstraction is "list of task that needs to be processed" while the usage is "list of items that need to be processed with the same function at all times".

If the abstraction wasn't wrong we wouldn't need that processWithYield helper where we pass the same function at all times 😇

btw, can we add an underscore to these functions by any chance to make sure people understand they're private? we need to make (all replaceable though so 🙈) true lol

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, will absorb this when my brain is not offsite-tired 😆

useEffect(() => {
posthog.init('phc_test_key_for_playground', {
api_host: '/ph-relay-xyz123',
posthog.init('sTMFPsFhdP1Ssg', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't add our production key here, people already use our key on their apps just because we have it on our posthog repo , we don't need even more people using it 😥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants