Sending a socket to a forked process in Node.JS

If you want to fork a process in Node and pass a socket, the current Node documentation has a rather odd example, so I’ve simplified it here for my own sanity (further complicated by the fact that the WebStorm debugger can’t debug a forked Node.JS process, which confused me for too long). Hopefully someone else finds this useful at some point.

Step 1, in a file called app.js:

var child = require('child_process').fork('socket_handler.js');

// Open up the server and send sockets to child
var server = require('net').createServer();

server.on('connection', function (socket) {
    child.send('socket', socket);
    server.getConnections(function(err, count) {
        console.log("Connections: " + count);
    });
});
server.listen(1337);

And then, in a file called socket_handler.js which is located in the same directory as app.js:
process.on('message', function(message, socket) {
    socket.on('data', function(data) {
        // really poor echo ... :)
        socket.write(data);
    });
});

In this case, the fork happens upon application startup by calling the fork method of the child_process module. It starts by executing the code in socket_handler.js. As this is a new instance of the V8 engine used by Node.JS, remember there’s a sizable overhead to a forked process.

After creating the server and listening on port 1337, when a connection is made (which can be tested by a terminal emulator or telnet), the socket is passed to the forked process. In fact, it’s not really the object as much as it’s the handle to the new socket.

The send method takes two parameters, a string message which can be any identifier you want, and the the handle, or socket in this case.

The forked process receives the message via the message event on the process. If you’re sending more than one message, you can add conditional logic to handle the type of message in the event handler. As part of the call to fork, you can also pass command line arguments and read them using process.argv.

Mongoose plugin runs for every new Schema

If you want to consistently apply changes to every Schema in Mongoose, it’s simple. Below is an example.

var mongoose = require('mongoose');

var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}");
mongoose.plugin(function(schema, opts) { 
    schema.statics.isObjectId = function(id) { 
        if(id) { 
            return checkForHexRegExp.test(id); 
        } 
        return false; 
    }; 
}); 
var AnimalSchema = mongoose.Schema({ name: String }); 
var Animal = mongoose.model("Animal", AnimalSchema); if(Animal.isObjectId("521b4891039857e07aae695a")) { 
    var animal = new Animal(); // something more interesting here ... 
}

The code above uses the plugin function on the global mongoose object to add a new plugin. When you add a plugin using that technique, it runs for every schema that is constructed.

So, in this case, I’ve added a static function to every Schema called isObjectId which uses a simple regular expression (liberally borrowed straight from the bson ObjectId source code) to test whether a string looks like a valid ObjectId (in fact, a 24 character HEX string).

Now, as new models are created (mongoose.model), the Schema is first passed to any defined plugins. The plugin adds the new function isObjectId. As you can see, the new Model has a static method called isObjectId.

The plugin will not affect any Schemas/Models that were defined before the plugin was added.

Using this technique, you could add standardized fields, indexes, etc. without repeating the same code to all Schemas. Of course, you can also use the plugin method defined on a Schema to selectively add functionality.

var isObjectIdPlugin = function(schema, opts) {
    schema.statics.isObjectId = function(id) {
        if(id) {
            return checkForHexRegExp.test(id);
        }
        return false;
    };
};


var AnimalSchema = mongoose.Schema({
    name: String
});

AnimalSchema.plugin(isObjectIdPlugin);

var Animal = mongoose.model("Animal", AnimalSchema);

if(Animal.isObjectId("521b4891039857e07aae695a")) {
    var animal = new Animal();
    // something more interesting here ...
}

Above, the code applies the plugin to only the AnimalSchema using the plugin method.

Of course, adding the same method statically may not be very useful – instead it probably belongs somewhere in a utility class (and really it’s too bad it’s not just exposed directly by the BSON ObjectId class).

Using Sqlite and C# to determine if a specified table exists

I had need of a bit of code in C# to determine whether several tables in a Sqlite database had been created, so …

public static class DbExtensions
{
    /// <summary>
    /// Determines whether the table exists
    /// </summary>
    /// <param name="connection">Existing, opened, database connection</param>
    /// <param name="tableName">The name of the table to test for.</param>
    /// <returns>True if table exists.</returns>
    public static bool TableExists(this IDbConnection connection, string tableName)
    {
        Debug.Assert(connection != null);
        Debug.Assert(!string.IsNullOrWhiteSpace(tableName));

        var cmd = connection.CreateCommand();
        cmd.CommandText = @"SELECT COUNT(*) FROM sqlite_master WHERE name=@TableName";
        var p1 = cmd.CreateParameter();
        p1.DbType = DbType.String;
        p1.ParameterName = "TableName";
        p1.Value = tableName;
        cmd.Parameters.Add(p1);

        var result = cmd.ExecuteScalar();
        return ((long)result) == 1;
    }
}

