forked from snxraven/p2ns
Updates
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Peer Paste",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"domain": "peer.paste",
|
||||
"enabled": true,
|
||||
"description": "Temporary P2P text snippets with expiration and burn-after-read options",
|
||||
|
||||
@@ -9,6 +9,7 @@ const MAX_CONTENT_CHARS = 100000;
|
||||
const MAX_TITLE_CHARS = 120;
|
||||
const MAX_LANGUAGE_CHARS = 32;
|
||||
const MAX_MAXREADS = 1000000;
|
||||
const MAX_LIST_SCAN = 500;
|
||||
|
||||
let cleanupTimer = null;
|
||||
|
||||
@@ -85,10 +86,61 @@ async function deletePaste(paste) {
|
||||
await sdk.db.delete(COLLECTION, { id: paste.id });
|
||||
}
|
||||
|
||||
function isQueryTimeoutError(err) {
|
||||
const msg = (err && err.message) || '';
|
||||
return msg.includes('Query timeout') || msg.includes('stream did not complete within');
|
||||
}
|
||||
|
||||
async function safeFindPastes(options = {}) {
|
||||
const {
|
||||
includeExpired = true,
|
||||
maxEntries = MAX_LIST_SCAN,
|
||||
retryOnTimeout = true,
|
||||
context = 'query'
|
||||
} = options;
|
||||
|
||||
const queryOptions = { limit: maxEntries };
|
||||
const run = async () => sdk.db.find(COLLECTION, {}, queryOptions);
|
||||
|
||||
try {
|
||||
let rows = await run();
|
||||
if (!includeExpired) {
|
||||
const t = now();
|
||||
rows = rows.filter((p) => p.expiresAt > t);
|
||||
}
|
||||
return { rows, timedOut: false };
|
||||
} catch (err) {
|
||||
if (!isQueryTimeoutError(err) || !retryOnTimeout) throw err;
|
||||
sdk.log.warn('peer.paste', `${context}: timed out, retrying once (${err.message})`);
|
||||
}
|
||||
|
||||
try {
|
||||
let rows = await run();
|
||||
if (!includeExpired) {
|
||||
const t = now();
|
||||
rows = rows.filter((p) => p.expiresAt > t);
|
||||
}
|
||||
return { rows, timedOut: false };
|
||||
} catch (err) {
|
||||
if (isQueryTimeoutError(err)) {
|
||||
sdk.log.warn('peer.paste', `${context}: timeout persisted, returning empty fallback`);
|
||||
return { rows: [], timedOut: true };
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanupExpiredPastes() {
|
||||
try {
|
||||
const t = now();
|
||||
const pastes = await sdk.db.find(COLLECTION, {});
|
||||
const { rows: pastes, timedOut } = await safeFindPastes({
|
||||
includeExpired: true,
|
||||
maxEntries: MAX_LIST_SCAN,
|
||||
context: 'cleanupExpiredPastes'
|
||||
});
|
||||
if (timedOut) {
|
||||
return { deleted: 0, timedOut: true };
|
||||
}
|
||||
let deleted = 0;
|
||||
|
||||
for (const paste of pastes) {
|
||||
@@ -104,10 +156,10 @@ async function cleanupExpiredPastes() {
|
||||
await sdk.db.flush();
|
||||
sdk.log.info('peer.paste', `Cleanup removed ${deleted} expired/consumed paste(s)`);
|
||||
}
|
||||
return { deleted };
|
||||
return { deleted, timedOut: false };
|
||||
} catch (err) {
|
||||
sdk.log.error('peer.paste', `Cleanup failed: ${err.message}`);
|
||||
throw err;
|
||||
return { deleted: 0, error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +214,11 @@ async function createPaste(req, res) {
|
||||
}
|
||||
|
||||
async function listPastes(req, res, ownerOnly = false) {
|
||||
const all = await sdk.db.find(COLLECTION, {});
|
||||
const { rows: all, timedOut } = await safeFindPastes({
|
||||
includeExpired: false,
|
||||
maxEntries: MAX_LIST_SCAN,
|
||||
context: ownerOnly ? 'listPastes(mine)' : 'listPastes(all)'
|
||||
});
|
||||
const t = now();
|
||||
const ownerPeerId = sdk.state.localPeerId || '';
|
||||
const search = sanitizeText(req.query?.search || '').toLowerCase();
|
||||
@@ -182,7 +238,8 @@ async function listPastes(req, res, ownerOnly = false) {
|
||||
|
||||
return sdk.router.json(res, {
|
||||
count: pastes.length,
|
||||
pastes
|
||||
pastes,
|
||||
degraded: timedOut
|
||||
});
|
||||
}
|
||||
|
||||
@@ -281,7 +338,11 @@ async function deletePasteRoute(req, res, pasteId) {
|
||||
}
|
||||
|
||||
async function getStats(res) {
|
||||
const all = await sdk.db.find(COLLECTION, {});
|
||||
const { rows: all, timedOut } = await safeFindPastes({
|
||||
includeExpired: true,
|
||||
maxEntries: MAX_LIST_SCAN,
|
||||
context: 'getStats'
|
||||
});
|
||||
const t = now();
|
||||
const active = all.filter((p) => p.expiresAt > t);
|
||||
const expired = all.length - active.length;
|
||||
@@ -299,7 +360,8 @@ async function getStats(res) {
|
||||
burnEnabled,
|
||||
totalReads,
|
||||
mine,
|
||||
timestamp: t
|
||||
timestamp: t,
|
||||
degraded: timedOut
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user