npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

seppuku

v0.1.6

Published

Allow your worker processes to die honourably

Downloads

20

Readme

Seppuku: Allow your Node.js workers to die honourably

Seppuku (named after the highly ritual suicide ceremony of Japanese samurai) is a simple module that streamlines the process of gracefully shutting down worker processes in a Node.js cluster that serves web pages through restify or express.

It can be triggered manually, in response to an abnormal condition (e.g.: an unhandled exception), or automatically after a configurable number of requests to keep memory creep at bay.

By default, it stops the server from accepting connections, instructs the parent process to respawn, and gives existing connections a period of time to shut down, after which it automatically terminates the worker process.

To help prevent accidental hosing of your servers, these shutdown periods can be randomized so that two workers started at roughly the same time are less likely to enter seppuku at the same time.

Installation

npm install seppuku

Usage


var restify = require('restify');
var seppuku = require('seppuku');

var server = restify.createServer();

server.use(seppuku(server, options));

// Go about your business. You're done!

Options

Seppuku's functionality can be altered by passing a number of options, listed below together with their respective defaults:

{
    minDeferralTime: 5000,      // Minimum time to wait between seppuku and kaishaku
    maxDeferralTime: 10000,     // Maximum time to wait between seppuku and kaishaku

    maxRequests: 0,             // Number of requests after which seppuku starts automatically (0 = never)

    trapExceptions: true,       // Whether exceptions should start seppuku

    filter: null,               // A filter function that determines the relative weight of a request
    
    kaishakunin: null,          // An optional function that replaces the default termination handler
    
    exitCode: 1                 // The code to pass to process.exit()
};

Randomizing the termination time

When a seppuku operation starts, the default kaishakunin (“beheader”) method shuts down the server and instructs the worker to disconnect from the parent process (which should then automatically spawn a new worker). Before terminating the worker process, kaishakunin() waits a variable amount of time to allow existing requests to be terminated gracefully, after which, if any requests are still open, it calls process.exit(1).

The termination time is randomized in order to minimize the impact that multiple workers started on or around the same time could have if they entered a seppuku at the same time. You can provide a set of minDeferralTime and maxDeferralTime options to determine the randomization boundaries.

Restarting automatically after a certain number of requests

Seppuku has the ability to restart automatically after a certain number of requests have been processed by the server. This can be helpful if you have a creeping memory leak that you cannot attend to right away. You can set the maxRequest option to any arbitrary number, or to zero if you want to turn off this functionality altogether.

By default, seppuku increments the request counter by one every time a request is processed, regardless of its type. If you wish, you can specify a filter function that receives the current request alongside the current request count and can pass a different weight value depending on the type of request. For example, if you don't want HEAD and OPTIONS requests to be counted towards the request count, you could write this filter:


var options = {
    maxRequests: 10000,
    filter: function(req, requestCount) {
        switch(req.method.toLowerCase()) {
            case 'head':
            case 'options':
            
            return 0;
        }
        
        return 1;
    }
}

seppuku(server, options);

Writing a custom termination handler

The default termination handler performs the following:

  1. Determine and set a timer for the termination time.
  2. Emit the seppuku event on the server instance
  3. Close the server
  4. Disconnect the worker (this step is safely skipped if the process is not running in a cluster)
  5. Terminate the process if the timer expires

Note that the timer itself is not retained; if all outstanding events (including existing requests) are resolved before the termination time, the process will terminate before the timer has expired.:

If the default termination handler doesn't do everything you need, you have a couple of options. The first is to trap the seppuku event on the server object, which is emitted as soon as the seppuku process begins. It receives two parameters, the first the amount of time until the process will be terminated, and the second a cancellation callback (more about this later).

Here's an example:

server.on('seppuku', function(count, cancel, err) {
    // Terminate outstanding long-running connections
    terminateAllConnections(); // ...
    // `err` contains the exception that caused seppuku to start, if any
});

If you desire a completely custom termination process, you can pass your own kaishakunin method as an option—at which point you're completely on your own. For example:

var options = {
    kaishakunin: function(err) {
        // Terminate immediately
        process.exit(255);
        // `err` contains the exception that caused seppuku to start, if any
    }
}

Initiating a seppuku operation manually

Simply call server.seppuku(), and all will be handled for you.

Cancelling a seppuku operation

You can terminate a seppuku operation by trapping the seppuku event emitted by your server instance and calling the callback that the handler receives as its second parameter. This causes seppuku to be completely reset as if you were restarting the server.

server.on('seppuku', function(count, cancel, err) {
    if (someCondition) {
        cancel();
    }
});

Contributing

Contributions are welcome, particularly if accompanied by a unit test.

License

Copyright © 2013 Marco Tabini & Associates, Inc.

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.