Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 104 additions & 82 deletions workspaces/server/src/websocket/commands/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,107 +2,129 @@
import type { PayloadsList } from "@nodesecure/cache";

// Import Internal Dependencies
import { context } from "../websocket.als.js";
import type {
WebSocketContext,
WebSocketResponse
WebSocketResponse,
WebSocketContext
} from "../websocket.types.js";

export async function* remove(
spec: string,
context: WebSocketContext
spec: string
): AsyncGenerator<WebSocketResponse, void, unknown> {
const { cache, logger } = context;
const ctx = context.getStore()!;

const { mru, lru, current, lastUsed, root, availables } = await cache.payloadsList();
delete lastUsed[spec];
if (availables.includes(spec)) {
logger.info("[ws|command.remove] remove from availables");
cache.removePayload(spec);
const updatedList: PayloadsList = {
mru,
current,
lru,
lastUsed: {
...lastUsed
},
root,
availables: availables.filter((iterSpec) => iterSpec !== spec)
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
cache: updatedList
};

return;
const cacheList = await ctx.cache.payloadsList();
let updatedList: PayloadsList;
if (cacheList.availables.includes(spec)) {
updatedList = await removeFromAvailables(spec, ctx, cacheList);
}
else {
updatedList = await removeFromMruOrLru(spec, ctx, cacheList);
}

logger.debug(`[ws|command.remove](lru: ${lru}|current: ${current})`);
yield {
status: "RELOAD",
cache: updatedList
};
}

async function removeFromAvailables(
spec: string,
context: WebSocketContext,
cacheList: PayloadsList
): Promise<PayloadsList> {
const { cache, logger } = context;
const { availables, lastUsed, ...rest } = cacheList;

logger.info("[ws|command.remove] remove from availables");
const { [spec]: _, ...updatedLastUsed } = lastUsed;
const updatedList: PayloadsList = {
...rest,
lastUsed: updatedLastUsed,
availables: availables.filter((iterSpec) => iterSpec !== spec)
};

await cache.updatePayloadsList(updatedList);
cache.removePayload(spec);

return updatedList;
}

async function removeFromMruOrLru(
spec: string,
context: WebSocketContext,
cacheList: PayloadsList
): Promise<PayloadsList> {
const { logger, cache } = context;
const { mru, lru, current } = cacheList;

logger.debug(`[ws|command.remove](lru: ${lru}|current: ${current})`);
if (mru.length === 1 && lru.length === 0) {
throw new Error("Cannot remove the last package.");
}

const mruIndex = mru.findIndex((iterSpec) => iterSpec === spec);
const lruIndex = lru.findIndex((iterSpec) => iterSpec === spec);

if (mruIndex === -1 && lruIndex === -1) {
throw new Error("Package not found in cache.");
}

if (mruIndex > -1) {
logger.info("[ws|command.remove] removed from mru");
const updatedMru = mru.filter((iterSpec) => iterSpec !== spec);
if (lru.length > 0) {
// We need to move the first lru package to the mru list
const olderLruPkg = lru.sort((a, b) => {
const aDate = lastUsed[a];
const bDate = lastUsed[b];

return aDate - bDate;
});
updatedMru.push(olderLruPkg[0]);
lru.splice(lru.indexOf(olderLruPkg[0]), 1);
}

const updatedList: PayloadsList = {
mru: updatedMru,
lru,
lastUsed: {
...lastUsed
},
current: current === spec ? updatedMru[0] : current,
root,
availables
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
cache: updatedList
};
}
else {
logger.info("[ws|command.remove] removed from lru");
const updatedLru = lru.filter((iterSpec) => iterSpec !== spec);
const updatedList: PayloadsList = {
mru,
lru: updatedLru,
availables,
lastUsed: {
...lastUsed
},
current,
root
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
cache: updatedList
};
}
const isInMru = mruIndex > -1;
logger.info(`[ws|command.remove] removing from ${isInMru ? "MRU" : "LRU"}`);
const updatedList = isInMru ?
removeFromMru(spec, cacheList) :
removeFromLru(spec, cacheList);

await cache.updatePayloadsList(updatedList);
cache.removePayload(spec);

return updatedList;
}

function removeFromMru(
spec: string,
cacheList: PayloadsList
): PayloadsList {
const { mru, lru, current, lastUsed, root, availables } = cacheList;

const updatedMru = mru.filter((iterSpec) => iterSpec !== spec);
let updatedLru = lru;

if (lru.length > 0) {
const sortedLru = [...lru].sort((a, b) => lastUsed[a] - lastUsed[b]);
const olderLruPkg = sortedLru[0];
updatedMru.push(olderLruPkg);
updatedLru = lru.filter((iterSpec) => iterSpec !== olderLruPkg);
}

const { [spec]: _, ...updatedLastUsed } = lastUsed;
const updatedList: PayloadsList = {
mru: updatedMru,
lru: updatedLru,
lastUsed: updatedLastUsed,
current: current === spec ? updatedMru[0] : current,
root,
availables
};

return updatedList;
}

function removeFromLru(
spec: string,
cacheList: PayloadsList
): PayloadsList {
const { mru, lru, current, lastUsed, root, availables } = cacheList;

const { [spec]: _, ...updatedLastUsed } = lastUsed;
const updatedList: PayloadsList = {
mru,
lru: lru.filter((iterSpec) => iterSpec !== spec),
availables,
lastUsed: updatedLastUsed,
current,
root
};

return updatedList;
}
Loading