PHP Classes

File: templates/admin/buffer_test.twig

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   templates/admin/buffer_test.twig   Download  
File: templates/admin/buffer_test.twig
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 7,605 bytes
 

Contents

Class file image Download
{% extends "base.twig" %} {% block title %}Buffer Test ? {{ app_name }}{% endblock %} {% block content %} <div class="container-fluid py-3"> <div class="d-flex align-items-center mb-3 gap-2 flex-wrap"> <h4 class="mb-0"><i class="fas fa-filter me-2"></i>Proxy Buffer Test</h4> <span id="connBadge" class="badge bg-secondary ms-2">Idle</span> </div> <div class="alert alert-info py-2 mb-3"> <strong>What this tests:</strong> Opens a raw <code>EventSource</code> directly to this server (no SharedWorker, no database) and streams one event per second. If events appear one-by-one the proxy chain is <strong>not buffering</strong>. If they all appear at once at the end, something upstream (Apache, Caddy, or PHP-FPM) is holding the response body. </div> <div class="row g-2 align-items-end mb-3"> <div class="col-sm-auto"> <label class="form-label mb-1">Events</label> <select class="form-select form-select-sm" id="ctrlCount"> <option value="5">5</option> <option value="8" selected>8</option> <option value="10">10</option> <option value="15">15</option> </select> </div> <div class="col-sm-auto"> <button class="btn btn-primary btn-sm" id="btnStart"><i class="fas fa-play me-1"></i>Start</button> <button class="btn btn-danger btn-sm d-none ms-1" id="btnStop"><i class="fas fa-stop me-1"></i>Stop</button> </div> </div> <div class="row g-2 mb-3"> <div class="col-6 col-md-3"> <div class="card text-center"> <div class="card-body py-2"> <div class="h4 mb-0" id="statReceived">?</div> <div class="small text-muted">Received</div> </div> </div> </div> <div class="col-6 col-md-3"> <div class="card text-center"> <div class="card-body py-2"> <div class="h4 mb-0" id="statExpected">?</div> <div class="small text-muted">Expected</div> </div> </div> </div> <div class="col-12 col-md-6"> <div class="card text-center"> <div class="card-body py-2"> <div class="h5 mb-0" id="statVerdict">?</div> <div class="small text-muted">Verdict</div> </div> </div> </div> </div> <div class="card"> <div class="card-header py-1"> <span class="small fw-semibold">Event log</span> <span class="small text-muted ms-2">Each row should appear ~1 second apart if the chain is not buffering</span> </div> <div class="card-body p-0"> <table class="table table-sm table-striped mb-0 font-monospace" id="eventTable"> <thead class="table-light sticky-top"> <tr> <th>#</th> <th>Client received (ms since start)</th> <th>Server timestamp</th> <th>Gap from previous (ms)</th> <th>Note</th> </tr> </thead> <tbody id="eventLog"></tbody> </table> </div> </div> </div> <script> (function () { let es = null; let startTs = null; let prevTs = null; let received = 0; const badge = document.getElementById('connBadge'); const btnStart = document.getElementById('btnStart'); const btnStop = document.getElementById('btnStop'); const logBody = document.getElementById('eventLog'); function setStatus(text, cls) { badge.textContent = text; badge.className = 'badge ms-2 ' + cls; } function addRow(seq, clientOffset, serverTs, gap, note) { const tr = document.createElement('tr'); tr.innerHTML = `<td>${seq}</td>` + `<td>${clientOffset.toFixed(0)} ms</td>` + `<td>${serverTs}</td>` + `<td>${gap === null ? '?' : gap.toFixed(0) + ' ms'}</td>` + `<td>${note}</td>`; logBody.appendChild(tr); tr.scrollIntoView({ block: 'nearest' }); } function setVerdict(total) { const el = document.getElementById('statVerdict'); if (received === 0) { el.textContent = 'No events received'; el.className = 'h5 mb-0 text-danger'; return; } // If all events arrived within 500 ms of each other it smells like buffering const rows = logBody.querySelectorAll('tr'); const first = rows[0] ? parseFloat(rows[0].cells[1].textContent) : 0; const last = rows[rows.length - 1] ? parseFloat(rows[rows.length - 1].cells[1].textContent) : 0; const span = last - first; if (received < total) { el.textContent = `Incomplete (${received}/${total})`; el.className = 'h5 mb-0 text-warning'; } else if (span < 500) { el.textContent = '? Likely buffered ? all events arrived within ' + span.toFixed(0) + ' ms'; el.className = 'h5 mb-0 text-danger'; } else { el.textContent = '? Not buffered ? events streamed in real time'; el.className = 'h5 mb-0 text-success'; } } function start() { const count = parseInt(document.getElementById('ctrlCount').value, 10); logBody.innerHTML = ''; received = 0; startTs = null; prevTs = null; document.getElementById('statReceived').textContent = '0'; document.getElementById('statExpected').textContent = count; document.getElementById('statVerdict').textContent = '?'; document.getElementById('statVerdict').className = 'h5 mb-0'; btnStart.classList.add('d-none'); btnStop.classList.remove('d-none'); setStatus('Connecting?', 'bg-warning text-dark'); es = new EventSource(`/admin/buffer-test/stream?count=${count}`); es.addEventListener('tick', function (e) { const now = Date.now(); if (!startTs) startTs = now; const data = JSON.parse(e.data); const offset = now - startTs; const gap = prevTs !== null ? now - prevTs : null; prevTs = now; received++; document.getElementById('statReceived').textContent = received; setStatus('Connected', 'bg-success'); addRow(data.seq, offset, data.server_ts, gap, ''); }); es.addEventListener('done', function () { setVerdict(count); stop(false); }); es.onerror = function () { if (es && es.readyState === EventSource.CLOSED) { setStatus('Error / closed', 'bg-danger'); setVerdict(count); stop(false); } }; } function stop(closeEs) { if (closeEs !== false && es) { es.close(); } es = null; btnStart.classList.remove('d-none'); btnStop.classList.add('d-none'); if (badge.textContent === 'Connecting?') { setStatus('Idle', 'bg-secondary'); } } btnStart.addEventListener('click', start); btnStop.addEventListener('click', function () { setStatus('Stopped', 'bg-secondary'); stop(true); }); })(); </script> {% endblock %}