Nothing too complex … only determining that the list of tables is stored in a system table named sqlite_master. If you want to find all indexes that have dependencies on a specific table, you can instead use the column tbl_name.

If you’re using Dapper and the DapperExtensions, you might find this useful:

_connection = new System.Data.SQLite.SQLiteConnection();
DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect();
_connection.ConnectionString = new DbConnectionStringBuilder()
{
    {"Data Source", "thumbnailer.db"},
    {"Version", "3"},
    {"FailIfMissing", "False"},
}.ConnectionString;

First, it creates the SQLite connection (nuget) and then configures the DapperExtensions to use the SqliteDialect. What that means is that the extensions will generate SQL that actually works! :) Finally, in my case, I wanted the DB to be created if it didn’t exist, so I set FailIfMissing to False.

PRTG Network Monitor, Part 2

Since my last post on the PRTG monitor, I’ve added some more probes (thanks to their offer of a free upgrade to 30 sensors).

However, before I got started, the monitor showed that the system health had an alert:

image

I clicked on the red alert box, and the detail page is displayed:

image

The server that hosts the PRTG Network monitor is intentionally underpowered as to consume as little electricity as possible (it’s a HP ProLiant Micro Tower Server as seen here on Amazon. It’s 64 bit, had has 4 non-hot swappable drive bays. It runs 64 Bit Windows 8 very nicely.) Because it’s underpowered, it often can be utilized heavily by the various routine processes that are always running on it. I logged in to the server (remote desktop), and the new Task Manager app made it clear what was happening:

image

I’d started a “maintenance” cycle earlier which apparently included a disk defrag.

Back to the sensors – I‘ve got quite a few network connected devices in the house (see details here). So, there are a number of things that can be monitored, etc. One thing in particular is (ironically?), a network monitor , from Synaccess Networks (the NP-02, which can detect the status of our internet connection and automatically toggle the power to the DSL modem if no internet connection is detected).

So, initially, the list of Devices automatically found included the NP-02. I wanted to add a probe, so, next to the name of the device, you can click Add Sensor.

image

Note that originally, it was just listed by IP Address, but the name is editable:

image

I clicked Add Sensor:

image

There are many things that can be monitored. Each click of a filter at the top reduces the options at the bottom.

image

I selected Ping:

image

You can then edit more sensor appropriate settings (and override defaults):

image

Then to the summary screen for the device:

image

Not much to show right away of course.

Awesomely, it automatically discovered a network connected printer, and selected several probes (I deleted all but one):

image

It’s a very cool system that works well for my home needs. While I can’t speak to the viability of this in a commercial setting, it’s certainly capable and well worth looking at for home or business.

PRTG Network Monitor for Windows

mysql monitoringMy current router/firewall/VPN device has an unfortunately mediocre live monitor for bandwidth statistics, but supports SMNP. So after a reasonably painful search for decent free options (oh boy are there some awful ones!), I installed the freeware version of the Paessler PRTG monitor so that I could easily see the network statistics for our internet connection and a few other neat things that it can track out of the box. I installed it on a shared, always-on Windows 8 Pro PC that does a ton of other things for our house like security camera monitoring, file shares, etc. It installed easily and was up and running quickly. While the paid version is far outside of my budget for this type of thing (budget=$0), the freeware version had just the right features for me.

It’s got tons of things it can monitor, but with the freeware limit of 10 devices, I’ve got it monitoring traffic, disk and a few other things:

image

I’ve got the default page set to just show the internet bandwidth (in/out):

image

The software automatically scanned my network and found way more things to monitor originally than I had expected.

It’s a reasonably sophisticated Ajax web application that works well on modern browsers. My only complaint about the experience is that it requires me to login frequently, yet has a button that makes it basically not be important (a button that if the login is the default, just automatically logs me in). I’d really like it to instead jump straight to the dashboard to show the statistics (maybe in a read-only mode).

image

(And right now, if you blog about the software, they’ll upgrade your license to 30 keys, so I’m doing that right now).