Skip to content

Commit cc4c620

Browse files
committed
WIP: local gnomon live log handling
1 parent 21b2b35 commit cc4c620

4 files changed

Lines changed: 97 additions & 85 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ npm start
7878
- [x] Start/Stop Gnomon
7979
- [ ] Startpage refresh on Gnomon start
8080
- [ ] Display getInfo
81-
- [ ] Saved Live Logs on page change/refresh
81+
- [x] Keeping the log listener alive
8282

8383
### Readme Page
8484
- [ ] How to run you own node Guide

main.js

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
let gnomonProcess = null;
2+
let gnomonLogBuffer = [];
3+
const MAX_GNOMON_LOG_LINES = 5000;
4+
25
let telaServerProcess = null;
36

47

@@ -111,7 +114,26 @@ let gnomonNodeAddress = loadGnomonConfig().node;
111114

112115
// ---------------- Gnomon ----------------
113116

114-
/* ---- Gnomon status check ---- */
117+
/* ---------- Log buffer helper ---------- */
118+
function pushGnomonLog(str) {
119+
if (!str) return;
120+
121+
gnomonLogBuffer.push(str);
122+
123+
// Prevent memory bloat
124+
if (gnomonLogBuffer.length > MAX_GNOMON_LOG_LINES) {
125+
gnomonLogBuffer.splice(
126+
0,
127+
gnomonLogBuffer.length - MAX_GNOMON_LOG_LINES
128+
);
129+
}
130+
131+
if (mainWindow && !mainWindow.isDestroyed()) {
132+
mainWindow.webContents.send("gnomon-log", str);
133+
}
134+
}
135+
136+
/* ---------- IPC: status check ---------- */
115137
ipcMain.handle("check-gnomon", () => {
116138
return new Promise((resolve) => {
117139
const req = http.get(
@@ -131,42 +153,21 @@ ipcMain.handle("check-gnomon", () => {
131153
});
132154
});
133155

134-
135-
/* ---- Gnomon getInfo ---- */
136-
ipcMain.handle("gnomon:get-info", async () => {
137-
return new Promise((resolve) => {
138-
const req = http.get(
139-
"http://127.0.0.1:8099/api/getinfo",
140-
{ timeout: 1500 },
141-
(res) => {
142-
let data = "";
143-
144-
res.on("data", chunk => data += chunk);
145-
res.on("end", () => {
146-
try {
147-
resolve(JSON.parse(data));
148-
} catch {
149-
resolve(null);
150-
}
151-
});
152-
}
153-
);
154-
155-
req.on("error", () => resolve(null));
156-
req.on("timeout", () => {
157-
req.destroy();
158-
resolve(null);
159-
});
160-
});
156+
/* ---------- IPC: get log buffer ---------- */
157+
ipcMain.handle("gnomon:get-log-buffer", () => {
158+
// Send only last N lines
159+
const slice = gnomonLogBuffer.slice(-500);
160+
return slice.join("");
161161
});
162162

163-
// -------------------- Gnomon Start/Stop ---------------------------------
164-
163+
/* ---------- IPC: start Gnomon ---------- */
165164
ipcMain.handle("gnomon:start", async () => {
166165
if (gnomonProcess) return { running: true };
167166

168167
const gnomonPath = path.join(__dirname, "resources", "gnomonindexer");
169168

169+
gnomonLogBuffer.push("\n--- Gnomon starting ---\n");
170+
170171
gnomonProcess = spawn(gnomonPath, [
171172
`--daemon-rpc-address=${gnomonNodeAddress}`,
172173
"--fastsync",
@@ -175,55 +176,49 @@ ipcMain.handle("gnomon:start", async () => {
175176
'--search-filter="telaVersion"'
176177
]);
177178

178-
// Send live stdout logs to renderer
179-
gnomonProcess.stdout.on('data', (data) => {
179+
gnomonProcess.stdout.on("data", (data) => {
180180
const str = data.toString();
181-
mainWindow.webContents.send('gnomon-log', str);
181+
pushGnomonLog(str);
182182

183-
// 🔹 Detect new SCID indexed lines (adjust regex to your output)
183+
// Detect indexed SCIDs
184184
const match = str.match(/Indexed SCID:\s+([a-z0-9]+)/i);
185-
if (match) {
186-
const scid = match[1];
187-
mainWindow.webContents.send('gnomon-new-scid', scid);
185+
if (match && mainWindow && !mainWindow.isDestroyed()) {
186+
mainWindow.webContents.send("gnomon-new-scid", match[1]);
188187
}
189188
});
190189

191-
// Send live stderr logs to renderer
192190
gnomonProcess.stderr.on("data", (data) => {
193-
if (mainWindow && !mainWindow.isDestroyed()) {
194-
mainWindow.webContents.send("gnomon-log", data.toString());
195-
}
191+
pushGnomonLog(data.toString());
196192
});
197193

198-
// Handle process exit
199-
gnomonProcess.on("exit", (code) => {
194+
gnomonProcess.once("exit", (code) => {
195+
pushGnomonLog(`\n--- Gnomon exited (code ${code}) ---\n`);
200196
gnomonProcess = null;
197+
201198
if (mainWindow && !mainWindow.isDestroyed()) {
202199
mainWindow.webContents.send("gnomon-exit", { code });
203200
}
204201
});
205202

206-
// 🔹 Notify the renderer (start.html) that Gnomon started
207203
if (mainWindow && !mainWindow.isDestroyed()) {
208-
mainWindow.webContents.send('gnomon-started');
204+
mainWindow.webContents.send("gnomon-started");
209205
}
210206

211207
return { started: true };
212208
});
213209

210+
/* ---------- IPC: stop Gnomon ---------- */
214211
ipcMain.handle("gnomon:stop", async () => {
215212
if (!gnomonProcess) return { running: false };
216213

217-
gnomonProcess.kill("SIGINT");
218-
gnomonProcess = null;
214+
pushGnomonLog("\n--- Stopping Gnomon ---\n");
219215

220-
if (mainWindow && !mainWindow.isDestroyed()) {
221-
mainWindow.webContents.send("gnomon-exit", { code: null });
222-
}
216+
gnomonProcess.kill("SIGINT");
223217

224-
return { stopped: true };
218+
return { stopping: true };
225219
});
226220

221+
227222
// ---------- IPC to apply the node address to Gnomon -------------------
228223
ipcMain.handle("gnomon:apply-node", async (event, nodeAddress) => {
229224
if (!nodeAddress || typeof nodeAddress !== "string") {

managers/gnomon.js

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ export function createGnomonManager() {
1515
<button id="gnomon-stop">Stop</button>
1616
</div>
1717
18-
<pre id="gnomon-log" style="margin-top:15px; height:300px; overflow:auto; background:#111; color:#0f0; padding:10px; border-radius:5px;"></pre>
18+
<pre id="gnomon-log"
19+
style="margin-top:15px;height:300px;overflow:auto;
20+
background:#111;color:#0f0;padding:10px;border-radius:5px;">
21+
</pre>
1922
`;
2023

2124
const led = el.querySelector("#gnomon-status");
@@ -25,14 +28,21 @@ export function createGnomonManager() {
2528
const logEl = el.querySelector("#gnomon-log");
2629

2730
const api = window.electronAPI;
28-
2931
if (!api) {
30-
console.error("electronAPI not found!");
3132
text.textContent = "electronAPI not available";
3233
return el;
3334
}
3435

35-
// Function to update status LED
36+
// ---------- Restore buffered log ----------
37+
(async () => {
38+
const history = await api.getGnomonLogBuffer();
39+
if (history) {
40+
logEl.textContent = history;
41+
logEl.scrollTop = logEl.scrollHeight;
42+
}
43+
})();
44+
45+
// ---------- Status ----------
3646
async function updateStatus() {
3747
led.className = "led yellow";
3848
text.textContent = "Checking Gnomon...";
@@ -46,46 +56,43 @@ export function createGnomonManager() {
4656
}
4757
}
4858

49-
// Start button
50-
startBtn.addEventListener("click", async () => {
59+
// ---------- Buttons ----------
60+
startBtn.onclick = async () => {
5161
text.textContent = "Starting Gnomon...";
52-
try {
53-
await api.gnomonStart();
54-
await updateStatus();
55-
} catch (err) {
56-
console.error(err);
57-
text.textContent = "Failed to start Gnomon";
58-
}
59-
});
62+
await api.gnomonStart();
63+
updateStatus();
64+
};
6065

61-
// Stop button
62-
stopBtn.addEventListener("click", async () => {
66+
stopBtn.onclick = async () => {
6367
text.textContent = "Stopping Gnomon...";
64-
try {
65-
await api.gnomonStop();
66-
await updateStatus();
67-
} catch (err) {
68-
console.error(err);
69-
text.textContent = "Failed to stop Gnomon";
70-
}
71-
});
68+
await api.gnomonStop();
69+
updateStatus();
70+
};
7271

73-
// Live log listener
74-
api.onGnomonLog((log) => {
72+
// ---------- Named listeners (CRITICAL) ----------
73+
const logHandler = (log) => {
7574
logEl.textContent += log;
76-
logEl.scrollTop = logEl.scrollHeight; // auto-scroll
77-
});
75+
logEl.scrollTop = logEl.scrollHeight;
76+
};
7877

79-
// Exit listener
80-
api.onGnomonExit(() => {
78+
const exitHandler = () => {
8179
logEl.textContent += "\n--- Gnomon stopped ---\n";
8280
updateStatus();
83-
});
81+
};
8482

85-
// Check initial status every 2s
83+
api.onGnomonLog(logHandler);
84+
api.onGnomonExit(exitHandler);
85+
86+
// ---------- Poll status ----------
8687
updateStatus();
8788
const interval = setInterval(updateStatus, 2000);
88-
el.cleanup = () => clearInterval(interval);
89+
90+
// ---------- Cleanup ----------
91+
el.cleanup = () => {
92+
clearInterval(interval);
93+
api.removeGnomonLogListener(logHandler);
94+
api.removeGnomonExitListener(exitHandler);
95+
};
8996

9097
return el;
9198
}

preload.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ contextBridge.exposeInMainWorld("electronAPI", {
3636
gnomonStart: () => ipcRenderer.invoke("gnomon:start"),
3737
gnomonStop: () => ipcRenderer.invoke("gnomon:stop"),
3838

39+
getGnomonLogBuffer: () => ipcRenderer.invoke("gnomon:get-log-buffer"),
40+
41+
removeGnomonLogListener: (cb) =>
42+
ipcRenderer.removeListener("gnomon-log", cb),
43+
44+
removeGnomonExitListener: (cb) =>
45+
ipcRenderer.removeListener("gnomon-exit", cb),
46+
47+
48+
3949
onGnomonLog: (callback) => ipcRenderer.on("gnomon-log", (_, log) => callback(log)),
4050
onGnomonExit: (callback) => ipcRenderer.on("gnomon-exit", (_, data) => callback(data)),
4151

0 commit comments

Comments
 (0)