/// // Live progress for a run in flight. // // The record used to arrive only when a run finished, so the answer to "how far // is it" was to poll files on the machine doing the work -- which the owner // could not see at all. The runner now creates the record before the first case // and updates it after each one, so the dashboard can draw a bar. // // `status` is the only field that needs explaining: a run that dies leaves its // record saying `running` forever, so the dashboard reads `updated` as well and // calls a run stalled when nothing has moved for a few minutes. Better than a // heartbeat nobody sends when the process is killed. migrate( (app) => { const runs = app.findCollectionByNameOrId("e2e_runs"); runs.fields.add( new TextField({ name: "status", max: 12 }), // running | done new TextField({ name: "current", max: 120 }), // the case in flight new NumberField({ name: "total", onlyInt: true }), // cases planned new NumberField({ name: "done", onlyInt: true }), // cases finished ); app.save(runs); }, (app) => { const runs = app.findCollectionByNameOrId("e2e_runs"); for (const name of ["status", "current", "total", "done"]) { const f = runs.fields.getByName(name); if (f) runs.fields.removeById(f.id); } app.save(runs); }, );