How to watch symlink'ed files in node.js using watchFile()

Problem

I am trying to monitor a file that is (soft) symlink'ed with node.js' watchFile() with the following code:

var fs=require('fs')
    , file= './somesymlink'
    , config= {persist:true, interval:1}; 

fs.watchFile(file, config, function(curr, prev) { 
    if((curr.mtime+'')!=(prev.mtime+'')) { 
        console.log( file+' changed'); 
    } 
});

In the above code, ./somesymlink is a (soft) symlink to /path/to/the/actual/file. When changes are made to the /path/to/the/actual/file, no event is fired. I have to replace the symlink with /path/to/the/actual/file to make it work. It seems to me that watchFile is not able to watch symlink'ed files. Of course I could make this work by using spawn+tail method but I prefer not to use that path as it would introduce more overhead.

So my question is how can I watch symlink'ed files in node.js using watchFile(). Thanks folks in advance.

Problem courtesy of: ricochen

Solution

You could use fs.readlink:

fs.readlink(file, function(err, realFile) {
    if(!err) {
        fs.watch(realFile, ... );
    }
});

Of course, you could get fancier and write a little wrapper that can watch either the file or it's link, so you don't have to think about it.

UPDATE: Here's such a wrapper, for the future:

/** Helper for watchFile, also handling symlinks */
function watchFile(path, callback) {
    // Check if it's a link
    fs.lstat(path, function(err, stats) {
        if(err) {
            // Handle errors
            return callback(err);
        } else if(stats.isSymbolicLink()) {
            // Read symlink
            fs.readlink(path, function(err, realPath) {
                // Handle errors
                if(err) return callback(err);
                // Watch the real file
                fs.watch(realPath, callback);
            });
        } else {
            // It's not a symlink, just watch it
            fs.watch(path, callback);
        }
    });
}
Solution courtesy of: Linus Gustav Larsson Thiel

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.