Skip to content

Commit b9d3f95

Browse files
Reduce RAM consumption when handling webmentions (#113)
* Reduce RAM consumption when handling webmentions * Recommended updates form Copilot
1 parent 1d92054 commit b9d3f95

File tree

1 file changed

+90
-3
lines changed

1 file changed

+90
-3
lines changed

src/_data/webmentions.js

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,65 @@ const domain = site.domain;
1818
const spammers_file = "src/_data/webmention_spammers.json";
1919
const spammers = JSON.parse(fs.readFileSync(spammers_file));
2020

21+
// Configuration constants for optimization
22+
const MAX_NAME_LENGTH = 200; // Reasonable limit for webmention names to avoid storing extremely long titles
23+
24+
// Optimize webmention data to reduce memory usage
25+
function optimizeWebmention(mention) {
26+
const optimized = {
27+
"wm-id": mention["wm-id"],
28+
"wm-target": mention["wm-target"],
29+
"wm-property": mention["wm-property"],
30+
url: mention.url,
31+
published: mention.published
32+
};
33+
34+
// Only include author data if it exists and has useful info
35+
if (mention.author && (mention.author.name || mention.author.photo || mention.author.url)) {
36+
optimized.author = {};
37+
if (mention.author.name) optimized.author.name = mention.author.name;
38+
if (mention.author.photo) optimized.author.photo = mention.author.photo;
39+
if (mention.author.url) optimized.author.url = mention.author.url;
40+
}
41+
42+
// Only include content if it exists and is meaningful
43+
if (mention.content) {
44+
const hasContent = mention.content.html || mention.content.text;
45+
if (hasContent) {
46+
optimized.content = {};
47+
if (mention.content.html) optimized.content.html = mention.content.html;
48+
if (mention.content.text) optimized.content.text = mention.content.text;
49+
// Include 'value' as fallback only if no other content is present
50+
} else if (mention.content.value) {
51+
optimized.content = { value: mention.content.value };
52+
}
53+
}
54+
55+
// Include name only if it's reasonably short and useful
56+
if (mention.name && mention.name.length <= MAX_NAME_LENGTH) {
57+
optimized.name = mention.name;
58+
}
59+
60+
// Include summary as fallback content
61+
if (mention.summary && !optimized.content) {
62+
optimized.summary = mention.summary;
63+
}
64+
65+
// Include webmention type properties
66+
['like-of', 'repost-of', 'in-reply-to', 'mention-of', 'bookmark-of'].forEach(prop => {
67+
if (mention[prop]) {
68+
optimized[prop] = mention[prop];
69+
}
70+
});
71+
72+
// Include wm-source for Twitter/Mastodon detection
73+
if (mention["wm-source"]) {
74+
optimized["wm-source"] = mention["wm-source"];
75+
}
76+
77+
return optimized;
78+
}
79+
2180
async function fetchWebmentions(since, perPage = 10000) {
2281
// If we dont have a domain name or token, abort
2382
if (!domain || !TOKEN) {
@@ -92,8 +151,20 @@ export default async function () {
92151
console.log(">>> Reading webmentions from cache...");
93152

94153
const cache = readFromCache();
154+
let optimizedChildren = [];
155+
95156
if (cache.children.length) {
96157
console.log(`>>> ${cache.children.length} webmentions loaded from cache`);
158+
159+
// Optimize webmentions data in memory to reduce build-time memory usage
160+
console.log(">>> Optimizing webmentions data for memory efficiency...");
161+
const startData = JSON.stringify(cache.children);
162+
const startSize = Buffer.byteLength(startData, 'utf8');
163+
optimizedChildren = cache.children.map(optimizeWebmention);
164+
const endData = JSON.stringify(optimizedChildren);
165+
const endSize = Buffer.byteLength(endData, 'utf8');
166+
const savings = ((startSize - endSize) / startSize * 100).toFixed(1);
167+
console.log(`>>> Memory optimization: ${savings}% reduction (${(startSize/1024/1024).toFixed(1)}MB -> ${(endSize/1024/1024).toFixed(1)}MB)`);
97168
}
98169

99170
// Only fetch new mentions in production
@@ -102,14 +173,30 @@ export default async function () {
102173
const feed = await fetchWebmentions(cache.lastFetched);
103174

104175
if (feed) {
176+
const mergedChildren = mergeWebmentions(cache, feed);
177+
178+
// Save unoptimized version to cache for future fetches
105179
const webmentions = {
106180
lastFetched: new Date().toISOString(),
107-
children: mergeWebmentions(cache, feed),
181+
children: mergedChildren,
108182
};
109183
writeToCache(webmentions);
110-
return excludeSpammers(webmentions);
184+
185+
// Return optimized version for build
186+
const optimizedWebmentions = {
187+
lastFetched: webmentions.lastFetched,
188+
children: mergedChildren.map(optimizeWebmention)
189+
};
190+
191+
return excludeSpammers(optimizedWebmentions);
111192
}
112193
}
113194

114-
return excludeSpammers(cache);
195+
// Return optimized cache data
196+
const optimizedCache = {
197+
lastFetched: cache.lastFetched,
198+
children: optimizedChildren
199+
};
200+
201+
return excludeSpammers(optimizedCache);
115202
}

0 commit comments

Comments
 (0)