Files
FabledCurator/frontend/src/stores/systemActivity.js
T
bvandeusen 70d4017cf6
CI / lint (push) Successful in 4s
CI / frontend-build (push) Successful in 21s
CI / backend-lint-and-test (push) Successful in 39s
CI / integration (push) Successful in 3m17s
feat(activity): search/filter on both Activity-tab panes
Recent failures gains a client-side search over the already-loaded 24h
rows (task/queue/target/error), shown as a filtered/total count alongside
the existing error-type chips. All recent activity gains a debounced
server-side task-name search (new `task` ILIKE param on /runs) so it
spans the full history, not just the loaded page. LIKE wildcards are
escaped so task names' literal underscores match literally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 11:34:42 -04:00

117 lines
3.6 KiB
JavaScript

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useApi } from '../composables/useApi.js'
export const useSystemActivityStore = defineStore('systemActivity', () => {
const api = useApi()
// Live polled state.
const queues = ref(null) // { queues: {name: depth|null}, fetched_at }
const workers = ref(null) // { workers: {hostname: {...}}, fetched_at }
const recentRuns = ref([]) // last-60s rows (for Overview summary)
const failures = ref(null) // { recent, count_by_type, since }
// Paginated runs (Activity tab "All recent activity" pane).
const runs = ref([])
const runsCursor = ref(null)
const runsHasMore = ref(false)
const runsFilter = ref({ queue: null, status: null, task: null, limit: 50 })
const loading = ref({ queues: false, workers: false, runs: false, failures: false })
const lastError = ref(null)
async function loadQueues() {
loading.value.queues = true
lastError.value = null
try {
queues.value = await api.get('/api/system/activity/queues')
} catch (e) {
lastError.value = e.message
} finally {
loading.value.queues = false
}
}
async function loadWorkers() {
loading.value.workers = true
lastError.value = null
try {
workers.value = await api.get('/api/system/activity/workers')
} catch (e) {
lastError.value = e.message
} finally {
loading.value.workers = false
}
}
async function loadRecentRuns() {
// Used by the Overview summary card: pull last 60s of runs to compute
// per-queue ok/err counts. One call covers all queues; UI groups.
try {
const body = await api.get('/api/system/activity/runs', {
params: { limit: 200 },
})
recentRuns.value = body.runs || []
} catch (e) {
lastError.value = e.message
}
}
async function loadRuns({ reset = false } = {}) {
loading.value.runs = true
lastError.value = null
try {
const params = { limit: runsFilter.value.limit }
if (runsFilter.value.queue) params.queue = runsFilter.value.queue
if (runsFilter.value.status) params.status = runsFilter.value.status
if (runsFilter.value.task) params.task = runsFilter.value.task
if (!reset && runsCursor.value) params.before_id = runsCursor.value
const body = await api.get('/api/system/activity/runs', { params })
runs.value = reset ? body.runs : [...runs.value, ...body.runs]
runsCursor.value = body.next_cursor
runsHasMore.value = body.next_cursor !== null
} catch (e) {
lastError.value = e.message
} finally {
loading.value.runs = false
}
}
async function loadFailures() {
loading.value.failures = true
lastError.value = null
try {
failures.value = await api.get('/api/system/activity/failures')
} catch (e) {
lastError.value = e.message
} finally {
loading.value.failures = false
}
}
function setFilter(filter) {
runsFilter.value = { ...runsFilter.value, ...filter }
}
// One-call rollup for the always-on TopNav pipeline indicator:
// { scheduler, queues, queued_total, running, failing }.
const summary = ref(null)
async function loadSummary() {
try {
summary.value = await api.get('/api/system/activity/summary')
} catch (e) {
lastError.value = e.message
}
return summary.value
}
return {
queues, workers, recentRuns, failures, summary,
runs, runsCursor, runsHasMore, runsFilter,
loading, lastError,
loadQueues, loadWorkers, loadRecentRuns,
loadRuns, loadFailures, loadSummary, setFilter,
}
})