1.0.2 • Published 4 years ago

go-singleflight v1.0.2

Weekly downloads
-
License
ISC
Repository
-
Last release
4 years ago

Go-Singleflight

Highly inspired by Golang singleflight class.

The Singleflight class would hold all function calls at the same time, execute only execute source function once then copy result to others.

Singleflight has these feature 1. call async / sync function as usual 2. Throw out error 3. Full test coverage

Sample Code

import SingleFlight from 'go-singleflight';

const key = "id-for-source-function"
const singleFlight = new SingleFlight()

const sourceFn = async function VeryExpensiveOperation(){
	...
}
// specify key and source function to protect
const protectFn = singleFlight.do(key, sourceFn)

// call as usual
const promiseList = []
promiseList.push(protectFn(args1, args2, ...))
promiseList.push(protectFn(args1, args2, ...))
promiseList.push(protectFn(args1, args2, ...))
promiseList.push(protectFn(args1, args2, ...))

await Promise.all(promiseList)

Source function would only run once.

Using in express server

It would be useful to prevent multiple db query when cache invalidate, known as cache penetration.

See the full example in ./example/express-server

// initial once and pass down by middleware
const singleFlight = new SingleFlight();
app.use((req, res, next) => {
	req.singleFlight = singleFlight
	next();
});

app.get('/test-singleflight', async (req, res) => {
	const key = 'test';
	let value = await readFromCache(key);
	if (!value) {
		try {
			const protectFn = req.singleFlight.do(key, readFromDb);
			value = await protectFn(key);
		}catch (e) {
			console.error(e)
		}
		await setCache(key, value);
	}
	
	return res.json({
		value
	});
});

Forget

Sometimes you would like to forget before the first one function finished, due to some timeout mechanism.
You could call forget to let source function execute.

The protect function run before forget would get the previous result

import SingleFlight from 'go-singleflight';

const key = "id-for-source-function"
const singleFlight = new SingleFlight()

const sourceFn = async function VeryExpensiveOperation(){
	...
}
// specify key and source function to protect
const protectFn = singleFlight.do(key, sourceFn)

// call as usual
await protectFn(args1, args2, ...)
1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago

0.1.0

4 years ago