execution-engine
Version:
A TypeScript library for tracing and visualizing code execution workflows.
123 lines (122 loc) • 6.1 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const cache_decorator_1 = require("./cache.decorator");
describe('cache decorator', () => {
it('should cache async function results and prevent redundant calls', async () => {
let memoizationCheckCount = 0;
let memoizedCalls = 0;
let totalFunctionCalls = 0;
let bypassCache = false;
class DataService {
async fetchData(id) {
totalFunctionCalls++;
return new Promise((resolve) => setTimeout(() => resolve(`Data for ID: ${id}`), 100));
}
async fetchDataWithByPassedCacheFunction(id) {
totalFunctionCalls++;
return new Promise((resolve) => setTimeout(() => resolve(`Data for ID: ${id}`), 100));
}
async throwData(name) {
totalFunctionCalls++;
throw new Error(`hello ${name} but I throw!`);
}
}
__decorate([
(0, cache_decorator_1.cache)({
ttl: 3000,
onCacheEvent: (cacheContext) => {
memoizationCheckCount++;
if (cacheContext.isCached && !cacheContext.isBypassed) {
memoizedCalls++;
}
}
})
], DataService.prototype, "fetchData", null);
__decorate([
(0, cache_decorator_1.cache)({
ttl: 3000,
bypass: () => bypassCache,
onCacheEvent: (cacheContext) => {
memoizationCheckCount++;
if (cacheContext.isCached && !cacheContext.isBypassed) {
memoizedCalls++;
}
}
})
], DataService.prototype, "fetchDataWithByPassedCacheFunction", null);
__decorate([
(0, cache_decorator_1.cache)({
ttl: 3000,
onCacheEvent: (cacheContext) => {
memoizationCheckCount++;
if (cacheContext.isCached) {
memoizedCalls++;
}
}
})
], DataService.prototype, "throwData", null);
const service = new DataService();
memoizationCheckCount = 0;
memoizedCalls = 0;
totalFunctionCalls = 0;
const result1 = await service.fetchData(1);
expect(result1).toBe('Data for ID: 1');
expect(memoizedCalls).toBe(0);
expect(totalFunctionCalls).toBe(1);
expect(memoizationCheckCount).toBe(1); // Called once
const result2 = await service.fetchData(1);
expect(result2).toBe('Data for ID: 1');
expect(memoizedCalls).toBe(1); // Now it should be memoized
expect(totalFunctionCalls).toBe(1); // No new calls
expect(memoizationCheckCount).toBe(2); // Checked twice
const result3 = await service.fetchData(2);
expect(result3).toBe('Data for ID: 2');
expect(memoizedCalls).toBe(1); // No extra memoized calls yet
expect(totalFunctionCalls).toBe(2); // New call for different ID
expect(memoizationCheckCount).toBe(3); // Three checks (1st, 2nd for ID 1, and 3rd for ID 2)
const result4 = await service.fetchData(2);
expect(result4).toBe('Data for ID: 2');
expect(memoizedCalls).toBe(2); // ID 2 result is now memoized
expect(totalFunctionCalls).toBe(2); // No extra new calls
expect(memoizationCheckCount).toBe(4); // 4 checks in total
// test NO cache for a Bypassed cache function
memoizationCheckCount = 0;
memoizedCalls = 0;
totalFunctionCalls = 0;
const result21 = await service.fetchDataWithByPassedCacheFunction(2);
expect(result21).toBe('Data for ID: 2');
expect(memoizedCalls).toBe(0); // ID 2 result is now memoized
expect(totalFunctionCalls).toBe(1); // extra new call
expect(memoizationCheckCount).toBe(1); // 5 checks in total
bypassCache = false;
const result22 = await service.fetchDataWithByPassedCacheFunction(2);
expect(result22).toBe('Data for ID: 2');
expect(memoizedCalls).toBe(1); // ID 2 result is now memoized
expect(totalFunctionCalls).toBe(1); // NO extra new call
expect(memoizationCheckCount).toBe(2); // 2 checks in total
bypassCache = true;
const result23 = await service.fetchDataWithByPassedCacheFunction(2);
expect(result23).toBe('Data for ID: 2');
expect(memoizedCalls).toBe(1); // ID 2 result is NOT RETRIEVED FROM CACHE AS THEY ARE BYPASSED
expect(totalFunctionCalls).toBe(2); // extra new call as bypassCache = true
expect(memoizationCheckCount).toBe(3); // 5 checks in total
// test NO cache for a throwing async method
memoizationCheckCount = 0;
memoizedCalls = 0;
totalFunctionCalls = 0;
await Promise.all([
expect(service.throwData('akram')).rejects.toThrow('hello akram but I throw!'),
expect(service.throwData('akram')).rejects.toThrow('hello akram but I throw!'),
expect(service.throwData('akram')).rejects.toThrow('hello akram but I throw!')
]);
expect(memoizationCheckCount).toEqual(totalFunctionCalls + memoizedCalls);
expect(memoizedCalls).toEqual(0); // No cache
expect(totalFunctionCalls).toBe(3); // we call everytime we get a throw
});
});
;