diff --git a/lib/storage/items.js b/lib/storage/items.js index 7e25096..002762b 100644 --- a/lib/storage/items.js +++ b/lib/storage/items.js @@ -288,6 +288,46 @@ export async function countReadItems(application, channelId, userId) { * @param {string} userId - User ID * @returns {Promise} 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; } diff --git a/package.json b/package.json index e92e396..f3dbbfe 100644 --- a/package.json +++ b/package.json @@ -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",