| … | … | @@ -116,12 +116,19 @@ async function boot () { |
| 116 | 116 | // populated comma-string roster as empty is how you overwrite a real one. And back the file up |
| 117 | 117 | // first: this rewrites the file that names the identity. |
| 118 | 118 | try { |
| 119 | | const { rosterIsEmpty } = await import('./roster.js') |
| 119 | const { rosterIsEmpty, rosterKeys } = await import('./roster.js') |
| 120 | 120 | const entry0 = (cfg.dids || [])[0] |
| 121 | 121 | const node0 = state.hpp && state.hpp.nodes && state.hpp.nodes[0] |
| 122 | | if (entry0 && rosterIsEmpty(entry0) && node0 && node0.device && typeof node0.device.membersDiag === 'function') { |
| 122 | // SAY WHY IT DECLINED. The first cut logged only on success and only on throw, so when it did |
| 123 | // neither it was indistinguishable from not having run — the exact failure mode (a branch that |
| 124 | // refuses silently) that made the write-path 500 take an evening to localise. A repair that |
| 125 | // skips must report which condition stopped it. |
| 126 | const can = !!(node0 && node0.device && typeof node0.device.membersDiag === 'function') |
| 127 | log('local roster check', { entryPresent: !!entry0, localMembers: rosterKeys(entry0).length, canReadRoom: can }) |
| 128 | if (entry0 && rosterIsEmpty(entry0) && can) { |
| 123 | 129 | const md = await node0.device.membersDiag() |
| 124 | 130 | const inView = Object.keys((md && md.membersInView) || {}) |
| 131 | log('room reports members', { inView: inView.length }) |
| 125 | 132 | if (inView.length) { |
| 126 | 133 | fs.copyFileSync(cfgPath, cfgPath + '.bak.' + Date.now()) |
| 127 | 134 | entry0.members = inView |