• Stars
    star
    602
  • Rank 71,431 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 7 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Semaphore using `async` and `await`

async-sema

This is a semaphore implementation for use with async and await. The implementation follows the traditional definition of a semaphore rather than the definition of an asynchronous semaphore seen in some js community examples. Where as the latter one generally allows every defined task to proceed immediately and synchronizes at the end, async-sema allows only a selected number of tasks to proceed at once while the rest will remain waiting.

Async-sema manages the semaphore count as a list of tokens instead of a single variable containing the number of available resources. This enables an interesting application of managing the actual resources with the semaphore object itself. To make it practical the constructor for Sema includes an option for providing an init function for the semaphore tokens. Use of a custom token initializer is demonstrated in examples/pooling.js.

Usage

Firstly, add the package to your project's dependencies:

npm install --save async-sema

or

yarn add async-sema

Then start using it like shown in the following example. Check more use case examples here.

Example

const { Sema } = require('async-sema');
const s = new Sema(
  4, // Allow 4 concurrent async calls
  {
    capacity: 100 // Prealloc space for 100 tokens
  }
);

async function fetchData(x) {
  await s.acquire()
  try {
    console.log(s.nrWaiting() + ' calls to fetch are waiting')
    // ... do some async stuff with x
  } finally {
    s.release();
  }
}

const data = await Promise.all(array.map(fetchData));

The package also offers a simple rate limiter utilizing the semaphore implementation.

const { RateLimit } = require('async-sema');

async function f() {
  const lim = RateLimit(5); // rps

  for (let i = 0; i < n; i++) {
    await lim();
    // ... do something async
  }
}

API

Sema

Constructor(nr, { initFn, pauseFn, resumeFn, capacity })

Creates a semaphore object. The first argument is mandatory and the second argument is optional.

  • nr The maximum number of callers allowed to acquire the semaphore concurrently.
  • initFn Function that is used to initialize the tokens used to manage the semaphore. The default is () => '1'.
  • pauseFn An optional fuction that is called to opportunistically request pausing the the incoming stream of data, instead of piling up waiting promises and possibly running out of memory. See examples/pausing.js.
  • resumeFn An optional function that is called when there is room again to accept new waiters on the semaphore. This function must be declared if a pauseFn is declared.
  • capacity Sets the size of the preallocated waiting list inside the semaphore. This is typically used by high performance where the developer can make a rough estimate of the number of concurrent users of a semaphore.

async drain()

Drains the semaphore and returns all the initialized tokens in an array. Draining is an ideal way to ensure there are no pending async tasks, for example before a process will terminate.

nrWaiting()

Returns the number of callers waiting on the semaphore, i.e. the number of pending promises.

tryAcquire()

Attempt to acquire a token from the semaphore, if one is available immediately. Otherwise, return undefined.

async acquire()

Acquire a token from the semaphore, thus decrement the number of available execution slots. If initFn is not used then the return value of the function can be discarded.

release(token)

Release the semaphore, thus increment the number of free execution slots. If initFn is used then the token returned by acquire() should be given as an argument when calling this function.

RateLimit(rps, { timeUnit, uniformDistribution })

Creates a rate limiter function that blocks with a promise whenever the rate limit is hit and resolves the promise once the call rate is within the limit set by rps. The second argument is optional.

The timeUnit is an optional argument setting the width of the rate limiting window in milliseconds. The default timeUnit is 1000 ms, therefore making the rps argument act as requests per second limit.

The uniformDistribution argument enforces a discrete uniform distribution over time, instead of the default that allows hitting the function rps time and then pausing for timeWindow milliseconds. Setting the uniformDistribution option is mainly useful in a situation where the flow of rate limit function calls is continuous and and occuring faster than timeUnit (e.g. reading a file) and not enabling it would cause the maximum number of calls to resolve immediately (thus exhaust the limit immediately) and therefore the next bunch calls would need to wait for timeWindow milliseconds. However if the flow is sparse then this option may make the code run slower with no advantages.

Contributing

  1. Fork this repository to your own GitHub account and then clone it to your local device
  2. Move into the directory of the clone: cd async-sema
  3. Link it to the global module directory of Node.js: npm link

Inside the project where you want to test your clone of the package, you can now either use npm link async-sema to link the clone to the local dependencies.

Author

Olli Vanhoja (@OVanhoja)

More Repositories

1

next.js

The React Framework
JavaScript
120,060
star
2

hyper

A terminal built on web technologies
TypeScript
42,467
star
3

