mirror of
https://github.com/logos-messaging/lab.waku.org.git
synced 2026-01-02 05:43:13 +00:00
feat: add a control for querying store in dogfooding app (#142)
This commit is contained in:
parent
07c9a6a1eb
commit
90c7927283
@ -51,6 +51,17 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="store-query">
|
||||
<h2>Store Protocol Query</h2>
|
||||
<div class="store-controls">
|
||||
<label for="storeMessageCount">Number of messages to fetch:</label>
|
||||
<input type="number" id="storeMessageCount" value="5" min="1" max="100" />
|
||||
<button id="queryStoreButton" class="btn btn-primary">Query Store</button>
|
||||
</div>
|
||||
<div id="storeQueryStatus" class="store-status"></div>
|
||||
<div id="storeQueryResults" class="store-results"></div>
|
||||
</section>
|
||||
|
||||
<section class="charts">
|
||||
<h2>Discovery Peers Over Time</h2>
|
||||
<canvas id="discoveryChart"></canvas>
|
||||
|
||||
@ -92,6 +92,24 @@ h2 {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #27ae60;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
background-color: #229954;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background-color: #c0392b;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
@ -106,6 +124,40 @@ h2 {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* Store Query Section */
|
||||
.store-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.store-controls label {
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.store-controls input[type="number"] {
|
||||
width: 80px;
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.store-status {
|
||||
margin-top: 15px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.store-results {
|
||||
margin-top: 15px;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Message Display */
|
||||
.message-list {
|
||||
max-height: 400px;
|
||||
@ -214,7 +266,7 @@ footer {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.message-stats, .message-controls {
|
||||
.message-stats, .message-controls, .store-query, .charts {
|
||||
grid-column: span 1;
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,9 @@ import {
|
||||
trackMessageSent,
|
||||
trackMessageReceived,
|
||||
recordLatency,
|
||||
updateStoreQueryStatus,
|
||||
displayStoreQueryResults,
|
||||
clearStoreQueryResults,
|
||||
} from "./ui-manager";
|
||||
|
||||
const NUM_MESSAGES_PER_BATCH = 5;
|
||||
@ -206,6 +209,100 @@ async function initializeApp() {
|
||||
console.log("Subscription active.");
|
||||
};
|
||||
|
||||
const queryStoreMessages = async () => {
|
||||
const storeMessageCountInput = document.getElementById("storeMessageCount") as HTMLInputElement;
|
||||
const messageLimit = storeMessageCountInput ? parseInt(storeMessageCountInput.value, 10) : 5;
|
||||
|
||||
if (isNaN(messageLimit) || messageLimit < 1) {
|
||||
updateStoreQueryStatus("Please enter a valid number of messages (minimum 1)", true);
|
||||
return;
|
||||
}
|
||||
|
||||
clearStoreQueryResults();
|
||||
updateStoreQueryStatus("Querying store...", false);
|
||||
console.log(`Querying store for up to ${messageLimit} messages...`);
|
||||
|
||||
try {
|
||||
const decoder = createWakuDecoder();
|
||||
const allMessages: ChatMessage[] = [];
|
||||
|
||||
console.log("Decoder content topic:", decoder.contentTopic);
|
||||
console.log("Decoder pubsub topic:", decoder.pubsubTopic);
|
||||
|
||||
// Query for messages from the last hour, using paginationLimit to control result size
|
||||
const timeEnd = new Date();
|
||||
const timeStart = new Date(Date.now() - 1000 * 60 * 60);
|
||||
|
||||
const queryOptions = {
|
||||
timeStart,
|
||||
timeEnd,
|
||||
paginationForward: false, // Start from newest
|
||||
paginationLimit: messageLimit, // Limit the number of messages returned
|
||||
};
|
||||
|
||||
console.log("Store query options:", queryOptions);
|
||||
console.log("Time range:", timeStart.toISOString(), "to", timeEnd.toISOString());
|
||||
|
||||
// Collect messages - stop once we have enough
|
||||
await node.store.queryWithOrderedCallback(
|
||||
[decoder],
|
||||
async (wakuMessage) => {
|
||||
// Check if we already have enough messages before processing more
|
||||
if (allMessages.length >= messageLimit) {
|
||||
console.log(`Already collected ${messageLimit} messages, stopping`);
|
||||
return true; // Stop processing
|
||||
}
|
||||
|
||||
const chatMessage = decodeMessage(wakuMessage.payload);
|
||||
if (chatMessage) {
|
||||
allMessages.push(chatMessage);
|
||||
console.log(`Store found message ${allMessages.length}/${messageLimit}:`, {
|
||||
id: chatMessage.id,
|
||||
content: chatMessage.content.substring(0, 50),
|
||||
timestamp: new Date(chatMessage.timestamp).toISOString(),
|
||||
sender: chatMessage.senderPeerId.substring(0, 12)
|
||||
});
|
||||
|
||||
// Stop if we've reached the limit
|
||||
if (allMessages.length >= messageLimit) {
|
||||
console.log(`Reached limit of ${messageLimit} messages, stopping`);
|
||||
return true; // Stop processing
|
||||
}
|
||||
} else {
|
||||
console.warn("Failed to decode message from store");
|
||||
}
|
||||
|
||||
return false; // Continue to next message
|
||||
},
|
||||
queryOptions
|
||||
);
|
||||
|
||||
console.log(`Store query completed. Collected ${allMessages.length} messages.`);
|
||||
|
||||
if (allMessages.length > 0) {
|
||||
// Sort by timestamp descending (newest first)
|
||||
// Since we're querying with paginationForward: false, we're getting recent messages,
|
||||
// but they may not be in perfect order, so we sort them
|
||||
allMessages.sort((a, b) => b.timestamp - a.timestamp);
|
||||
|
||||
console.log(`Returning ${allMessages.length} message(s)`);
|
||||
console.log("Newest message timestamp:", new Date(allMessages[0].timestamp).toISOString());
|
||||
if (allMessages.length > 1) {
|
||||
console.log("Oldest returned message timestamp:", new Date(allMessages[allMessages.length - 1].timestamp).toISOString());
|
||||
}
|
||||
|
||||
updateStoreQueryStatus(`✓ Successfully retrieved ${allMessages.length} message${allMessages.length !== 1 ? 's' : ''} from store`, false);
|
||||
displayStoreQueryResults(allMessages);
|
||||
} else {
|
||||
updateStoreQueryStatus("✓ Query completed successfully, but no messages found in store", false);
|
||||
displayStoreQueryResults([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error querying store:", error);
|
||||
updateStoreQueryStatus(`✗ Error querying store: ${error instanceof Error ? error.message : String(error)}`, true);
|
||||
}
|
||||
};
|
||||
|
||||
const sendMessageButton = document.getElementById("sendMessageButton");
|
||||
if (sendMessageButton) {
|
||||
sendMessageButton.addEventListener("click", () => {
|
||||
@ -241,6 +338,14 @@ async function initializeApp() {
|
||||
});
|
||||
}
|
||||
|
||||
const queryStoreButton = document.getElementById("queryStoreButton");
|
||||
if (queryStoreButton) {
|
||||
queryStoreButton.addEventListener("click", () => {
|
||||
console.log("Query Store button clicked");
|
||||
queryStoreMessages();
|
||||
});
|
||||
}
|
||||
|
||||
initCharts();
|
||||
(window as any).onDiscoveryUpdate = onDiscoveryUpdate;
|
||||
(window as any).onConnectionsUpdate = onConnectionsUpdate;
|
||||
|
||||
@ -322,3 +322,82 @@ export function recordLatency(id: string, sent: number, received?: number) {
|
||||
export function wireUiToggles() {
|
||||
setupCollapsibles();
|
||||
}
|
||||
|
||||
// Store Query UI
|
||||
const storeQueryStatusEl = document.getElementById("storeQueryStatus") as HTMLDivElement | null;
|
||||
const storeQueryResultsEl = document.getElementById("storeQueryResults") as HTMLDivElement | null;
|
||||
|
||||
export function updateStoreQueryStatus(message: string, isError: boolean = false) {
|
||||
if (!storeQueryStatusEl) return;
|
||||
storeQueryStatusEl.textContent = message;
|
||||
storeQueryStatusEl.style.color = isError ? '#d32f2f' : '#2e7d32';
|
||||
storeQueryStatusEl.style.fontWeight = 'bold';
|
||||
storeQueryStatusEl.style.marginTop = '10px';
|
||||
}
|
||||
|
||||
export function displayStoreQueryResults(messages: ChatMessage[]) {
|
||||
if (!storeQueryResultsEl) return;
|
||||
|
||||
storeQueryResultsEl.innerHTML = "";
|
||||
|
||||
if (messages.length === 0) {
|
||||
storeQueryResultsEl.innerHTML = "<p style='color: #666; font-style: italic;'>No messages found.</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
const title = document.createElement("h3");
|
||||
title.textContent = `Found ${messages.length} message${messages.length !== 1 ? 's' : ''}:`;
|
||||
title.style.marginTop = "15px";
|
||||
storeQueryResultsEl.appendChild(title);
|
||||
|
||||
messages.forEach((message, index) => {
|
||||
const item = document.createElement("div");
|
||||
item.classList.add("message-item");
|
||||
item.style.marginBottom = "10px";
|
||||
item.style.padding = "10px";
|
||||
item.style.border = "1px solid #ddd";
|
||||
item.style.borderRadius = "4px";
|
||||
item.style.backgroundColor = "#f9f9f9";
|
||||
|
||||
const indexLabel = document.createElement("p");
|
||||
indexLabel.style.fontWeight = "bold";
|
||||
indexLabel.style.marginBottom = "5px";
|
||||
indexLabel.textContent = `Message ${index + 1}`;
|
||||
|
||||
const idText = document.createElement("p");
|
||||
idText.style.fontSize = "0.9em";
|
||||
idText.style.color = "#666";
|
||||
idText.textContent = `ID: ${message.id}`;
|
||||
|
||||
const contentP = document.createElement("p");
|
||||
contentP.style.margin = "8px 0";
|
||||
contentP.textContent = message.content;
|
||||
|
||||
const senderInfoP = document.createElement("p");
|
||||
senderInfoP.style.fontSize = "0.9em";
|
||||
senderInfoP.style.color = "#666";
|
||||
senderInfoP.textContent = `From: ${message.senderPeerId.substring(0, 12)}...`;
|
||||
|
||||
const timestampP = document.createElement("p");
|
||||
timestampP.style.fontSize = "0.9em";
|
||||
timestampP.style.color = "#666";
|
||||
timestampP.textContent = `Time: ${new Date(message.timestamp).toLocaleString()}`;
|
||||
|
||||
item.appendChild(indexLabel);
|
||||
item.appendChild(idText);
|
||||
item.appendChild(contentP);
|
||||
item.appendChild(senderInfoP);
|
||||
item.appendChild(timestampP);
|
||||
|
||||
storeQueryResultsEl.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
export function clearStoreQueryResults() {
|
||||
if (storeQueryResultsEl) {
|
||||
storeQueryResultsEl.innerHTML = "";
|
||||
}
|
||||
if (storeQueryStatusEl) {
|
||||
storeQueryStatusEl.textContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user