diff --git a/packages/endpoint-cache/package.json b/packages/endpoint-cache/package.json index 1efc7e7042a7..62a6a7df1da8 100644 --- a/packages/endpoint-cache/package.json +++ b/packages/endpoint-cache/package.json @@ -17,7 +17,7 @@ "module": "./dist/es/index.js", "types": "./dist/types/index.d.ts", "dependencies": { - "mnemonist": "0.38.3", + "@aws-sdk/lru-cache": "3.0.0", "tslib": "^2.0.0" }, "devDependencies": { diff --git a/packages/endpoint-cache/src/EndpointCache.spec.ts b/packages/endpoint-cache/src/EndpointCache.spec.ts index e9e31a3d51ba..7259f853e739 100644 --- a/packages/endpoint-cache/src/EndpointCache.spec.ts +++ b/packages/endpoint-cache/src/EndpointCache.spec.ts @@ -1,9 +1,9 @@ -import LRUCache from "mnemonist/lru-cache"; +import { LRUCache } from "@aws-sdk/lru-cache"; import { Endpoint } from "./Endpoint"; import { EndpointCache } from "./EndpointCache"; -jest.mock("mnemonist/lru-cache"); +jest.mock("@aws-sdk/lru-cache"); describe(EndpointCache.name, () => { let endpointCache; @@ -11,11 +11,11 @@ describe(EndpointCache.name, () => { const key = "key"; const now = Date.now(); - const set = jest.fn(); - const get = jest.fn(); - const peek = jest.fn(); - const has = jest.fn(); - const clear = jest.fn(); + const mockSet = jest.fn(); + const mockDelete = jest.fn(); + const mockGet = jest.fn(); + const mockHas = jest.fn(); + const mockClear = jest.fn(); const mockEndpoints = [ { Address: "addressA", CachePeriodInMinutes: 1 }, @@ -33,11 +33,11 @@ describe(EndpointCache.name, () => { beforeEach(() => { ((LRUCache as unknown) as jest.Mock).mockReturnValueOnce({ - set, - get, - peek, - has, - clear, + set: mockSet, + get: mockGet, + delete: mockDelete, + has: mockHas, + clear: mockClear, }); endpointCache = new EndpointCache(capacity); }); @@ -53,45 +53,41 @@ describe(EndpointCache.name, () => { describe("get", () => { beforeEach(() => { - has.mockReturnValue(true); + mockHas.mockReturnValue(true); const endpointsWithExpiry = getEndpointsWithExpiry(mockEndpoints); - peek.mockReturnValue(endpointsWithExpiry); - get.mockReturnValue(endpointsWithExpiry); + mockGet.mockReturnValue(endpointsWithExpiry); jest.spyOn(Date, "now").mockImplementation(() => now); }); const verifyHasAndGetCalls = () => { - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); - expect(get).toHaveBeenCalledTimes(1); - expect(get).toHaveBeenCalledWith(key); + expect(mockHas).toHaveBeenCalledTimes(1); + expect(mockHas).toHaveBeenCalledWith(key); + expect(mockGet).toHaveBeenCalledTimes(1); + expect(mockGet).toHaveBeenCalledWith(key); }; it("returns undefined if cache doesn't have key", () => { - has.mockReturnValueOnce(false); + mockHas.mockReturnValueOnce(false); expect(endpointCache.get(key)).toBeUndefined(); - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); - expect(peek).not.toHaveBeenCalled(); - expect(get).not.toHaveBeenCalled(); + expect(mockHas).toHaveBeenCalledTimes(1); + expect(mockHas).toHaveBeenCalledWith(key); + expect(mockGet).not.toHaveBeenCalled(); }); it("returns undefined if cache has empty array", () => { - has.mockReturnValueOnce(true); - peek.mockReturnValueOnce([]); + mockHas.mockReturnValueOnce(true); + mockGet.mockReturnValue([]); expect(endpointCache.get(key)).toBeUndefined(); - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); - expect(peek).toHaveBeenCalledTimes(1); - expect(peek).toHaveBeenCalledWith(key); - expect(get).not.toHaveBeenCalled(); + verifyHasAndGetCalls(); + expect(mockDelete).toHaveBeenCalledTimes(1); + expect(mockDelete).toHaveBeenCalledWith(key); }); it("returns undefined if cache returns undefined for key", () => { - get.mockReturnValueOnce(undefined); + mockGet.mockReturnValueOnce(undefined); expect(endpointCache.get(key)).toBeUndefined(); verifyHasAndGetCalls(); - expect(set).not.toHaveBeenCalled(); + expect(mockSet).not.toHaveBeenCalled(); }); it("returns undefined if endpoints have expired", () => { @@ -99,22 +95,22 @@ describe(EndpointCache.name, () => { jest.spyOn(Date, "now").mockImplementation(() => now + (maxCachePeriod + 1) * 60 * 1000); expect(endpointCache.get(key)).toBeUndefined(); verifyHasAndGetCalls(); - expect(set).toHaveBeenCalledTimes(1); - expect(set).toHaveBeenCalledWith(key, []); + expect(mockDelete).toHaveBeenCalledTimes(1); + expect(mockDelete).toHaveBeenCalledWith(key); }); describe("getEndpoint", () => { it("returns one of the un-expired endpoints", () => { expect(mockEndpoints.map((endpoint) => endpoint.Address)).toContain(endpointCache.getEndpoint(key)); verifyHasAndGetCalls(); - expect(set).not.toHaveBeenCalled(); + expect(mockSet).not.toHaveBeenCalled(); }); it("returns un-expired endpoint", () => { jest.spyOn(Date, "now").mockImplementation(() => now + 90 * 1000); expect(endpointCache.getEndpoint(key)).toEqual(mockEndpoints[1].Address); verifyHasAndGetCalls(); - expect(set).not.toHaveBeenCalled(); + expect(mockSet).not.toHaveBeenCalled(); }); [0, 1].forEach((index) => { @@ -122,7 +118,7 @@ describe(EndpointCache.name, () => { jest.spyOn(Math, "floor").mockImplementation(() => index); expect(mockEndpoints.map((endpoint) => endpoint.Address)).toContain(endpointCache.getEndpoint(key)); verifyHasAndGetCalls(); - expect(set).not.toHaveBeenCalled(); + expect(mockSet).not.toHaveBeenCalled(); }); }); }); @@ -135,8 +131,8 @@ describe(EndpointCache.name, () => { it("converts CachePeriodInMinutes to Expires before caching", () => { endpointCache.set(key, mockEndpoints); - expect(set).toHaveBeenCalledTimes(1); - expect(set).toHaveBeenCalledWith( + expect(mockSet).toHaveBeenCalledTimes(1); + expect(mockSet).toHaveBeenCalledWith( key, mockEndpoints.map(({ Address, CachePeriodInMinutes }) => ({ Address, @@ -148,47 +144,21 @@ describe(EndpointCache.name, () => { it("delete", () => { endpointCache.delete(key); - expect(set).toHaveBeenCalledTimes(1); - expect(set).toHaveBeenCalledWith(key, []); + expect(mockDelete).toHaveBeenCalledTimes(1); + expect(mockDelete).toHaveBeenCalledWith(key); }); describe("has", () => { - describe("returns false", () => { - it("when key is not present", () => { - has.mockReturnValueOnce(false); - expect(endpointCache.has(key)).toEqual(false); - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); - }); - - it("when key is present and value is empty", () => { - has.mockReturnValueOnce(true); - peek.mockReturnValueOnce([]); - expect(endpointCache.has(key)).toEqual(false); - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); - }); - - it("when key is present and value is undefined", () => { - has.mockReturnValueOnce(true); - peek.mockReturnValueOnce(undefined); - expect(endpointCache.has(key)).toEqual(false); - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); - }); - }); - - it("returns true when key is present and value is non-empty", () => { - has.mockReturnValueOnce(true); - peek.mockReturnValueOnce(getEndpointsWithExpiry(mockEndpoints)); - expect(endpointCache.has(key)).toEqual(true); - expect(has).toHaveBeenCalledTimes(1); - expect(has).toHaveBeenCalledWith(key); + it.each([false, true])("returns value cache.has call: %p", (expected) => { + mockHas.mockReturnValueOnce(expected); + expect(endpointCache.has(key)).toEqual(expected); + expect(mockHas).toHaveBeenCalledTimes(1); + expect(mockHas).toHaveBeenCalledWith(key); }); }); it("clear", () => { endpointCache.clear(); - expect(clear).toHaveBeenCalledTimes(1); + expect(mockClear).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/endpoint-cache/src/EndpointCache.ts b/packages/endpoint-cache/src/EndpointCache.ts index 2403ea0df7e1..34974564b7b0 100644 --- a/packages/endpoint-cache/src/EndpointCache.ts +++ b/packages/endpoint-cache/src/EndpointCache.ts @@ -1,4 +1,4 @@ -import LRUCache from "mnemonist/lru-cache"; +import { LRUCache } from "@aws-sdk/lru-cache"; import { Endpoint } from "./Endpoint"; @@ -81,9 +81,7 @@ export class EndpointCache { * @param {string} key */ delete(key: string) { - // Replace with remove/delete call once support is added upstream - // Refs: https://github.com/Yomguithereal/mnemonist/issues/143 - this.cache.set(key, []); + this.cache.delete(key); } /** @@ -93,17 +91,7 @@ export class EndpointCache { * @returns {boolean} */ has(key: string): boolean { - if (!this.cache.has(key)) { - return false; - } - - // Remove call for peek, once remove/delete support is added upstream - // Refs: https://github.com/Yomguithereal/mnemonist/issues/143 - const endpoints = this.cache.peek(key); - if (!endpoints) { - return false; - } - return endpoints.length > 0; + return this.cache.has(key); } /** diff --git a/yarn.lock b/yarn.lock index c030d6ddc4f3..0679bbcca6ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8260,13 +8260,6 @@ mkdirp@0.5.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: dependencies: minimist "^1.2.5" -mnemonist@0.38.3: - version "0.38.3" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.3.tgz#35ec79c1c1f4357cfda2fe264659c2775ccd7d9d" - integrity sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw== - dependencies: - obliterator "^1.6.1" - mocha@^8.0.1: version "8.3.2" resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.3.2.tgz#53406f195fa86fbdebe71f8b1c6fb23221d69fcc" @@ -8759,11 +8752,6 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -obliterator@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-1.6.1.tgz#dea03e8ab821f6c4d96a299e17aef6a3af994ef3" - integrity sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig== - octokit-pagination-methods@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"