swr

React Hooks for Data Fetching
TypeScript
29,396
star
4

turbo

Incremental bundler and build system optimized for JavaScriptΒ and TypeScript, written in Rust – including Turbopack and Turborepo.
Rust
24,396
star
5

pkg

Package your Node.js project into an executable
JavaScript
24,151
star
6

vercel

Develop. Preview. Ship.
TypeScript
11,950
star
7

micro

Asynchronous HTTP microservices
TypeScript
10,525
star
8

satori

Enlightened library to convert HTML and CSS to SVG
TypeScript
10,113
star
9

commerce

Next.js Commerce
TypeScript
9,996
star
10

serve

Static file serving and directory listing
TypeScript
9,088
star
11

ncc

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
JavaScript
8,786
star
12

ai

Build AI-powered applications with React, Svelte, Vue, and Solid
TypeScript
7,674
star
13

styled-jsx

Full CSS support for JSX without compromises
JavaScript
7,577
star
14

platforms

A full-stack Next.js app with multi-tenancy and custom domain support. Built with Next.js App Router and the Vercel Domains API.
TypeScript
5,016
star
15

nextjs-subscription-payments

Clone, deploy, and fully customize a SaaS subscription application with Next.js.
TypeScript
5,004
star
16

ms

Tiny millisecond conversion utility
TypeScript
4,912
star
17

ai-chatbot

A full-featured, hackable Next.js AI chatbot built by Vercel
TypeScript
4,873
star
18

og-image

Open Graph Image as a Service - generate cards for Twitter, Facebook, Slack, etc
TypeScript
4,031
star
19

release

Generate changelogs with a single command
JavaScript
3,544
star
20

examples

Enjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.
TypeScript
3,198
star
21

next-learn

Learn Next.js Starter Code
TypeScript
3,063
star
22

hazel

Lightweight update server for Electron apps
JavaScript
2,855
star
23

next-plugins

Official Next.js plugins
2,676
star
24

app-playground

https://app-dir.vercel.app/
TypeScript
2,226
star
25

virtual-event-starter-kit

Open source demo that Next.js developers can clone, deploy, and fully customize for events.
TypeScript
2,115
star
26

geist-font

1,846
star
27

async-retry

Retrying made simple, easy and async
JavaScript
1,780
star
28

arg

Simple argument parsing
JavaScript
1,191
star
29

nft

Node.js dependency tracing utility
JavaScript
1,182
star
30

react-tweet

Embed tweets in your React application.
TypeScript
1,134
star
31

style-guide

Vercel's engineering style guide
JavaScript
1,064
star
32

avatar

πŸ’Ž Beautiful avatars as a microservice
TypeScript
1,046
star
33

next-react-server-components

Demo repository for Next.js + React Server Components
JavaScript
957
star
34

nextjs-postgres-nextauth-tailwindcss-template

Admin dashboard template.
TypeScript
744
star
35

nextjs-postgres-auth-starter

Next.js + Tailwind + Typescript + Drizzle + NextAuth + PostgreSQL starter template.
TypeScript
743
star
36

edge-runtime

Developing, testing, and defining the runtime Web APIs for Edge infrastructure.
TypeScript
736
star
37

server-components-notes-demo

Experimental demo of React Server Components with Next.js. Deployed serverlessly on Vercel.
TypeScript
722
star
38

micro-dev

The development environment for `micro`
JavaScript
695
star
39

nextgram

A sample Next.js app showing dynamic routing with modals as a route.
TypeScript
681
star
40

react-keyframes

Create frame-based animations in React
TypeScript
615
star
41

nextjs-portfolio-starter

Easily create a portfolio with Next.js and Markdown.
JavaScript
613
star
42

hyperpower

Hyper particle effects extension
JavaScript
613
star
43

static-fun

A fun demo for wildcard domains
TypeScript
610
star
44

title

A service for capitalizing your title properly
JavaScript
576
star
45

fetch

Opinionated `fetch` (with retrying and DNS caching) optimized for use with Node.js
JavaScript
564
star
46

serve-handler

The foundation of `serve`
JavaScript
545
star
47

vrs

A serverless virtual reality e-commerce experience powered by Vercel
TypeScript
517
star
48

swr-site

The official website for SWR.
MDX
464
star
49

fun

Ζ’un - Local serverless function Ξ» development runtime
TypeScript
462
star
50

storage

Vercel Postgres, KV, Blob, and Edge Config
TypeScript
455
star
51

mongodb-starter

