{"id":11995,"library":"semaphore","title":"Concurrency Semaphore for Node.js","description":"This package provides a basic counting semaphore mechanism for Node.js environments, designed to limit the number of concurrent operations accessing a shared resource. The current and only stable version, 1.1.0, was published 9 years ago and explicitly targets Node.js 0.8.0. Due to its age and lack of maintenance, it does not follow a regular release cadence and is effectively abandoned for modern Node.js development. Its primary differentiator is its extreme simplicity and minimal footprint, offering fundamental concurrency control without features found in more contemporary, promise-based semaphore implementations (e.g., `async-sema`, `await-semaphore`). While functional for very old projects, it lacks modern JavaScript features and type definitions out of the box.","status":"abandoned","version":"1.1.0","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/abrkn/semaphore.js","tags":["javascript"],"install":[{"cmd":"npm install semaphore","lang":"bash","label":"npm"},{"cmd":"yarn add semaphore","lang":"bash","label":"yarn"},{"cmd":"pnpm add semaphore","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This package is CommonJS-only and does not support ES Modules. The `require()` call returns the factory function directly, which then needs to be invoked with a capacity.","wrong":"import semaphore from 'semaphore';","symbol":"semaphore","correct":"const semaphore = require('semaphore');"},{"note":"The `require('semaphore')` call returns a function that must be immediately invoked with the desired capacity to create a semaphore instance. It is not a class constructor.","wrong":"const sem = new semaphore(capacity);","symbol":"sem","correct":"const sem = require('semaphore')(capacity);"},{"note":"The `take` method uses a callback-based API, typical of Node.js 0.8.0 era, and does not return a Promise. Modern semaphore implementations often offer promise-based APIs for `async/await`.","wrong":"sem.take().then(() => { /* ... */ });","symbol":"sem.take","correct":"sem.take(function() { /* ... */ });"}],"quickstart":{"code":"const semaphore = require('semaphore');\nconst http = require('http');\n\n// Limit concurrent database access to 1 operation at a time\nconst dbSemaphore = semaphore(1);\n\nconst expensive_database_operation = (callback) => {\n  console.log('Starting expensive DB operation...');\n  setTimeout(() => {\n    const error = Math.random() > 0.8 ? new Error('Database error!') : null;\n    console.log('Finished expensive DB operation.');\n    callback(error, 'Data from DB');\n  }, 1000);\n};\n\nconst server = http.createServer((req, res) => {\n  res.writeHead(200, { 'Content-Type': 'text/plain' });\n  dbSemaphore.take(function() {\n    console.log('Semaphore taken, requesting DB operation...');\n    expensive_database_operation(function(err, data) {\n      dbSemaphore.leave();\n      if (err) {\n        console.error('Request failed:', err.message);\n        return res.end(`Error: ${err.message}`);\n      }\n      res.end(`Success: ${data}`);\n    });\n  });\n});\n\nconst PORT = process.env.PORT ?? 3000;\nserver.listen(PORT, () => {\n  console.log(`Server listening on http://localhost:${PORT}`);\n  console.log('Try opening multiple tabs to http://localhost:3000 to see concurrency limits in action.');\n});\n","lang":"javascript","description":"This quickstart demonstrates how to create a semaphore to limit simultaneous database access within a Node.js HTTP server. It shows taking and leaving the semaphore using its callback-based API."},"warnings":[{"fix":"For ESM projects, consider using modern promise-based semaphore libraries like `async-sema` or `await-semaphore` that natively support `import` syntax and `async/await`. If you must use this package, configure your bundler (e.g., Webpack, Rollup) to handle CommonJS modules or use dynamic import `import('semaphore')`.","message":"The package is CommonJS-only and relies on `require()` syntax. It will not work natively in ES Module (ESM) environments without a CJS wrapper or bundler configuration. Modern Node.js projects increasingly use ESM by default.","severity":"breaking","affected_versions":"All versions (1.1.0)"},{"fix":"For new projects or existing projects using modern Node.js, it is strongly recommended to use a more actively maintained and feature-rich semaphore implementation. Search npm for 'semaphore' to find current alternatives.","message":"The package is extremely old, last published 9 years ago, targeting Node.js >=0.8.0. It lacks active maintenance, which means potential bugs, security vulnerabilities, or performance issues are unlikely to be addressed.","severity":"gotcha","affected_versions":"All versions (1.1.0)"},{"fix":"Install `@types/semaphore` if using TypeScript (`npm install --save-dev @types/semaphore`). Be aware that types might be outdated or incomplete. Alternatively, migrate to a modern semaphore library that ships with native TypeScript support.","message":"This package does not provide TypeScript type definitions natively. While `@types/semaphore` exists, it's also not actively maintained and may not fully align with modern TypeScript practices.","severity":"gotcha","affected_versions":"All versions (1.1.0)"},{"fix":"Always ensure `sem.leave()` is called, even if errors occur within the `sem.take()` callback. Wrap the critical section in a `try...finally` block if possible, or ensure all error paths explicitly call `sem.leave()`.","message":"The `sem.take()` method is callback-based. If the callback function throws an error, the semaphore's `leave()` method might not be called, leading to a deadlock where the semaphore never releases its hold and subsequent operations are permanently blocked.","severity":"gotcha","affected_versions":"All versions (1.1.0)"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"If using ES Modules, consider migrating to a modern, promise-based semaphore library that supports `import` statements. If you must use this package, you might need to use dynamic `import('semaphore')` or configure a bundler to transform CommonJS. Ensure your file is a CommonJS module (e.g., `.js` without `\"type\": \"module\"` or explicitly `.cjs`).","cause":"Attempting to import the CommonJS-only `semaphore` package in an ES Module context (e.g., a `.mjs` file or a project with `\"type\": \"module\"` in `package.json`).","error":"ReferenceError: require is not defined"},{"fix":"You must invoke the result of `require('semaphore')` with a `capacity` argument to create a semaphore instance. Correct usage: `const sem = require('semaphore')(capacity);`.","cause":"You are trying to use the result of `require('semaphore')` directly as an object or calling methods on it, but it's actually a factory function that needs to be invoked first.","error":"TypeError: semaphore is not a function"}],"ecosystem":"npm"}