diff --git a/frontend/src/stores/systemActivity.js b/frontend/src/stores/systemActivity.js new file mode 100644 index 0000000..e152ade --- /dev/null +++ b/frontend/src/stores/systemActivity.js @@ -0,0 +1,103 @@ +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 recentMinute = 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, 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 loadRecentMinute() { + // 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 }, + }) + recentMinute.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 (!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 } + } + + return { + queues, workers, recentMinute, failures, + runs, runsCursor, runsHasMore, runsFilter, + loading, lastError, + loadQueues, loadWorkers, loadRecentMinute, + loadRuns, loadFailures, setFilter, + } +})