{"id":17983488,"url":"https://github.com/techjacker/exit-strategy","last_synced_at":"2025-07-01T12:34:05.503Z","repository":{"id":8082148,"uuid":"9495500","full_name":"techjacker/exit-strategy","owner":"techjacker","description":"Gracefully kill your app using node's domains","archived":false,"fork":false,"pushed_at":"2013-10-07T19:38:14.000Z","size":180,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-10T17:56:10.399Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/techjacker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-04-17T10:57:58.000Z","updated_at":"2015-03-01T20:35:29.000Z","dependencies_parsed_at":"2022-09-07T09:30:52.487Z","dependency_job_id":null,"html_url":"https://github.com/techjacker/exit-strategy","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techjacker%2Fexit-strategy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techjacker%2Fexit-strategy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techjacker%2Fexit-strategy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techjacker%2Fexit-strategy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/techjacker","download_url":"https://codeload.github.com/techjacker/exit-strategy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247107828,"owners_count":20884797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-29T18:17:23.690Z","updated_at":"2025-04-04T02:12:55.477Z","avatar_url":"https://github.com/techjacker.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exit Strategy\n\n[![Build Status](https://secure.travis-ci.org/techjacker/exit-strategy.png)](http://travis-ci.org/techjacker/exit-strategy)\n\n- Generates error event handlers to gracefully kill your app\n- Optimised for use with node's domains\n- Uses [visionmedia's logger](https://github.com/visionmedia/log.js) to print POSIX error codes to STDOUT that will be picked up by [logwatch](http://linux.die.net/man/8/logwatch)\n\n\n## Full Example\n\n```JavaScript\nvar\tapp\t\t\t\t\t= require('express').express(),\n\tdomain\t\t\t\t= require('domain'),\n\tappDomain\t\t\t= domain.create(),\n\texitStrategy\t\t= require('exit-strategy'),\n\texitAppDomain\t\t= exitStrategy.app.exitAppDomain,\n\texitServerDomain\t= exitStrategy.server.exitServerDomain,\n\texitApp\t\t\t\t= exitAppDomain(app),\n\tserver, exitServer;\n\n// attach error handler\nappDomain.on('error', exitApp);\n\n// wrap app execution in domain to deal with uncaught exceptions\nappDomain.run(function () {\n\n\t// 1. create http server\n\tserver = server.listen(app.get('port'), function() {\n\t\t// you need to add this!\n\t\tapp.set('serverListening', true);\n\t});\n\n\t// 2. replace exitApp with exitServer error handler once inited server\n\texitServer = exitServerDomain(app, server);\n\tappDomain.on('error', exitServer).removeListener('error', exitApp);\n\n\t// 3. kill app for serious error evts you catch and broadcast with app.emit('seriousError')\n\tapp.on('seriousError', exitServer);\n\tprocess.on('SIGTERM', exitServer);\n\n\t// 4. send 502s to new connections if started server shutdown process\n\tapp.use(exitStrategy.middleware.closeGracefully(app));\n\n\t// define routes etc\n});\n```\n\n## Logwatch Setup\n- by default logwatch watches all files in /var/log and subdirs\n- make sure your app logs to a file in this dir\n- logwatch will email you alerts depending upon the --detail level you set it to\n\n\n\n## API\n\n### .app.exitServerDomain(app, httpServer) returns -\u003e fn (err)\n\n- app needs get/set methods (see [getter-setter module](https://github.com/techjacker/getter-setter) if you don't want to use express)\n- returns error handler function (fn (err))\n\n```JavaScript\nvar app       \t  = require('express').express(),\n\tappDomain\t  = domain.create(),\n\texitAppDomain = require('exit-strategy').app.exitAppDomain(app);\n\nvar server = server.listen(app.get('port'), function() {\n\t// you need to add this!\n\tapp.set('serverListening', true);\n});\nappDomain.on('error', exitServerDomain(app, server));\nappDomain.run(function () {\n\t// run your app - set up routes etc...\n});\n```\n\n##### what the server domain error handler does:\n1. checks if the server is active\n2. calls server.close()\n3. sets timer to kill app if server.close() takes more than 30s\n4. calls exitApp\n5. calls exitProcess\n\n\n### .app.exitAppDomain(app) returns -\u003e fn (err)\n\n- app needs get/set methods (see getter-setter module if you don't want to use express)\n- returns error handler function (fn (err))\n\n\t```JavaScript\n\tvar app       \t  = require('express').express(),\n\t\tappDomain\t  = domain.create(),\n\t\texitAppDomain = require('exit-strategy').app.exitAppDomain(app);\n\n\tappDomain.on('error', exitApp);\n\tappDomain.run(function () {\n\t\t// run your app\n\t});\n\t```\n\n##### what the app domain error handler does:\n1. if app.get('serverListening') then lets serverDomain handle it\n2. sets app flag\n```JavaScript\napp.set('killingApp', true);\n```\n3. calls exitProcess\n\n\n### .exitProcess(app, err)\n\n##### what it does:\n\n1. logs error to STDOUT\n2. exits process\n\n\n### .middleware.closeGracefully(app)\n\n- Middleware to prevent new connections once the exit routine has been initiated.\n- If you are load balancing then see [this guide](http://blog.argteam.com/coding/hardening-node-js-for-production-part-3-zero-downtime-deployments-with-nginx/) for configuring nginx to fail over to the next upstream server\n\n```JavaScript\nvar app = require('express').express(),\n\n// send 502s to new connections if started server shutdown process\napp.use(exitStrategy.middleware.closeGracefully(app));\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechjacker%2Fexit-strategy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechjacker%2Fexit-strategy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechjacker%2Fexit-strategy/lists"}