fix: serve index disk storage sizes from /srch/ endpoint (#8511)

* [ee] fix: serve index disk storage sizes from /srch/ endpoint

On multi-container deployments, the API server doesn't have the index
files on its local disk, so disk size was always reported as 0.0B.

Added a new GET /srch/index/storage/disk endpoint that calculates disk
sizes on the indexer process (which owns the files). The frontend now
fetches disk sizes from this endpoint in parallel with the status call.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to 71aab648925f31cde37efd31d79a7f3a977fd42a

This commit updates the EE repository reference after PR #480 was merged in windmill-ee-private.

Previous ee-repo-ref: b3e0000e2528809302c18f36930aebf3d004747a

New ee-repo-ref: 71aab648925f31cde37efd31d79a7f3a977fd42a

Automated by sync-ee-ref workflow.

* chore: update ee-repo-ref to indexer-disk-storage-zero branch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update sqlx metadata and ee-repo-ref

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
Ruben Fiszel
2026-03-25 07:56:45 +00:00
committed by GitHub
parent 0db21aa6b7
commit e3620e074e
11 changed files with 64 additions and 228 deletions
@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM usr WHERE workspace_id = $1 AND disabled = false",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null
]
},
"hash": "21f4840f60e8310d7b7efcba7483e69e4ef8821c6cbf3b4f296b3853d95692af"
}
@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT parent_job, flow_step_id FROM v2_job WHERE id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "parent_job",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "flow_step_id",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
true,
true
]
},
"hash": "32ca7941db013dacd2479962fa9ed5c8c64daec45ba820a6c8f7d7ab76cc40c9"
}
@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH dk AS (\n INSERT INTO debounce_key (job_id, key)\n VALUES ($1, $2)\n ON CONFLICT (key)\n DO UPDATE SET\n previous_job_id = debounce_key.job_id,\n job_id = EXCLUDED.job_id,\n debounced_times = debounce_key.debounced_times + 1\n RETURNING\n debounced_times,\n first_started_at,\n previous_job_id AS job_id_to_debounce\n ), _batch AS (\n INSERT INTO v2_job_debounce_batch (id, debounce_batch)\n SELECT\n $1,\n COALESCE(\n (SELECT debounce_batch FROM v2_job_debounce_batch WHERE id = dk.job_id_to_debounce LIMIT 1),\n nextval('debounce_batch_seq')\n )\n FROM dk\n )\n SELECT debounced_times, first_started_at, job_id_to_debounce FROM dk\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "debounced_times",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "first_started_at",
"type_info": "Timestamptz"
},
{
"ordinal": 2,
"name": "job_id_to_debounce",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Uuid",
"Varchar"
]
},
"nullable": [
false,
false,
true
]
},
"hash": "79b82ae996fba2e2ab53fcf84c108cb1ca21fbdba3373af54fadf1f4af324073"
}
@@ -1,46 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH RECURSIVE chain AS (\n SELECT\n j.id,\n j.parent_job,\n j.flow_step_id,\n 1 AS depth\n FROM v2_job j\n WHERE j.id = $1\n UNION ALL\n SELECT\n pj.id,\n pj.parent_job,\n pj.flow_step_id,\n c.depth + 1\n FROM chain c\n JOIN v2_job pj ON pj.id = c.parent_job\n WHERE c.parent_job IS NOT NULL\n )\n SELECT\n c.id,\n c.parent_job,\n c.flow_step_id,\n EXISTS(SELECT 1 FROM v2_job_queue q WHERE q.id = c.parent_job) AS \"parent_in_queue!\",\n EXISTS(\n SELECT 1 FROM v2_job sib\n WHERE sib.parent_job = c.parent_job\n AND sib.id != c.id\n AND sib.id IN (SELECT sq.id FROM v2_job_queue sq)\n ) AS \"has_other_active_siblings!\"\n FROM chain c\n WHERE c.depth >= 1\n ORDER BY c.depth ASC\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "parent_job",
"type_info": "Uuid"
},
{
"ordinal": 2,
"name": "flow_step_id",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "parent_in_queue!",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "has_other_active_siblings!",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
null,
null,
null,
null,
null
]
},
"hash": "950f364c9fa3c680eea895558a559f29220c08e94e1822e3bcb5c6ed6aa7d2bb"
}
@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH dk AS (\n INSERT INTO debounce_key (job_id, key)\n VALUES ($1, $2)\n ON CONFLICT (key)\n DO UPDATE SET\n previous_job_id = debounce_key.job_id,\n job_id = EXCLUDED.job_id,\n debounced_times = debounce_key.debounced_times + 1\n RETURNING\n debounced_times,\n first_started_at,\n previous_job_id AS job_id_to_debounce\n ), _batch AS (\n INSERT INTO v2_job_debounce_batch (id, debounce_batch)\n SELECT\n $1,\n COALESCE(\n (SELECT debounce_batch FROM v2_job_debounce_batch WHERE id = dk.job_id_to_debounce LIMIT 1),\n nextval('debounce_batch_seq')\n )\n FROM dk\n )\n SELECT debounced_times, first_started_at, job_id_to_debounce FROM dk\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "debounced_times",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "first_started_at",
"type_info": "Timestamptz"
},
{
"ordinal": 2,
"name": "job_id_to_debounce",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Uuid",
"Varchar"
]
},
"nullable": [
false,
false,
true
]
},
"hash": "98033aae3182bde22d5b2ff08ef6e8a4f8f3a9bf04238b33e9caf46836df73d9"
}
@@ -1,16 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE v2_job_status SET flow_status = (\n SELECT jsonb_set(\n flow_status,\n ARRAY['modules', (idx - 1)::text],\n $2::jsonb\n )\n FROM jsonb_array_elements(flow_status->'modules')\n WITH ORDINALITY arr(elem, idx)\n WHERE elem->>'id' = $3\n LIMIT 1\n ) WHERE id = $1 AND (\n SELECT COUNT(*) FROM jsonb_array_elements(flow_status->'modules')\n WITH ORDINALITY arr(elem, idx)\n WHERE elem->>'id' = $3\n ) > 0",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Jsonb",
"Text"
]
},
"nullable": []
},
"hash": "b1979a8249557d29e9055fde06191688f3ed0efd3a43e81f4ea296255248092c"
}
@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH dk AS (\n INSERT INTO debounce_key (job_id, key)\n VALUES ($1, $2)\n ON CONFLICT (key)\n DO UPDATE SET\n previous_job_id = debounce_key.job_id,\n job_id = EXCLUDED.job_id,\n debounced_times = debounce_key.debounced_times + 1\n RETURNING\n debounced_times,\n first_started_at,\n previous_job_id AS job_id_to_debounce\n ), _batch AS (\n INSERT INTO v2_job_debounce_batch (id, debounce_batch)\n SELECT\n $1,\n COALESCE(\n (SELECT debounce_batch FROM v2_job_debounce_batch WHERE id = dk.job_id_to_debounce LIMIT 1),\n nextval('debounce_batch_seq')\n )\n FROM dk\n )\n SELECT debounced_times, first_started_at, job_id_to_debounce FROM dk\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "debounced_times",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "first_started_at",
"type_info": "Timestamptz"
},
{
"ordinal": 2,
"name": "job_id_to_debounce",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Uuid",
"Varchar"
]
},
"nullable": [
false,
false,
true
]
},
"hash": "c2347460b73ae9d3167031c263032e97ebefb46be9e58bd3da9067748075311b"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(\n SELECT 1 FROM v2_job\n WHERE parent_job = $1 AND id != $2\n AND id IN (SELECT id FROM v2_job_queue)\n ) as has",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "has",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Uuid",
"Uuid"
]
},
"nullable": [
null
]
},
"hash": "ecf67b08d327c351909b7ba80218903bec93ef79a71053c00227e17c6f0415a2"
}
+1 -1
View File
@@ -1 +1 @@
ec613f2db9e72e32e9131181546dcd679405a782
414202845a45e2a7c6a2d3e154bd8dfd0273cc14
+21
View File
@@ -17429,6 +17429,27 @@ paths:
description: count of log lines that matched the query per hostname
type: object
/srch/index/storage/disk:
get:
summary: Get index disk storage sizes from the indexer.
operationId: getIndexDiskStorageSizes
tags:
- indexSearch
responses:
"200":
description: disk storage sizes for each index
content:
application/json:
schema:
type: object
properties:
job_index_disk_size_bytes:
type: integer
nullable: true
log_index_disk_size_bytes:
type: integer
nullable: true
/indexer/delete/{idx_name}:
delete:
summary: Clear an index and restart the indexer.
@@ -2,7 +2,7 @@
import { Button } from '$lib/components/common'
import ConfirmationModal from '../common/confirmationModal/ConfirmationModal.svelte'
import { IndexSearchService } from '$lib/gen'
import type { GetIndexerStatusResponse } from '$lib/gen'
import type { GetIndexerStatusResponse, GetIndexDiskStorageSizesResponse } from '$lib/gen'
import { sendUserToast } from '$lib/toast'
import { displaySize } from '$lib/utils'
import Tooltip from '../Tooltip.svelte'
@@ -24,6 +24,7 @@
let clearServiceLogsIndexModalOpen = $state(false)
let status: GetIndexerStatusResponse | undefined = $state(undefined)
let diskSizes: GetIndexDiskStorageSizesResponse | undefined = $state(undefined)
let statusLoading = $state(true)
let statusError = $state(false)
@@ -41,9 +42,15 @@
statusLoading = true
statusError = false
try {
status = await IndexSearchService.getIndexerStatus()
const [statusRes, diskRes] = await Promise.all([
IndexSearchService.getIndexerStatus(),
IndexSearchService.getIndexDiskStorageSizes().catch(() => undefined)
])
status = statusRes
diskSizes = diskRes
} catch (e) {
status = undefined
diskSizes = undefined
statusError = true
} finally {
statusLoading = false
@@ -139,7 +146,11 @@
: 'bg-red-500'}"
></span>
<span class="text-primary font-medium">{label}:</span>
<span class="font-semibold {entry?.is_alive ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}">
<span
class="font-semibold {entry?.is_alive
? 'text-green-600 dark:text-green-400'
: 'text-red-600 dark:text-red-400'}"
>
{entry?.is_alive ? 'Running' : 'Stopped'}
</span>
{#if entry?.last_locked_at}
@@ -161,21 +172,21 @@
<div class="flex flex-col gap-1 text-2xs text-tertiary">
<span>
Jobs index:
{#if status.job_indexer?.storage?.disk_size_bytes != null}
Disk: {displaySize(status.job_indexer.storage.disk_size_bytes) ?? 'N/A'}
{#if diskSizes?.job_index_disk_size_bytes != null}
Disk: {displaySize(diskSizes.job_index_disk_size_bytes) ?? 'N/A'}
{/if}
{#if status.job_indexer?.storage?.s3_size_bytes != null}
{#if status.job_indexer?.storage?.disk_size_bytes != null}&middot;{/if}
{#if diskSizes?.job_index_disk_size_bytes != null}&middot;{/if}
S3: {displaySize(status.job_indexer.storage.s3_size_bytes) ?? 'N/A'}
{/if}
</span>
<span>
Service logs index:
{#if status.log_indexer?.storage?.disk_size_bytes != null}
Disk: {displaySize(status.log_indexer.storage.disk_size_bytes) ?? 'N/A'}
{#if diskSizes?.log_index_disk_size_bytes != null}
Disk: {displaySize(diskSizes.log_index_disk_size_bytes) ?? 'N/A'}
{/if}
{#if status.log_indexer?.storage?.s3_size_bytes != null}
{#if status.log_indexer?.storage?.disk_size_bytes != null}&middot;{/if}
{#if diskSizes?.log_index_disk_size_bytes != null}&middot;{/if}
S3: {displaySize(status.log_indexer.storage.s3_size_bytes) ?? 'N/A'}
{/if}
</span>