Merge branch 'unstable' into optimize-watch-history-publish-13715338775513051648

This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-05 15:35:38 -05:00
commit 0e7940eb56
3 files changed
+98 -23

No files matched your search

+69
View File
@@ -0,0 +1,69 @@
import { createWatchHistoryManager } from "../js/nostr/watchHistory.js";
async function main() {
console.log("Starting WatchHistoryManager benchmark...");
// Mock dependencies
const mockSigner = {
signEvent: async (event) => {
// Simulate signing latency
await new Promise(resolve => setTimeout(resolve, 10));
return { ...event, sig: "mock-sig" };
},
nip04Encrypt: async (pubkey, plaintext) => {
await new Promise(resolve => setTimeout(resolve, 5));
return "mock-ciphertext";
}
};
const mockPool = {
publish: (relays, event) => {
return {
on: (status, cb) => {
if (status === 'ok') {
// Simulate network latency
setTimeout(cb, 50);
}
}
}
}
};
const deps = {
ensureNostrTools: async () => ({
nip04: { encrypt: async () => "encrypted" },
utils: { hexToBytes: () => new Uint8Array(32) }
}),
getCachedNostrTools: () => ({
nip04: { encrypt: async () => "encrypted" },
utils: { hexToBytes: () => new Uint8Array(32) }
}),
getActivePubkey: () => "00".repeat(32),
getSessionActor: () => null,
resolveActiveSigner: () => mockSigner,
getPool: () => mockPool,
signEventWithPrivateKey: async () => {
await new Promise(resolve => setTimeout(resolve, 10));
return { sig: "mock-sig" };
},
shouldRequestExtensionPermissions: () => false,
};
const manager = createWatchHistoryManager(deps);
// Create records for 12 months
const records = {};
for (let i = 1; i <= 12; i++) {
const month = `2023-${String(i).padStart(2, '0')}`;
records[month] = [{ type: 'e', value: `item-${i}`, watchedAt: 1672531200 + i * 100 }];
}
const start = Date.now();
await manager.publishRecords(records, { actorPubkey: "00".repeat(32) });
const duration = Date.now() - start;
console.log(`Published 12 months in ${duration}ms`);
}
main().catch(console.error);
+24 -22
View File
@@ -1908,30 +1908,32 @@ class WatchHistoryManager {
const chunkEvents = Array.isArray(results)
? results.flat().filter((event) => event && typeof event === "object")
: [];
const decryptionPromises = chunkEvents.map(async (event) => {
const ciphertext = typeof event.content === "string" ? event.content : "";
if (!ciphertext) {
return [];
}
let plaintext = "";
if (typeof decryptSigner.nip04Decrypt === "function") {
try {
plaintext = await decryptSigner.nip04Decrypt(actorKey, ciphertext);
} catch (error) {
devLogger.warn("[nostr] Failed to decrypt watch history chunk:", error);
const chunkResults = await pMap(
chunkEvents,
async (event) => {
const ciphertext = typeof event.content === "string" ? event.content : "";
if (!ciphertext) {
return [];
}
let plaintext = "";
if (typeof decryptSigner.nip04Decrypt === "function") {
try {
plaintext = await decryptSigner.nip04Decrypt(actorKey, ciphertext);
} catch (error) {
devLogger.warn("[nostr] Failed to decrypt watch history chunk:", error);
}
}
if (!plaintext) {
return [];
}
const parsed = parseWatchHistoryPayload(plaintext);
if (Array.isArray(parsed.items) && parsed.items.length) {
return parsed.items;
}
}
if (!plaintext) {
return [];
}
const parsed = parseWatchHistoryPayload(plaintext);
if (Array.isArray(parsed.items) && parsed.items.length) {
return parsed.items;
}
return [];
});
const chunkResults = await Promise.all(decryptionPromises);
},
{ concurrency: 5 },
);
decryptedItems.push(...chunkResults.flat());
} catch (error) {
devLogger.warn("[nostr] Failed to fetch watch history chunks:", error);
+5 -1
View File
@@ -367,8 +367,12 @@ class ProfileCache {
return userCache ? userCache.get(section) : undefined;
}
/**
* Clears all cached data for a specific public key from memory.
* This operation is O(1) thanks to the nested map structure.
* @param {string} pubkey - The hex public key to clear.
*/
clearMemoryCache(pubkey) {
// Optimized: O(1) deletion due to nested map structure
this.memoryCache.delete(pubkey);
}