Skip to content

Commit

Permalink
Merge pull request #490 from hgrsd/fix-cache-false-positive
Browse files Browse the repository at this point in the history
fix(cache): cache key comparison ignores milliseconds
  • Loading branch information
jkbrzt authored Nov 28, 2021
2 parents c512a1b + 3e6bd20 commit f446250
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ import { isArray } from './helpers'

export type CacheKeys = 'before' | 'after' | 'between'

function argsMatch (
left: IterArgs[keyof IterArgs] | undefined,
right: IterArgs[keyof IterArgs] | undefined
) {
if (Array.isArray(left)) {
if (!Array.isArray(right)) return false
if (left.length !== right.length) return false
return left.every((date, i) => date.getTime() === right[i].getTime())
}

if (left instanceof Date) {
return right instanceof Date && left.getTime() === right.getTime()
}

return left === right
}

export class Cache {
all: Date[] | Partial<IterArgs> | false = false
before: IterArgs[] = []
Expand Down Expand Up @@ -51,7 +68,7 @@ export class Cache {
const findCacheDiff = function (item: IterArgs) {
for (let i = 0; i < argsKeys.length; i++) {
const key = argsKeys[i]
if (String(args![key]) !== String(item[key])) {
if (!argsMatch(args![key], item[key])) {
return true
}
}
Expand Down Expand Up @@ -89,5 +106,4 @@ export class Cache {
? dateutil.clone(cached)
: cached
}

}
101 changes: 101 additions & 0 deletions test/cache.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Cache } from "../src/cache";
import { expect } from "chai";
import { IterArgs } from "../src/iterresult";

const dates = [
new Date("2021-01-01T00:00:00.000+00:00"),
new Date("2021-01-02T00:00:00.000+00:00"),
new Date("2021-01-03T00:00:00.000+00:00"),
new Date("2021-01-04T00:00:00.000+00:00"),
new Date("2021-01-05T00:00:00.000+00:00"),
new Date("2021-01-06T00:00:00.000+00:00"),
new Date("2021-01-07T00:00:00.000+00:00"),
];

describe("Cache", () => {
it("returns false for an empty cache", () => {
const cache = new Cache();
const args: Partial<IterArgs> = {
after: new Date("2021-01-01T00:00:00.000+00:00"),
before: new Date("2021-01-08T00:00:00.000+00:00"),
inc: true,
};

expect(cache._cacheGet("between", args)).to.be.false;
});

it("returns an empty array for a cached but empty set", () => {
const cache = new Cache();
const args: Partial<IterArgs> = {
after: new Date("2021-01-01T00:00:00.000+00:00"),
before: new Date("2021-01-08T00:00:00.000+00:00"),
inc: true,
};

cache._cacheAdd("between", [], args);

expect(cache._cacheGet("between", args)).to.eql([]);
});

it('returns cached entries if the "what" and the args both match', () => {
const cache = new Cache();
const args: Partial<IterArgs> = {
after: new Date("2021-01-01T00:00:00.000+00:00"),
before: new Date("2021-01-08T00:00:00.000+00:00"),
inc: true,
};

cache._cacheAdd("between", dates, args);

expect(cache._cacheGet("between", args)).to.eql(dates);
});

it('does not return cached entries if the "what" matches but the args do not', () => {
const cache = new Cache();
const args: Partial<IterArgs> = {
after: new Date("2021-01-01T00:00:00.000+00:00"),
before: new Date("2021-01-08T00:00:00.000+00:00"),
inc: true,
};

cache._cacheAdd("between", dates, args);

expect(
cache._cacheGet("between", {
...args,
/** 1ms later than the args used for the insert */
after: new Date("2021-01-01T00:00:00.001+00:00"),
})
).to.equal(false);
});

it('does not return cached entries if args match but the "what" does not', () => {
const cache = new Cache();
const args: Partial<IterArgs> = {
after: new Date("2021-01-01T00:00:00.000+00:00"),
before: new Date("2021-01-08T00:00:00.000+00:00"),
inc: true,
};

cache._cacheAdd("between", dates, args);

expect(cache._cacheGet("after", args)).to.equal(false);
});

it('reuses dates cached for the "all" method when querying using another method', () => {
const cache = new Cache();
const args: Partial<IterArgs> = {
after: new Date("2021-01-04T00:00:00.000+00:00"),
before: new Date("2021-01-06T00:00:00.000+00:00"),
inc: true,
};

cache._cacheAdd("all", dates);

expect(cache._cacheGet("between", args)).to.eql([
new Date("2021-01-04T00:00:00.000+00:00"),
new Date("2021-01-05T00:00:00.000+00:00"),
new Date("2021-01-06T00:00:00.000+00:00"),
]);
});
});

0 comments on commit f446250

Please sign in to comment.