Files
wekan/server/methods/systemStatus.js
T
Lauri Ojansivu 5a1c9a61e9 Admin Panel / Problems "Status" overview + snap run wekan.problems: show migrations/repairs in progress and login-page "Must be logged in" causes; run repairs server-side.
Motivated by the 10.16-10.21 reports where, after an upgrade, the login page
showed "Must be logged in" or sat on the logo + "Loading, please wait." spinner,
pages took 5+ minutes, All Boards counts stayed 0 and i18n showed raw keys — the
FerretDB v1 (SQLite) process pegged ~2 cores for a long time under WeKan's poll
load, i.e. a migration/repair or a saturated backend, with no way to see it
without the Admin Panel.

Server-side, independent of any client / progress page:
 - server/startup/repairBoardsOnStartup.js runs the shared board data-repairs once
   (version-gated, background, 30s after boot) so corrupted data is fixed even if
   no user opens a board and nobody watches a progress page.
 - The MongoDB <-> SQLite text migration and the startup repair now PERSIST their
   progress to the text_migration_status collection (models/textMigrationStatus.js),
   so a separate process can see "a migration/repair is in progress" (an in-memory
   object could not).

Status overview (server/lib/systemStatus.js), shown in Admin Panel / Problems ->
Summary and via the method systemStatusReport (admin-gated, server/methods/
systemStatus.js):
 - everything in progress (text migration, board repair, recovery, cron migration,
   attachment migration) aggregated from the persisted status collections;
 - detected problems (broken cards; failing login-page checks);
 - login-page "Must be logged in" / "Loading, please wait" cause checklist
   (migration in progress, ROOT_URL, LDAP, Sandstorm) — models/lib/loginProblems.js;
 - a CPU detail area that calls out a pegged ferretdb process and the mitigation.

Snap: `snap run wekan.problems` (snap-src/bin/wekan-problems[.mjs], snapcraft app
`problems`) prints the same overview as text — problems, migrations/repairs in
progress, login checks — so an admin with only server access can see it WITHOUT
Admin Panel access. Sub-commands: migrations | login | broken-cards | cpu | help.

Pure helpers models/lib/loginProblems.js and models/lib/problemsOverview.js are
unit-tested; tests/problemsStatus.test.cjs (14 checks) also source-guards the
server hub, method, startup pass, migration persistence and snap command.

Thanks to xet7 !
2026-07-22 16:22:39 +03:00

65 lines
2.5 KiB
JavaScript

import { Meteor } from 'meteor/meteor';
import os from 'os';
import { ReactiveCache } from '/imports/reactiveCache';
import {
getProblemsOverview,
getInProgress,
getLoginProblems,
} from '/server/lib/systemStatus';
// Admin-gated methods behind the Admin Panel / Problems "Status" overview. The
// same data is available without the Admin Panel via `snap run wekan.problems`.
async function requireAdmin() {
const user = await ReactiveCache.getCurrentUser();
if (!user || !user.isAdmin) {
throw new Meteor.Error('not-authorized', 'Admin only');
}
return user;
}
// Problem-specific detail, mirroring the `snap run wekan.problems <area>`
// sub-commands. Kept in one place so the Admin Panel and the snap command agree.
function cpuDetail() {
const cpus = os.cpus() || [];
const mem = process.memoryUsage();
return {
area: 'cpu',
title: 'CPU usage',
loadAverage: os.loadavg(), // 1 / 5 / 15 min
cpuCount: cpus.length,
cpuModel: cpus.length ? cpus[0].model : '',
uptimeSeconds: Math.round(process.uptime()),
rssBytes: mem.rss,
heapUsedBytes: mem.heapUsed,
note: 'Load average is machine-wide (1/5/15 min). rss/heap are the WeKan server process. Sustained load near or above the CPU count means the machine is saturated. If `top` shows the ferretdb process pegged near 100%/200% for a long time, the FerretDB v1 (SQLite) backend is saturated under WeKan\'s poll load (symptoms: pages take minutes, counts stuck at 0, raw i18n keys). Mitigation: run on MongoDB (snap: `snap set wekan database=mongodb`) or migrate text data across, and check for a migration/repair still running.',
};
}
Meteor.methods({
// The full Problems "Status" overview: everything in progress + problems found.
async systemStatusReport() {
await requireAdmin();
const [overview, loginProblems] = await Promise.all([
getProblemsOverview(),
getLoginProblems(),
]);
return { overview, loginProblems };
},
// Just the in-progress migrations/repairs (cheap; polled by the Status page).
async migrationsInProgress() {
await requireAdmin();
return getInProgress();
},
// Detail for one problem area (currently 'cpu'); mirrors the snap sub-command.
async problemDetailReport(area) {
await requireAdmin();
if (area === 'cpu') return cpuDetail();
if (area === 'login') return { area: 'login', checks: await getLoginProblems() };
if (area === 'status' || !area) return getProblemsOverview();
throw new Meteor.Error('unknown-area', `Unknown problem area: ${area}`);
},
});