Files
  • index.js
  • debouncer.js
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/* Reference debouncer implementation as descibed by article "Avoiding cache stampede at DoorDash" https://blog.doordash.com/avoiding-cache-stampede-at-doordash-55bbf596d94b

This code simulates and logs stats of potential reads debounced. Try playing around with varion parameters in object below.
*/

const Debouncer = require('./debouncer');
const debouncer = new Debouncer();

function delay(ms) {
	return new Promise(resolve => setTimeout(resolve, ms));
}

async function fetchMenu(id, config) {
    // Simulate fetch load
	await delay(config.read_latency + Math.random() * config.jitter); 
	return [
        // Imagine some results
    ];
}

async function handleRequest(id, db_config) {
	return await debouncer.debounce(`fetch-${id}`, (id) => fetchMenu(id, db_config));
}

function print_stats(stats) {
	console.log('-------');
	console.log('Debouncer stats');
    console.log(stats);
	console.log(
		`Debounced: ${Math.round((stats.debounced / stats.invoked) * 100)}%`
	);
	console.log('-------');
}

async function startSimulation(configuration) {
	for (let e = 0; e < configuration.iterations; e++) {
		console.log('Generating random requests...');
		const unique_requests_ids = new Set();

		for (let j = 0; j < configuration.requestsPerIteration; j++) {
			const id = Math.floor(
        Math.random() * configuration.uniqueRequests
      );
			unique_requests_ids.add(id);
			handleRequest(id, configuration.db_simulation);
		}

    const waitFor = configuration.iterationDelay + 
                    Math.random() * configuration.iterationDelayJitter;

    console.log('Generated', unique_requests_ids.size, 'unique IDs over ', configuration.requestsPerIteration, 'parallel requests. Wait for', waitFor, 'ms');

    await delay(waitFor);
    print_stats(debouncer.stats);
	}
}


startSimulation({
    // Imagine each iteration like a tick in milli-seconds
    iterations: 2 * 1000,

    // Simulate given amount of requests per iteration
    requestsPerIteration: 20,

    // Total unique reads going to database from above total requests
    uniqueRequests: 8,

    // Each iteration generates some unique read requests
    // This delay is to simulate random time windows within requests delays and from debouncer with we can introduce the randomness of requests coming in on different times
    iterationDelay: 1,
    iterationDelayJitter: 5,

    // Simulate a slow database read speed
    db_simulation: {
        read_latency: 10,
        jitter: 20
    }
});
node v10.15.2 linux/amd64