feat: cleanup old read items (keep last 30 per channel)

Prevents database accumulation by automatically deleting older read
items when marking items as read. Keeps the 30 most recent read items
per channel per user to allow revisiting recently read content.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ricardo
2026-02-06 22:59:46 +01:00
parent 59cbe7c238
commit 61819f1aeb
2 changed files with 49 additions and 1 deletions

View File

@@ -288,6 +288,46 @@ export async function countReadItems(application, channelId, userId) {
* @param {string} userId - User ID
* @returns {Promise<number>} Number of items updated
*/
// Maximum number of read items to keep per channel
const MAX_READ_ITEMS = 30;
/**
* Cleanup old read items, keeping only the most recent MAX_READ_ITEMS
* @param {object} collection - MongoDB collection
* @param {ObjectId} channelObjectId - Channel ObjectId
* @param {string} userId - User ID
*/
async function cleanupOldReadItems(collection, channelObjectId, userId) {
// Count read items in this channel
const readCount = await collection.countDocuments({
channelId: channelObjectId,
readBy: userId,
});
if (readCount > MAX_READ_ITEMS) {
// Find the oldest read items to delete
const itemsToDelete = await collection
.find({
channelId: channelObjectId,
readBy: userId,
})
.sort({ published: -1, _id: -1 }) // Newest first
.skip(MAX_READ_ITEMS) // Skip the ones we want to keep
.project({ _id: 1 })
.toArray();
if (itemsToDelete.length > 0) {
const idsToDelete = itemsToDelete.map((item) => item._id);
const deleteResult = await collection.deleteMany({
_id: { $in: idsToDelete },
});
console.info(
`[Microsub] Cleaned up ${deleteResult.deletedCount} old read items (keeping ${MAX_READ_ITEMS})`,
);
}
}
}
export async function markItemsRead(application, channelId, entryIds, userId) {
const collection = getCollection(application);
const channelObjectId =
@@ -309,6 +349,10 @@ export async function markItemsRead(application, channelId, entryIds, userId) {
console.info(
`[Microsub] Marked all items as read: ${result.modifiedCount} updated`,
);
// Cleanup old read items, keeping only the most recent
await cleanupOldReadItems(collection, channelObjectId, userId);
return result.modifiedCount;
}
@@ -339,6 +383,10 @@ export async function markItemsRead(application, channelId, entryIds, userId) {
console.info(
`[Microsub] markItemsRead result: ${result.modifiedCount} items updated`,
);
// Cleanup old read items, keeping only the most recent
await cleanupOldReadItems(collection, channelObjectId, userId);
return result.modifiedCount;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@rmdes/indiekit-endpoint-microsub",
"version": "1.0.19",
"version": "1.0.20",
"description": "Microsub endpoint for Indiekit. Enables subscribing to feeds and reading content using the Microsub protocol.",
"keywords": [
"indiekit",