summaryrefslogtreecommitdiff
path: root/node_modules/stoppable
diff options
context:
space:
mode:
authorakiyamn2023-09-24 23:22:21 +1000
committerakiyamn2023-09-24 23:22:21 +1000
commit4e87195739f2a5d9a05451b48773c8afdc680765 (patch)
tree9cba501844a4a11dcbdffc4050ed8189561c55ed /node_modules/stoppable
downloadprice-tracker-worker-4e87195739f2a5d9a05451b48773c8afdc680765.tar.gz
price-tracker-worker-4e87195739f2a5d9a05451b48773c8afdc680765.zip
Initial commit (by create-cloudflare CLI)
Diffstat (limited to 'node_modules/stoppable')
-rw-r--r--node_modules/stoppable/LICENSE21
-rw-r--r--node_modules/stoppable/lib/stoppable.js65
-rw-r--r--node_modules/stoppable/package.json49
-rw-r--r--node_modules/stoppable/readme.md127
4 files changed, 262 insertions, 0 deletions
diff --git a/node_modules/stoppable/LICENSE b/node_modules/stoppable/LICENSE
new file mode 100644
index 0000000..171534d
--- /dev/null
+++ b/node_modules/stoppable/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Hunter Loftis <hunter@hunterloftis.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/stoppable/lib/stoppable.js b/node_modules/stoppable/lib/stoppable.js
new file mode 100644
index 0000000..68d526c
--- /dev/null
+++ b/node_modules/stoppable/lib/stoppable.js
@@ -0,0 +1,65 @@
+'use strict'
+
+const https = require('https')
+
+module.exports = (server, grace) => {
+ grace = typeof grace === 'undefined' ? Infinity : grace
+ const reqsPerSocket = new Map()
+ let stopped = false
+ let gracefully = true
+
+ if (server instanceof https.Server) {
+ server.on('secureConnection', onConnection)
+ } else {
+ server.on('connection', onConnection)
+ }
+
+ server.on('request', onRequest)
+ server.stop = stop
+ server._pendingSockets = reqsPerSocket
+ return server
+
+ function onConnection (socket) {
+ reqsPerSocket.set(socket, 0)
+ socket.once('close', () => reqsPerSocket.delete(socket))
+ }
+
+ function onRequest (req, res) {
+ reqsPerSocket.set(req.socket, reqsPerSocket.get(req.socket) + 1)
+ res.once('finish', () => {
+ const pending = reqsPerSocket.get(req.socket) - 1
+ reqsPerSocket.set(req.socket, pending)
+ if (stopped && pending === 0) {
+ req.socket.end()
+ }
+ })
+ }
+
+ function stop (callback) {
+ // allow request handlers to update state before we act on that state
+ setImmediate(() => {
+ stopped = true
+ if (grace < Infinity) {
+ setTimeout(destroyAll, grace).unref()
+ }
+ server.close(e => {
+ if (callback) {
+ callback(e, gracefully)
+ }
+ })
+ reqsPerSocket.forEach(endIfIdle)
+ })
+ }
+
+ function endIfIdle (requests, socket) {
+ if (requests === 0) socket.end()
+ }
+
+ function destroyAll () {
+ gracefully = false
+ reqsPerSocket.forEach((reqs, socket) => socket.end())
+ setImmediate(() => {
+ reqsPerSocket.forEach((reqs, socket) => socket.destroy())
+ })
+ }
+}
diff --git a/node_modules/stoppable/package.json b/node_modules/stoppable/package.json
new file mode 100644
index 0000000..701b6b7
--- /dev/null
+++ b/node_modules/stoppable/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "stoppable",
+ "version": "1.1.0",
+ "engines": {
+ "node": ">=4",
+ "npm": ">=6"
+ },
+ "keywords": [
+ "server",
+ "net",
+ "connect",
+ "socket",
+ "connection",
+ "stop",
+ "close",
+ "disconnect",
+ "disconnection",
+ "http",
+ "https",
+ "tcp"
+ ],
+ "files": [
+ "lib"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/hunterloftis/stoppable.git"
+ },
+ "homepage": "https://github.com/hunterloftis/stoppable",
+ "scripts": {
+ "lint": "standard --fix \"lib/**/*.js\" \"test/**/*.js\"",
+ "spec": "nyc --check-coverage mocha --bail \"test/*.test.js\"",
+ "test": "npm run lint && npm audit && npm run spec",
+ "coverage": "nyc mocha --bail \"test/*.test.js\"",
+ "perf:baseline": "node test/performance.js & sleep 2 && artillery quick -d 10 -r 1000 -o /dev/null -k http://localhost:8000",
+ "perf:stoppable": "node test/performance.js 1 & sleep 2 && artillery quick -d 10 -r 1000 -o /dev/null -k http://localhost:8000"
+ },
+ "main": "lib/stoppable.js",
+ "license": "MIT",
+ "devDependencies": {
+ "artillery": "^1.6.0-15",
+ "awaiting": "^3.0.0",
+ "chai": "^4.1.2",
+ "mocha": "^5.0.5",
+ "nyc": "^11.6.0",
+ "requisition": "^1.7.0",
+ "standard": "^11.0.1"
+ }
+}
diff --git a/node_modules/stoppable/readme.md b/node_modules/stoppable/readme.md
new file mode 100644
index 0000000..d6f1d62
--- /dev/null
+++ b/node_modules/stoppable/readme.md
@@ -0,0 +1,127 @@
+# Stoppable
+
+[![Build Status](https://travis-ci.org/hunterloftis/stoppable.svg?branch=master)](https://travis-ci.org/hunterloftis/stoppable)
+
+> Node's `server.close()` the way you probably [expected it to work by default](https://github.com/nodejs/node/issues/2642).
+
+## Summary
+
+```js
+const server = stoppable(http.createServer(handler))
+server.stop()
+```
+
+Stoppable stops accepting new connections and closes existing, idle connections (including keep-alives)
+without killing requests that are in-flight.
+
+## Requirements
+
+- Node.js v6+
+
+Node.js v4.x is *unofficially* supported.
+
+## Installation
+
+```bash
+yarn add stoppable
+```
+
+(or use npm)
+
+## Usage
+
+**constructor**
+
+```js
+stoppable(server, grace)
+```
+
+Decorates the server instance with a `stop` method.
+Returns the server instance, so can be chained, or can be run as a standalone statement.
+
+- server: Any HTTP or HTTPS Server instance
+- grace: Milliseconds to wait before force-closing connections
+
+`grace` defaults to Infinity (don't force-close).
+If you want to immediately kill all sockets you can use a grace of 0.
+
+**stop()**
+
+```js
+server.stop(callback)
+```
+
+Closes the server.
+
+- callback: passed along to the existing `server.close` function to auto-register a 'close' event.
+The first agrument is an error, and the second argument is a boolean that indicates whether it stopped gracefully.
+
+## Design decisions
+
+- Monkey patching generally sucks, but in this case it's the nicest API. Let's call it "decorating."
+- `grace` could be specified on `stop`, but it's better to match the existing `server.close` API.
+- Clients should be handled respectfully, so we aren't just destroying sockets, we're sending `FIN` packets first.
+- Any solution to this problem requires bookkeeping on every connection and request/response.
+We're doing a minimum of work on these "hot" code paths and delaying as much as possible to the actual `stop` method.
+
+## Performance
+
+There's no way to provide this functionality without bookkeeping on connection, disconnection, request, and response.
+However, Stoppable strives to do minimal work in hot code paths and to use optimal data structures.
+
+I'd be interested to see real-world performance benchmarks;
+the simple loopback artillery benchmark included in the lib shows very little overhead from using a stoppable server:
+
+### Without Stoppable
+
+```plain
+ Scenarios launched: 10000
+ Scenarios completed: 10000
+ Requests completed: 10000
+ RPS sent: 939.85
+ Request latency:
+ min: 0.5
+ max: 51.3
+ median: 2.1
+ p95: 3.7
+ p99: 15.3
+ Scenario duration:
+ min: 1
+ max: 60.7
+ median: 3.6
+ p95: 7.6
+ p99: 19
+ Scenario counts:
+ 0: 10000 (100%)
+ Codes:
+ 200: 10000
+```
+
+### With Stoppable
+
+```plain
+ Scenarios launched: 10000
+ Scenarios completed: 10000
+ Requests completed: 10000
+ RPS sent: 940.73
+ Request latency:
+ min: 0.5
+ max: 43.4
+ median: 2.1
+ p95: 3.8
+ p99: 15.5
+ Scenario duration:
+ min: 1.1
+ max: 57
+ median: 3.7
+ p95: 8
+ p99: 19.4
+ Scenario counts:
+ 0: 10000 (100%)
+ Codes:
+ 200: 10000
+```
+
+## License
+
+MIT \ No newline at end of file