Skip to content
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

perf(query): Use long running async view for queries with poll #27758

Merged
merged 20 commits into from
Jan 28, 2025

Conversation

timgl
Copy link
Collaborator

@timgl timgl commented Jan 22, 2025

Problem

Polling is slow, doubly so when the browser is super busy fetching a bunch of other things

Changes

Use an async view that checks celery to see if the response is done. If it's not done after 50 seconds, kick it do polling instead. This avoids us having to have long timeouts in the load balancer etc. Async view means that this should not increase load on django too much (in fact, will probably reduce it as we'll be doing way fewer requests).

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Does this work well for both Cloud and self-hosted?

How did you test this code?

@timgl timgl requested a review from Twixes January 22, 2025 04:01
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.

PR Summary

This PR replaces the polling mechanism with EventSource for handling queries, aiming to improve performance and reduce latency, particularly for long-running queries.

  • Added new eventsource endpoint in /posthog/api/query.py using Django's StreamingHttpResponse for real-time query updates
  • Implemented feature flag 'query-eventsource' in /frontend/src/queries/query.ts to control EventSource functionality
  • Added queryEventSource and queryEventSourceUrl methods in /frontend/src/lib/api.ts for server-sent events handling
  • Modified execution modes to ensure proper blocking behavior for eventsource requests
  • Implemented connection abort handling and error management for EventSource connections

3 file(s) reviewed, 4 comment(s)
Edit PR Review Bot Settings | Greptile

posthog/api/query.py Outdated Show resolved Hide resolved
frontend/src/queries/query.ts Outdated Show resolved Hide resolved
frontend/src/queries/query.ts Outdated Show resolved Hide resolved
Comment on lines 2662 to 2664
queryEventSourceUrl(): string {
return new ApiRequest().queryEventSource().assembleFullUrl()
},
Copy link
Contributor

Choose a reason for hiding this comment

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

style: consider adding error handling and connection management for EventSource

posthog/api/query.py Fixed Show fixed Hide fixed
Copy link
Contributor

github-actions bot commented Jan 22, 2025

Size Change: +251 B (+0.02%)

Total Size: 1.16 MB

ℹ️ View Unchanged
Filename Size Change
frontend/dist/toolbar.js 1.16 MB +251 B (+0.02%)

compressed-size-action

@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

1 snapshot changes in total. 0 added, 1 modified, 0 deleted:

  • chromium: 0 added, 1 modified, 0 deleted (diff for shard 1)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

posthog/api/query.py Outdated Show resolved Hide resolved
@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

1 snapshot changes in total. 0 added, 1 modified, 0 deleted:

  • chromium: 0 added, 1 modified, 0 deleted (diff for shard 1)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

@timgl timgl force-pushed the use-eventsource-for-queries branch from 714d562 to 72478d3 Compare January 23, 2025 02:40
@timgl timgl changed the title perf(query): Use eventsource for query perf(query): Use long running async view for queries with poll Jan 23, 2025
posthog/api/query.py Fixed Show fixed Hide fixed
posthog/api/query.py Fixed Show fixed Hide fixed
Copy link
Member

@Twixes Twixes left a comment

Choose a reason for hiding this comment

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

That's a great idea – the wins here definitely are for queries under 60s, and the difference above that wouldn't matter as much. However, I think we can much more simply build this into the existing QueryViewSet.create method, instead of adding a separate hand-rolled request handler outside of DRF. Let's just add this polling-in-the-backend approach to that viewset method

frontend/src/queries/query.ts Outdated Show resolved Hide resolved
frontend/src/lib/api.ts Outdated Show resolved Hide resolved
ASYNC_FALLBACK_TO_POLLING_TIMEOUT = 50


async def query_async(request: Request, *args, **kwargs) -> HttpResponse:
Copy link
Member

Choose a reason for hiding this comment

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

Let's not overload the term async so much, because async queries already are a thing in the existing query endpoint. This is rather an UX optimization to async querying.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah fair.. I'm just going to roll it out, then I'll make this the default way for queries to happen once we've rolled it out

@timgl
Copy link
Collaborator Author

timgl commented Jan 23, 2025

@Twixes not sure what you mean by adding it to the existing viewset. DRF doesn’t support async and the performance impact of having a ton of open connections would be high i suspect

Copy link
Member

@Twixes Twixes left a comment

Choose a reason for hiding this comment

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

Ohh, so annoying DRF doesn't support async. Looks like they don't even really have plans. So in terms of duplicated logic, proposing a non-DRF but still simpler approach below:

posthog/api/query.py Outdated Show resolved Hide resolved
@posthog-bot
Copy link
Contributor

It looks like the code of hogql-parser has changed since last push, but its version stayed the same at 1.0.454. 👀
Make sure to resolve this in hogql_parser/setup.py before merging!

@timgl timgl force-pushed the use-eventsource-for-queries branch from 6435168 to 3f264a3 Compare January 28, 2025 01:43
@posthog-bot
Copy link
Contributor

It looks like the code of hogql-parser has changed since last push, but its version stayed the same at 1.0.454. 👀
Make sure to resolve this in hogql_parser/setup.py before merging!

@timgl timgl force-pushed the use-eventsource-for-queries branch from 3f264a3 to f930a4b Compare January 28, 2025 01:47
@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

1 snapshot changes in total. 0 added, 1 modified, 0 deleted:

  • chromium: 0 added, 1 modified, 0 deleted (diff for shard 1)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

1 snapshot changes in total. 0 added, 1 modified, 0 deleted:

  • chromium: 0 added, 1 modified, 0 deleted (diff for shard 1)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

Comment on lines 889 to 891
public queryAsync(teamId?: TeamType['id']): ApiRequest {
return this.environmentsDetail(teamId).addPathComponent('query_async')
}
Copy link
Member

Choose a reason for hiding this comment

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

Still I'm gonna say it's a bad idea to use "query_async" for something on top of existing async querying. More appropriate would be queryStream/query_stream

Copy link
Member

Choose a reason for hiding this comment

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

Or not "stream" anymore, since we're not streaming 🤔 More like query_awaitingquery_v2?

Copy link
Member

Choose a reason for hiding this comment

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

Pushed query_awaiting, steppin on toes

@Twixes Twixes force-pushed the use-eventsource-for-queries branch from 8ca8e43 to 8ff5ca3 Compare January 28, 2025 18:20
Copy link
Member

@Twixes Twixes left a comment

Choose a reason for hiding this comment

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

Looks good, let's try it out. One thing to note: this only helps with ad-hoc queries (primarily the insight editor), but not insight/dashboard loading (since these endpoints have querying built-in, for minimized rounds trips indeed)

@Twixes Twixes force-pushed the use-eventsource-for-queries branch from 9f75598 to fa0ac07 Compare January 28, 2025 19:06
@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

1 snapshot changes in total. 0 added, 1 modified, 0 deleted:

  • chromium: 0 added, 1 modified, 0 deleted (diff for shard 1)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

1 snapshot changes in total. 0 added, 1 modified, 0 deleted:

  • chromium: 0 added, 1 modified, 0 deleted (diff for shard 1)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

@timgl timgl merged commit 330e37b into master Jan 28, 2025
99 checks passed
@timgl timgl deleted the use-eventsource-for-queries branch January 28, 2025 20:11
adamleithp pushed a commit that referenced this pull request Jan 29, 2025
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Michael Matloka <michael@matloka.com>
adamleithp pushed a commit that referenced this pull request Jan 29, 2025
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Michael Matloka <michael@matloka.com>
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