A developer directory built on Next.js and MongoDB Atlas, deployed on Vercel with the Vercel + MongoDB integration.
TypeScript
438
star
52

spr-landing

Serverless Pre-Rendering Landing Page
CSS
426
star
53

hyper-site

The official website for the Hyper terminal
JavaScript
419
star
54

pkg-fetch

A utility to fetch or build patched Node binaries used by `pkg` to generate executables. This repo hosts prebuilt binaries in Releases.
TypeScript
412
star
55

analytics

Privacy-friendly, real-time traffic insights
TypeScript
384
star
56

sveltekit-commerce

SvelteKit Commerce
Svelte
352
star
57

reactions

Next.js Incremental Static Regeneration Demo
JavaScript
310
star
58

email-prompt

CLI email prompt with autocompletion and built-in validation
JavaScript
275
star
59

uid-promise

Creates a cryptographically strong UID
TypeScript
250
star
60

fetch-retry

Wrapper around `fetch` with sensible retrying defaults
JavaScript
220
star
61

git-hooks

No nonsense Git hook management
JavaScript
198
star
62

zsh-theme

Yet another zsh theme
178
star
63

remote-cache

The Vercel Remote Cache SDK
TypeScript
169
star
64

cosmosdb-server

A Cosmos DB server implementation for testing your applications locally.
TypeScript
167
star
65

update-check

Minimalistic update notifications for command line interfaces
JavaScript
157
star
66

test-listen

Quick ephemeral URLs for your tests
JavaScript
153
star
67

install-node

Simple one-liner shell script that installs official Node.js binaries
Shell
136
star
68

terraform-provider-vercel

Terraform Vercel Provider
Go
129
star
69

title-site

A website for capitalizing your titles
JavaScript
124
star
70

preview-mode-demo

This demo showcases Next.js' next-gen Static Site Generation (SSG) support.
TypeScript
105
star
71

nextjs-discord-bot

Discord bot for the official Next.js Discord
TypeScript
99
star
72

beginner-sveltekit

The complete course to start your journey building Svelte applications.
JavaScript
97
star
73

err-sh

Microservice that forwards you to error messages
JavaScript
96
star
74

community

Welcome to the Vercel Community. Discuss feature requests, ask questions, and connect with others in the community.
96
star
75

webpack-asset-relocator-loader

Used in ncc while emitting and relocating any asset references
JavaScript
95
star
76

commerce-framework

TypeScript
94
star
77

hyperyellow

Example theme for hyperterm
JavaScript
87
star
78

schemas

All schemas used for validation that are shared between our projects
JavaScript
78
star
79

nuxt3-kitchen-sink

An example template showing all Nuxt 3 features on Vercel.
Vue
64
star
80

next-codemod

codemod transformations to help upgrade Next.js codebases
JavaScript
63
star
81

react-transition-progress

Show a progress bar while React Transitions run
TypeScript
57
star
82

otel

TypeScript
54
star
83

opentelemetry-collector-dev-setup

Shell
50
star
84

async-listen

Promisify server.listen for your HTTP/HTTPS/TCP server.
TypeScript
45
star
85

wait-for

Small utility that waits for a file to exist and optionally have some permissions set.
C
44
star
86

tracing-js

An implementation of Opentracing API for honeycomb.io
TypeScript
43
star
87

dns-cached-resolve

Caching DNS resolver
TypeScript
40
star
88

example-integration

TypeScript
38
star
89

fetch-cached-dns

A decorator on top of `fetch` that caches the DNS query
JavaScript
35
star
90

speed-insights

Vercel Speed Insights package
TypeScript
30
star
91

remark-capitalize

Transform all markdown titles with title.sh
JavaScript
29
star
92

resolve-node

API endpoint to resolve an arbitrary Node.js version with semver support
JavaScript
29
star
93

cra-to-next

An example of migrating Create React App to Next.js.
JavaScript
24
star
94

ng-deploy-vercel

Deploy Angular applications to Vercel
TypeScript
22
star
95

stripe-integration

A Vercel deploy integration to automatically set up your Stripe API keys and webhook secrets.
TypeScript
21
star
96

rcurl

`curl --resolve` helper script
Shell
21
star
97

release-auth

Handles the authentication for `release`
JavaScript
21
star
98

gatsby-plugin-vercel

Track Core Web Vitals in Gatsby projects with Vercel Analytics.
JavaScript
20
star
99

cert-demo

TypeScript
19
star
100

go-bridge

Bridge for `@vercel/go`
Go
18
star