diff --git a/.github/workflows/ci-e2e.yml b/.github/workflows/ci-e2e.yml
index c633b70075a..a36a788b35a 100644
--- a/.github/workflows/ci-e2e.yml
+++ b/.github/workflows/ci-e2e.yml
@@ -191,7 +191,7 @@ jobs:
OBJECT_STORAGE_SECRET_ACCESS_KEY=object_storage_root_password
GITHUB_ACTION_RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
CELERY_METRICS_PORT=8999
- CLOUD_DEPLOYMENT=1
+ CLOUD_DEPLOYMENT=E2E
EOT
- name: Start PostHog
diff --git a/.run/Celery Threads.run.xml b/.run/Celery Threads.run.xml
index b437920c484..f57ed16d523 100644
--- a/.run/Celery Threads.run.xml
+++ b/.run/Celery Threads.run.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/.vscode/launch.json b/.vscode/launch.json
index cd681198de8..2df87ecfa08 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -94,7 +94,7 @@
},
"request": "launch",
"program": "${workspaceFolder}/manage.py",
- "args": ["run_autoreload_celery"],
+ "args": ["run_autoreload_celery", "--type=worker"],
"console": "integratedTerminal",
"python": "${workspaceFolder}/env/bin/python",
"cwd": "${workspaceFolder}",
diff --git a/bin/e2e-test-runner b/bin/e2e-test-runner
index 2eb0ae0455a..289e8057cc8 100755
--- a/bin/e2e-test-runner
+++ b/bin/e2e-test-runner
@@ -46,15 +46,13 @@ do
fi
done
-export DEBUG=1
-export NO_RESTART_LOOP=1
export CYPRESS_BASE_URL=http://localhost:8080
export SECURE_COOKIES=0
export SKIP_SERVICE_VERSION_REQUIREMENTS=1
export KAFKA_HOSTS=kafka:9092
export CLICKHOUSE_DATABASE=posthog_test
-export TEST=1 # Plugin server and kafka revert to 'default' Clickhouse database if TEST is not set
export CLICKHOUSE_SECURE=0
+export JS_URL=http://localhost:8234
export E2E_TESTING=1
export SECRET_KEY=e2e_test
export EMAIL_HOST=email.test.posthog.net
@@ -66,7 +64,9 @@ export PGUSER="${PGUSER:=posthog}"
export PGPASSWORD="${PGPASSWORD:=posthog}"
export PGPORT="${PGPORT:=5432}"
export DATABASE_URL="postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:${PGPORT}/${DATABASE}"
-export CLOUD_DEPLOYMENT=1
+export CLOUD_DEPLOYMENT=E2E
+
+source ./bin/celery-queues.env
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
@@ -92,8 +92,7 @@ setupDev() {
python manage.py setup_dev &
}
-nc -z localhost 9092 || ( echo -e "\033[0;31mKafka isn't running. Please run\n\tdocker compose -f docker-compose.dev.yml up zookeeper kafka clickhouse db redis\nI'll wait while you do that.\033[0m" ; bin/check_kafka_clickhouse_up )
-wget -nv -t1 --spider 'http://localhost:8123/' || ( echo -e "\033[0;31mClickhouse isn't running. Please run\n\tdocker compose -f docker-compose.dev.yml up zookeeper kafka clickhouse db redis.\nI'll wait while you do that.\033[0m" ; bin/check_kafka_clickhouse_up )
+bin/check_kafka_clickhouse_up
$SKIP_RECREATE_DATABASE || recreateDatabases
$SKIP_MIGRATE || migrateDatabases
@@ -103,4 +102,6 @@ $SKIP_SETUP_DEV || setupDev
# Only start webpack if not already running
nc -vz 127.0.0.1 8234 2> /dev/null || ./bin/start-frontend &
pnpm dlx cypress open --config-file cypress.e2e.config.ts &
+uv pip install -r requirements.txt -r requirements-dev.txt
+python manage.py run_autoreload_celery --type=worker &
python manage.py runserver 8080
diff --git a/bin/start-worker b/bin/start-worker
index 0c73050ddfd..aa7caeefc7b 100755
--- a/bin/start-worker
+++ b/bin/start-worker
@@ -7,8 +7,8 @@ trap 'kill $(jobs -p)' EXIT
source ./bin/celery-queues.env
# start celery worker with heartbeat (-B)
-SKIP_ASYNC_MIGRATIONS_SETUP=0 CELERY_WORKER_QUEUES=$CELERY_WORKER_QUEUES celery -A posthog worker --without-heartbeat --without-mingle --pool=threads -Ofair -n node@%h &
-celery -A posthog beat -S redbeat.RedBeatScheduler &
+python manage.py run_autoreload_celery --type=worker &
+python manage.py run_autoreload_celery --type=beat &
if [[ "$PLUGIN_SERVER_IDLE" != "1" && "$PLUGIN_SERVER_IDLE" != "true" ]]; then
./bin/plugin-server
diff --git a/cypress.e2e.config.ts b/cypress.e2e.config.ts
index 23f117a16fc..f9a504aaf6e 100644
--- a/cypress.e2e.config.ts
+++ b/cypress.e2e.config.ts
@@ -99,15 +99,16 @@ export default defineConfig({
const redisClient = await createClient()
.on('error', (err) => console.log('Redis client error', err))
.connect()
- for await (const key of redisClient.scanIterator({
- TYPE: 'string',
- MATCH: '*cache*',
- COUNT: 100,
- })) {
+ // Clear cache
+ for await (const key of redisClient.scanIterator({ TYPE: 'string', MATCH: '*cache*', COUNT: 500 })) {
+ await redisClient.del(key)
+ }
+ // Also clear the more ephemeral async query statuses
+ for await (const key of redisClient.scanIterator({ TYPE: 'string', MATCH: 'query_async*', COUNT: 500 })) {
await redisClient.del(key)
}
await redisClient.quit()
- return null
+ return null // Cypress requires _some_ return value
},
})
diff --git a/cypress/e2e/dashboard.cy.ts b/cypress/e2e/dashboard.cy.ts
index f047f768ea1..c67a21f2e24 100644
--- a/cypress/e2e/dashboard.cy.ts
+++ b/cypress/e2e/dashboard.cy.ts
@@ -61,6 +61,46 @@ describe('Dashboard', () => {
}
})
+ it('Refreshing dashboard works', () => {
+ const dashboardName = randomString('Dashboard with insights')
+ const insightName = randomString('insight to add to dashboard')
+
+ // Create and visit a dashboard to get it into turbo mode cache
+ dashboards.createAndGoToEmptyDashboard(dashboardName)
+
+ insight.create(insightName)
+
+ insight.addInsightToDashboard(dashboardName, { visitAfterAdding: true })
+
+ cy.get('.CardMeta h4').should('have.text', insightName)
+ cy.get('h4').contains('Refreshing').should('not.exist')
+ cy.get('main').contains('There are no matching events for this query').should('not.exist')
+
+ cy.intercept('GET', /\/api\/projects\/\d+\/dashboard_templates/, (req) => {
+ req.reply((response) => {
+ response.body.results[0].variables = [
+ {
+ id: 'id',
+ name: 'Unique variable name',
+ type: 'event',
+ default: {},
+ required: true,
+ description: 'description',
+ },
+ ]
+ return response
+ })
+ })
+
+ // refresh the dashboard by changing date range
+ cy.get('[data-attr="date-filter"]').click()
+ cy.contains('span', 'Last 14 days').click()
+ cy.contains('span', 'Apply and save dashboard').click()
+
+ cy.contains('span[class="text-primary text-sm font-medium"]', 'Refreshing').should('not.exist')
+ cy.get('span').contains('Refreshing').should('not.exist')
+ })
+
it('Shows details when moving between dashboard and insight', () => {
const dashboardName = randomString('Dashboard')
const insightName = randomString('DashboardInsight')
diff --git a/cypress/e2e/insights-saved.cy.ts b/cypress/e2e/insights-saved.cy.ts
new file mode 100644
index 00000000000..0eb1ea2e5a3
--- /dev/null
+++ b/cypress/e2e/insights-saved.cy.ts
@@ -0,0 +1,44 @@
+import { urls } from 'scenes/urls'
+
+import { createInsight } from '../productAnalytics'
+
+chai.Assertion.addMethod('neverHaveChild', function (childSelector) {
+ this._obj.on('DOMNodeInserted', () => {
+ const matchCount = cy.$$(childSelector, this._obj).length
+ if (matchCount > 0) {
+ throw new Error(
+ `Expected element to never have child ${childSelector}, but found ${matchCount} match${
+ matchCount > 1 ? 'es' : ''
+ }`
+ )
+ }
+ })
+})
+
+// For tests related to trends please check trendsElements.js
+// insight tests were split up because Cypress was struggling with this many tests in one file🙈
+describe('Insights - saved', () => {
+ it('Data is available immediately', () => {
+ createInsight('saved insight').then((newInsightId) => {
+ cy.get('[data-attr=trend-line-graph]').should('exist') // Results cached
+ cy.visit(urls.insightView(newInsightId)) // Full refresh
+ cy.get('.InsightViz').should('exist').should('neverHaveChild', '.insight-empty-state') // Only cached data
+ cy.get('[data-attr=trend-line-graph]').should('exist')
+ })
+ })
+
+ it('If cache empty, initiate async refresh', () => {
+ cy.intercept('GET', /\/api\/projects\/\d+\/insights\/?\?[^/]*?refresh=async/).as('getInsightsRefreshAsync')
+ let newInsightId: string
+ createInsight('saved insight').then((insightId) => {
+ newInsightId = insightId
+ })
+ cy.task('resetInsightCache').then(() => {
+ cy.visit(urls.insightView(newInsightId)) // Full refresh
+ cy.get('.insight-empty-state').should('exist') // There should be a loading state for a moment
+ cy.wait('@getInsightsRefreshAsync').then(() => {
+ cy.get('[data-attr=trend-line-graph]').should('exist')
+ })
+ })
+ })
+})
diff --git a/cypress/productAnalytics/index.ts b/cypress/productAnalytics/index.ts
index 6c907128617..cedfa970c82 100644
--- a/cypress/productAnalytics/index.ts
+++ b/cypress/productAnalytics/index.ts
@@ -192,11 +192,15 @@ export const dashboard = {
},
}
-export function createInsight(insightName: string): void {
+export function createInsight(insightName: string): Cypress.Chainable {
savedInsights.createNewInsightOfType('TRENDS')
insight.applyFilter()
insight.editName(insightName)
insight.save()
+ // return insight id from the url
+ return cy.url().then((url) => {
+ return url.split('/').at(-1)
+ })
}
export function duplicateDashboardFromMenu(duplicateTiles = false): void {
diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts
index e65787faec2..f2fad982870 100644
--- a/cypress/support/e2e.ts
+++ b/cypress/support/e2e.ts
@@ -23,6 +23,10 @@ Cypress.on('window:before:load', (win) => {
win._cypress_posthog_captures = []
})
+before(() => {
+ cy.task('resetInsightCache') // Reset insight cache before each suite
+})
+
beforeEach(() => {
Cypress.env('POSTHOG_PROPERTY_CURRENT_TEST_TITLE', Cypress.currentTest.title)
Cypress.env('POSTHOG_PROPERTY_CURRENT_TEST_FULL_TITLE', Cypress.currentTest.titlePath.join(' > '))
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts
index ac2169e4c67..6471475038e 100644
--- a/frontend/src/lib/api.ts
+++ b/frontend/src/lib/api.ts
@@ -899,14 +899,16 @@ const api = {
insights: {
loadInsight(
shortId: InsightModel['short_id'],
- basic?: boolean
+ basic?: boolean,
+ refresh?: RefreshType
): Promise>> {
return new ApiRequest()
.insights()
.withQueryString(
toParams({
short_id: encodeURIComponent(shortId),
- basic: basic,
+ basic,
+ refresh,
})
)
.get()
diff --git a/frontend/src/queries/nodes/DataNode/dataNodeLogic.ts b/frontend/src/queries/nodes/DataNode/dataNodeLogic.ts
index 307969e8426..afcf55bb7cf 100644
--- a/frontend/src/queries/nodes/DataNode/dataNodeLogic.ts
+++ b/frontend/src/queries/nodes/DataNode/dataNodeLogic.ts
@@ -128,9 +128,14 @@ export const dataNodeLogic = kea([
if (oldProps.query?.kind && props.query.kind !== oldProps.query.kind) {
actions.clearResponse()
}
- if (
+ const hasQueryChanged = !queryEqual(props.query, oldProps.query)
+ const queryStatus = (props.cachedResults?.query_status || null) as QueryStatus | null
+ if (hasQueryChanged && queryStatus?.complete === false) {
+ // If there is an incomplete query, load the data with the same query_id which should return its status
+ actions.loadData(undefined, queryStatus.id)
+ } else if (
+ hasQueryChanged &&
!(props.cachedResults && props.key.includes('dashboard')) && // Don't load data on dashboard if cached results are available
- !queryEqual(props.query, oldProps.query) &&
(!props.cachedResults ||
(isInsightQueryNode(props.query) && !props.cachedResults['result'] && !props.cachedResults['results']))
) {
@@ -141,7 +146,7 @@ export const dataNodeLogic = kea([
}
}),
actions({
- loadData: (refresh = false) => ({ refresh, queryId: uuid() }),
+ loadData: (refresh = false, queryId?: string) => ({ refresh, queryId: queryId || uuid() }),
abortAnyRunningQuery: true,
abortQuery: (payload: { queryId: string }) => payload,
cancelQuery: true,
@@ -166,7 +171,8 @@ export const dataNodeLogic = kea([
return props.cachedResults
}
- if (props.cachedResults && !refresh) {
+ const queryStatus = (props.cachedResults?.query_status || null) as QueryStatus | null
+ if (props.cachedResults && !refresh && queryStatus?.complete !== false) {
if (props.cachedResults['result'] || props.cachedResults['results']) {
return props.cachedResults
}
diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json
index cbe0a87dc08..3984f612d6a 100644
--- a/frontend/src/queries/schema.json
+++ b/frontend/src/queries/schema.json
@@ -151,6 +151,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -2230,6 +2234,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -2285,6 +2293,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -2357,6 +2369,10 @@
"description": "Input query string",
"type": "string"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -2398,6 +2414,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/WebOverviewItem"
@@ -2446,6 +2466,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -2487,6 +2511,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -2537,6 +2565,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {},
"timings": {
"description": "Measured timings for different parts of the query generation process",
@@ -2583,6 +2615,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/ErrorTrackingGroup"
@@ -3439,6 +3475,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/ErrorTrackingGroup"
@@ -3777,6 +3817,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -3947,6 +3991,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"$ref": "#/definitions/FunnelCorrelationResult"
},
@@ -4490,6 +4538,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"anyOf": [
{
@@ -4965,6 +5017,10 @@
"description": "Input query string",
"type": "string"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -5765,6 +5821,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"type": "object"
@@ -6081,6 +6141,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"type": "object"
@@ -6331,6 +6395,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -6386,6 +6454,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -6537,6 +6609,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/TimelineEntry"
@@ -6621,6 +6697,10 @@
"description": "Input query string",
"type": "string"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -6720,6 +6800,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/WebOverviewItem"
@@ -6768,6 +6852,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -6809,6 +6897,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -6859,6 +6951,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {},
"timings": {
"description": "Measured timings for different parts of the query generation process",
@@ -6905,6 +7001,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/ErrorTrackingGroup"
@@ -6957,6 +7057,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -7012,6 +7116,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"items": {},
@@ -7084,6 +7192,10 @@
"description": "Input query string",
"type": "string"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -7125,6 +7237,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/WebOverviewItem"
@@ -7173,6 +7289,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -7214,6 +7334,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -7264,6 +7388,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {},
"timings": {
"description": "Measured timings for different parts of the query generation process",
@@ -7310,6 +7438,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/ErrorTrackingGroup"
@@ -7342,6 +7474,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"type": "object"
@@ -7374,6 +7510,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"anyOf": [
{
@@ -7416,6 +7556,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/RetentionResult"
@@ -7448,37 +7592,9 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
- "results": {
- "items": {
- "type": "object"
- },
- "type": "array"
- },
- "timings": {
- "description": "Measured timings for different parts of the query generation process",
- "items": {
- "$ref": "#/definitions/QueryTiming"
- },
- "type": "array"
- }
- },
- "required": ["results"],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "error": {
- "description": "Query error. Returned only if 'explain' or `modifiers.debug` is true. Throws an error otherwise.",
- "type": "string"
- },
- "hogql": {
- "description": "Generated HogQL query.",
- "type": "string"
- },
- "modifiers": {
- "$ref": "#/definitions/HogQLQueryModifiers",
- "description": "Modifiers used when performing the query"
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
},
"results": {
"items": {
@@ -7512,6 +7628,46 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
+ "results": {
+ "items": {
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "timings": {
+ "description": "Measured timings for different parts of the query generation process",
+ "items": {
+ "$ref": "#/definitions/QueryTiming"
+ },
+ "type": "array"
+ }
+ },
+ "required": ["results"],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "error": {
+ "description": "Query error. Returned only if 'explain' or `modifiers.debug` is true. Throws an error otherwise.",
+ "type": "string"
+ },
+ "hogql": {
+ "description": "Generated HogQL query.",
+ "type": "string"
+ },
+ "modifiers": {
+ "$ref": "#/definitions/HogQLQueryModifiers",
+ "description": "Modifiers used when performing the query"
+ },
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"type": "object"
@@ -7557,6 +7713,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"$ref": "#/definitions/FunnelCorrelationResult"
},
@@ -8022,6 +8182,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/RetentionResult"
@@ -8297,6 +8461,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {},
"timings": {
"description": "Measured timings for different parts of the query generation process",
@@ -8388,6 +8556,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/TimelineEntry"
@@ -8546,6 +8718,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"type": "object"
@@ -8613,6 +8789,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -8929,6 +9109,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"type": "object"
@@ -9092,6 +9276,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {
"$ref": "#/definitions/WebOverviewItem"
@@ -9220,6 +9408,10 @@
"offset": {
"type": "integer"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
@@ -9304,6 +9496,10 @@
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
+ "query_status": {
+ "$ref": "#/definitions/QueryStatus",
+ "description": "Query status indicates whether next to the provided data, a query is still running."
+ },
"results": {
"items": {},
"type": "array"
diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts
index cd162e2fa36..3db53c8204d 100644
--- a/frontend/src/queries/schema.ts
+++ b/frontend/src/queries/schema.ts
@@ -255,6 +255,7 @@ export interface HogQueryResponse {
bytecode?: any[]
coloredBytecode?: any[]
stdout?: string
+ query_status?: never
}
export interface HogQuery extends DataNode {
@@ -276,6 +277,7 @@ export interface HogQLMetadataResponse {
errors: HogQLNotice[]
warnings: HogQLNotice[]
notices: HogQLNotice[]
+ query_status?: never
}
export interface AutocompleteCompletionItem {
@@ -340,6 +342,7 @@ export interface HogQLAutocompleteResponse {
incomplete_list: boolean
/** Measured timings for different parts of the query generation process */
timings?: QueryTiming[]
+ query_status?: never
}
export enum HogLanguage {
@@ -1020,6 +1023,8 @@ export interface AnalyticsQueryResponseBase {
error?: string
/** Modifiers used when performing the query */
modifiers?: HogQLQueryModifiers
+ /** Query status indicates whether next to the provided data, a query is still running. */
+ query_status?: QueryStatus
}
interface CachedQueryResponseMixin {
diff --git a/frontend/src/scenes/dashboard/dashboardLogic.tsx b/frontend/src/scenes/dashboard/dashboardLogic.tsx
index 3ef98a53155..00ca504a40d 100644
--- a/frontend/src/scenes/dashboard/dashboardLogic.tsx
+++ b/frontend/src/scenes/dashboard/dashboardLogic.tsx
@@ -1031,7 +1031,7 @@ export const dashboardLogic = kea([
insight,
dashboardId,
queryId,
- 'async',
+ 'force_cache',
methodOptions
)
dashboardsModel.actions.updateDashboardInsight(polledInsight)
diff --git a/frontend/src/scenes/insights/insightLogic.tsx b/frontend/src/scenes/insights/insightLogic.tsx
index 73016f93038..5eb33ffd6b6 100644
--- a/frontend/src/scenes/insights/insightLogic.tsx
+++ b/frontend/src/scenes/insights/insightLogic.tsx
@@ -123,8 +123,7 @@ export const insightLogic = kea([
{
loadInsight: async ({ shortId }, breakpoint) => {
await breakpoint(100)
- const response = await api.insights.loadInsight(shortId)
-
+ const response = await api.insights.loadInsight(shortId, undefined, 'async')
if (response?.results?.[0]) {
return response.results[0]
}
diff --git a/posthog/caching/insight_caching_state.py b/posthog/caching/insight_caching_state.py
index 8fde044e500..ff729d7c801 100644
--- a/posthog/caching/insight_caching_state.py
+++ b/posthog/caching/insight_caching_state.py
@@ -181,7 +181,7 @@ def sync_insight_caching_state(
# This is a best-effort kind synchronization, safe to ignore errors
logger.warn(
"Failed to sync InsightCachingState, ignoring",
- exception=err,
+ exception=str(err),
team_id=team_id,
insight_id=insight_id,
dashboard_tile_id=dashboard_tile_id,
diff --git a/posthog/clickhouse/table_engines.py b/posthog/clickhouse/table_engines.py
index b67ef9be5bc..9f959216fbd 100644
--- a/posthog/clickhouse/table_engines.py
+++ b/posthog/clickhouse/table_engines.py
@@ -49,7 +49,7 @@ class MergeTreeEngine:
shard_key, replica_key = "noshard", "{replica}-{shard}"
# ZK is not automatically cleaned up after DROP TABLE. Avoid zk path conflicts in tests by generating unique paths.
- if settings.TEST and self.zookeeper_path_key is None or self.force_unique_zk_path:
+ if (settings.TEST or settings.E2E_TESTING) and self.zookeeper_path_key is None or self.force_unique_zk_path:
self.set_zookeeper_path_key(str(uuid.uuid4()))
if self.zookeeper_path_key is not None:
diff --git a/posthog/management/commands/migrate_clickhouse.py b/posthog/management/commands/migrate_clickhouse.py
index 5511b8d07ee..a9469202095 100644
--- a/posthog/management/commands/migrate_clickhouse.py
+++ b/posthog/management/commands/migrate_clickhouse.py
@@ -60,7 +60,7 @@ class Command(BaseCommand):
password=CLICKHOUSE_PASSWORD,
cluster=CLICKHOUSE_CLUSTER,
verify_ssl_cert=False,
- randomize_replica_paths=settings.TEST,
+ randomize_replica_paths=settings.TEST or settings.E2E_TESTING,
)
if options["plan"] or options["check"]:
print("List of clickhouse migrations to be applied:")
diff --git a/posthog/management/commands/run_autoreload_celery.py b/posthog/management/commands/run_autoreload_celery.py
index b0faa088b66..cefb49df0ed 100644
--- a/posthog/management/commands/run_autoreload_celery.py
+++ b/posthog/management/commands/run_autoreload_celery.py
@@ -1,3 +1,4 @@
+from typing import Literal
import django
from django.core.management.base import BaseCommand
@@ -10,26 +11,34 @@ from django.utils import autoreload # noqa: E402
class Command(BaseCommand):
- help = "Wrap celery in djangos auto reload functionality"
+ help = "Run Celery wrapped in Django's auto-reload feature"
+
+ def add_arguments(self, parser):
+ parser.add_argument("--type", type=str, choices=("worker", "beat"), help="Process type")
def handle(self, *args, **options):
- autoreload.run_with_reloader(self.run_celery_worker)
+ autoreload.run_with_reloader(lambda: self.run_celery_worker(options["type"]))
- def run_celery_worker(self):
+ @staticmethod
+ def run_celery_worker(type: Literal["worker", "beat"]):
from posthog.celery import app as celery_app
- queues = [q.value for q in CeleryQueue]
-
- args = [
- "-A",
- "posthog",
- "worker",
- "-B",
- "--pool=threads",
- f"--queues={','.join(queues)}",
- "-Ofair",
- "-n",
- "node@%h",
- ]
+ args = (
+ [
+ "-A",
+ "posthog",
+ "worker",
+ "--pool=threads",
+ f"--queues={','.join(q.value for q in CeleryQueue)}",
+ ]
+ if type == "worker"
+ else [
+ "-A",
+ "posthog",
+ "beat",
+ "--scheduler",
+ "redbeat.RedBeatScheduler",
+ ]
+ )
celery_app.worker_main(args)
diff --git a/posthog/schema.py b/posthog/schema.py
index 0e81729b65f..bca2db0f409 100644
--- a/posthog/schema.py
+++ b/posthog/schema.py
@@ -972,6 +972,9 @@ class SessionAttributionExplorerQueryResponse(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: Any
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1040,6 +1043,9 @@ class StickinessQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[dict[str, Any]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1090,6 +1096,9 @@ class TestBasicQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1194,6 +1203,9 @@ class TrendsQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[dict[str, Any]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1265,6 +1277,9 @@ class WebOverviewQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[WebOverviewItem]
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -1308,6 +1323,9 @@ class WebStatsTableQueryResponse(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -1329,6 +1347,9 @@ class WebTopClicksQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -1354,6 +1375,9 @@ class ActorsQueryResponse(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: int
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1900,6 +1924,9 @@ class Response(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1924,6 +1951,9 @@ class Response1(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: int
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -1945,6 +1975,9 @@ class Response3(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[WebOverviewItem]
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -1968,6 +2001,9 @@ class Response4(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -1989,6 +2025,9 @@ class Response5(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2013,6 +2052,9 @@ class Response6(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: Any
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2036,6 +2078,9 @@ class Response7(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[ErrorTrackingGroup]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2124,6 +2169,9 @@ class ErrorTrackingQueryResponse(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[ErrorTrackingGroup]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2157,6 +2205,9 @@ class EventsQueryResponse(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2191,6 +2242,9 @@ class FunnelCorrelationResponse(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: FunnelCorrelationResult
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2230,6 +2284,9 @@ class FunnelsQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: Union[FunnelTimeToConvertResults, list[dict[str, Any]], list[list[dict[str, Any]]]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2316,6 +2373,9 @@ class HogQLQueryResponse(BaseModel):
)
offset: Optional[int] = None
query: Optional[str] = Field(default=None, description="Input query string")
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2377,6 +2437,9 @@ class LifecycleQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[dict[str, Any]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2402,6 +2465,9 @@ class PathsQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[dict[str, Any]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2435,6 +2501,9 @@ class QueryResponseAlternative1(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2459,6 +2528,9 @@ class QueryResponseAlternative2(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: int
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2492,6 +2564,9 @@ class QueryResponseAlternative4(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[TimelineEntry]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2518,6 +2593,9 @@ class QueryResponseAlternative6(BaseModel):
)
offset: Optional[int] = None
query: Optional[str] = Field(default=None, description="Input query string")
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2550,6 +2628,9 @@ class QueryResponseAlternative9(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[WebOverviewItem]
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2573,6 +2654,9 @@ class QueryResponseAlternative10(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2594,6 +2678,9 @@ class QueryResponseAlternative11(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2618,6 +2705,9 @@ class QueryResponseAlternative12(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: Any
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2641,6 +2731,9 @@ class QueryResponseAlternative13(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[ErrorTrackingGroup]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2663,6 +2756,9 @@ class QueryResponseAlternative14(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2687,6 +2783,9 @@ class QueryResponseAlternative15(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: int
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[list]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2714,6 +2813,9 @@ class QueryResponseAlternative16(BaseModel):
)
offset: Optional[int] = None
query: Optional[str] = Field(default=None, description="Input query string")
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2735,6 +2837,9 @@ class QueryResponseAlternative17(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[WebOverviewItem]
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2758,6 +2863,9 @@ class QueryResponseAlternative18(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2779,6 +2887,9 @@ class QueryResponseAlternative19(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
samplingRate: Optional[SamplingRate] = None
timings: Optional[list[QueryTiming]] = Field(
@@ -2803,6 +2914,9 @@ class QueryResponseAlternative20(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: Any
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2826,6 +2940,9 @@ class QueryResponseAlternative21(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[ErrorTrackingGroup]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2844,6 +2961,9 @@ class QueryResponseAlternative22(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[dict[str, Any]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2862,6 +2982,9 @@ class QueryResponseAlternative23(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: Union[FunnelTimeToConvertResults, list[dict[str, Any]], list[list[dict[str, Any]]]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2880,6 +3003,9 @@ class QueryResponseAlternative25(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[dict[str, Any]]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -2902,6 +3028,9 @@ class QueryResponseAlternative28(BaseModel):
default=None, description="Modifiers used when performing the query"
)
offset: Optional[int] = None
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: FunnelCorrelationResult
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -3035,6 +3164,9 @@ class SessionsTimelineQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[TimelineEntry]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -3259,6 +3391,9 @@ class Response2(BaseModel):
)
offset: Optional[int] = None
query: Optional[str] = Field(default=None, description="Input query string")
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -3791,6 +3926,9 @@ class QueryResponseAlternative24(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[RetentionResult]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
@@ -3809,6 +3947,9 @@ class RetentionQueryResponse(BaseModel):
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
+ query_status: Optional[QueryStatus] = Field(
+ default=None, description="Query status indicates whether next to the provided data, a query is still running."
+ )
results: list[RetentionResult]
timings: Optional[list[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
diff --git a/posthog/settings/base_variables.py b/posthog/settings/base_variables.py
index b9f5ef7511c..22395d947c6 100644
--- a/posthog/settings/base_variables.py
+++ b/posthog/settings/base_variables.py
@@ -14,8 +14,9 @@ DEBUG: bool = get_from_env("DEBUG", False, type_cast=str_to_bool)
TEST = "test" in sys.argv or sys.argv[0].endswith("pytest") or get_from_env("TEST", False, type_cast=str_to_bool) # type: bool
DEMO: bool = get_from_env("DEMO", False, type_cast=str_to_bool) # Whether this is a managed demo environment
CLOUD_DEPLOYMENT: str | None = get_from_env(
- "CLOUD_DEPLOYMENT", optional=True
-) # "US", "EU", or "DEV" - unset on self-hosted
+ "CLOUD_DEPLOYMENT",
+ optional=True, # "US", "EU", "DEV", or "E2E" - unset on self-hosted
+)
SELF_CAPTURE: bool = get_from_env("SELF_CAPTURE", DEBUG and not DEMO, type_cast=str_to_bool)
E2E_TESTING: bool = get_from_env(
"E2E_TESTING", False, type_cast=str_to_bool
@@ -24,7 +25,7 @@ OPT_OUT_CAPTURE: bool = get_from_env("OPT_OUT_CAPTURE", False, type_cast=str_to_
BENCHMARK: bool = get_from_env("BENCHMARK", False, type_cast=str_to_bool)
if E2E_TESTING:
logger.warning(
- ["️WARNING! E2E_TESTING is set to `True`. This is a security vulnerability unless you are running tests."]
+ "️WARNING! Environment variable E2E_TESTING is enabled. This is a security vulnerability unless you are running tests."
)
IS_COLLECT_STATIC = len(sys.argv) > 1 and sys.argv[1] == "collectstatic"