owlservable 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dashboard.html CHANGED
@@ -257,9 +257,10 @@ function addRow(r,prepend){
257
257
 
258
258
  function applyUpdate(id,patch){
259
259
  var e=byId[id];if(!e)return;
260
+ var prevTok=(e.data.tokens&&e.data.tokens.total)||0;
260
261
  Object.assign(e.data,patch);
261
262
  if(patch.tokens){
262
- totalTok+=patch.tokens.total||0;
263
+ totalTok+=(patch.tokens.total||0)-prevTok;
263
264
  nTok.textContent=fn(totalTok);
264
265
  e.tr.querySelector('.c-tok').innerHTML=tokHtml(e.data);
265
266
  }else if('metaPending' in patch&&!patch.metaPending){
@@ -307,7 +308,7 @@ function handleMsg(msg){
307
308
  msg.requests.slice().reverse().forEach(function(r){addRow(r,false);});
308
309
  renderSave(msg.save);
309
310
  }else if(msg.type==='request'){
310
- addRow(msg.record,true);
311
+ if(!byId[msg.record.id])addRow(msg.record,true);
311
312
  }else if(msg.type==='update'){
312
313
  applyUpdate(msg.id,msg.patch);
313
314
  }else if(msg.type==='saveConfig'){
@@ -336,10 +337,14 @@ document.getElementById('btn-theme').addEventListener('click',function(){
336
337
 
337
338
  function connect(){
338
339
  var es=new EventSource('/events');
339
- es.addEventListener('open',function(){dot.classList.remove('off');});
340
- es.addEventListener('error',function(){dot.classList.add('off');es.close();setTimeout(connect,2000);});
340
+ var lastMsg=Date.now(),staleTimer=null;
341
+ staleTimer=setInterval(function(){if(Date.now()-lastMsg>35000){dot.classList.add('off');clearInterval(staleTimer);es.close();setTimeout(connect,1000);}},5000);
342
+ es.addEventListener('open',function(){dot.classList.remove('off');lastMsg=Date.now();});
343
+ es.addEventListener('error',function(){dot.classList.add('off');clearInterval(staleTimer);es.close();setTimeout(connect,2000);});
341
344
  es.addEventListener('message',function(e){
345
+ lastMsg=Date.now();
342
346
  var msg;try{msg=JSON.parse(e.data);}catch(_){return;}
347
+ if(msg.type==='ping')return;
343
348
  if(paused&&(msg.type==='request'||msg.type==='update')){
344
349
  pauseBuffer.push(msg);
345
350
  btnPause.title='Resume ('+pauseBuffer.length+' buffered)';
@@ -348,6 +353,23 @@ function connect(){
348
353
  try{handleMsg(msg);}catch(_){}
349
354
  });
350
355
  }
356
+ var pollGen=1;
357
+ function poll(){
358
+ fetch('/api/requests').then(function(r){return r.json();}).then(function(d){
359
+ var reqs=d.requests||[],gen=d.generation||1;
360
+ if(gen!==pollGen){
361
+ pollGen=gen;reset();
362
+ reqs.slice().reverse().forEach(function(r){addRow(r,false);});
363
+ renderSave(d.save);return;
364
+ }
365
+ reqs.forEach(function(r){
366
+ if(!byId[r.id]){addRow(r,true);}
367
+ else if(byId[r.id].data.metaPending&&!r.metaPending){applyUpdate(r.id,r);}
368
+ });
369
+ }).catch(function(){});
370
+ }
371
+ setInterval(poll,2000);
372
+ setTimeout(poll,500);
351
373
  connect();
352
374
  })();
353
375
  </script>
package/index.cjs CHANGED
@@ -17,6 +17,7 @@ emitter.setMaxListeners(100)
17
17
 
18
18
  const requests = []
19
19
  let nextId = 1
20
+ let generation = 1
20
21
 
21
22
  function addRequest(entry) {
22
23
  try {
@@ -43,6 +44,7 @@ function updateRequest(id, patch) {
43
44
  function getRequests() { try { return requests.slice() } catch (_) { return [] } }
44
45
 
45
46
  function clearRequests() {
47
+ generation++
46
48
  requests.splice(0)
47
49
  if (saveState.enabled) try { fs.writeFileSync(saveState.filePath, '') } catch (_) {}
48
50
  emitter.emit('reload', { requests: [], save: getSaveInfo() })
@@ -352,12 +354,16 @@ function startDashboard(port) {
352
354
  emitter.on('update', onUpdate)
353
355
  emitter.on('saveConfig', onSave)
354
356
  emitter.on('reload', onReload)
355
- req.on('close', () => {
357
+ let hb = null
358
+ const cleanup = () => {
359
+ if (hb) { clearInterval(hb); hb = null }
356
360
  emitter.off('request', onReq)
357
361
  emitter.off('update', onUpdate)
358
362
  emitter.off('saveConfig', onSave)
359
363
  emitter.off('reload', onReload)
360
- })
364
+ }
365
+ hb = setInterval(() => { try { res.write('data: {"type":"ping"}\n\n') } catch (_) { cleanup() } }, 15000)
366
+ req.on('close', cleanup)
361
367
  return
362
368
  }
363
369
 
@@ -379,6 +385,12 @@ function startDashboard(port) {
379
385
  return
380
386
  }
381
387
 
388
+ if (urlPath === '/api/requests' && req.method === 'GET') {
389
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' })
390
+ res.end(JSON.stringify({ requests: getRequests(), save: getSaveInfo(), generation }))
391
+ return
392
+ }
393
+
382
394
  if (urlPath === '/owl.png') {
383
395
  try {
384
396
  const data = fs.readFileSync(path.join(__dir, 'owl.png'))
package/index.js CHANGED
@@ -17,6 +17,7 @@ emitter.setMaxListeners(100)
17
17
 
18
18
  const requests = []
19
19
  let nextId = 1
20
+ let generation = 1
20
21
 
21
22
  function addRequest(entry) {
22
23
  try {
@@ -43,6 +44,7 @@ function updateRequest(id, patch) {
43
44
  function getRequests() { try { return requests.slice() } catch (_) { return [] } }
44
45
 
45
46
  function clearRequests() {
47
+ generation++
46
48
  requests.splice(0)
47
49
  if (saveState.enabled) try { fs.writeFileSync(saveState.filePath, '') } catch (_) {}
48
50
  emitter.emit('reload', { requests: [], save: getSaveInfo() })
@@ -352,12 +354,16 @@ function startDashboard(port) {
352
354
  emitter.on('update', onUpdate)
353
355
  emitter.on('saveConfig', onSave)
354
356
  emitter.on('reload', onReload)
355
- req.on('close', () => {
357
+ let hb = null
358
+ const cleanup = () => {
359
+ if (hb) { clearInterval(hb); hb = null }
356
360
  emitter.off('request', onReq)
357
361
  emitter.off('update', onUpdate)
358
362
  emitter.off('saveConfig', onSave)
359
363
  emitter.off('reload', onReload)
360
- })
364
+ }
365
+ hb = setInterval(() => { try { res.write('data: {"type":"ping"}\n\n') } catch (_) { cleanup() } }, 15000)
366
+ req.on('close', cleanup)
361
367
  return
362
368
  }
363
369
 
@@ -379,6 +385,12 @@ function startDashboard(port) {
379
385
  return
380
386
  }
381
387
 
388
+ if (urlPath === '/api/requests' && req.method === 'GET') {
389
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' })
390
+ res.end(JSON.stringify({ requests: getRequests(), save: getSaveInfo(), generation }))
391
+ return
392
+ }
393
+
382
394
  if (urlPath === '/owl.png') {
383
395
  try {
384
396
  const data = fs.readFileSync(path.join(__dir, 'owl.png'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "owlservable",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Minimalist Observability Platform. Zero config, zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "index.js",