55

I have the following UseCase:

A creates a Chat and invites B and C - On the Server A creates a File. A, B and C writes messages into this file. A, B and C read this file.

I want a to create a file on server and observe this file if anybody else writes something into this file send the new content back with websockets.

So, any change of this file should be observed by my node.js application.

How can I observe files-changes? Is this possible with node js without locking the files?

If not possible with files, would it be possible with database object (NoSQL)

Sam
  • 2,707
  • 1
  • 23
  • 32

3 Answers3

77

Good news is that you can observe filechanges with Node's API.

This however doesn't give you access to the contents that has been written into the file. You can maybe use the fs.appendFile(); function so that when something is being written into the file you emit an event to something else that "logs" your new data that is being written.

fs.watch(): Directly pasted from the docs

fs.watch('somedir', function (event, filename) {
    console.log('event is: ' + event);
    if (filename) {
        console.log('filename provided: ' + filename);
    } else {
        console.log('filename not provided');
    }
});

Read here about the fs.watch(); function

EDIT: You can use the function

fs.watchFile(); 

Read here about the fs.watchFile(); function

This will allow you to watch a file for changes. Ie. whenever it is accessed by some other processes of any kind.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Henrik Andersson
  • 45,354
  • 16
  • 98
  • 92
  • Thanks for the input. In my opinion it means, that you can watch changes on the filename with fs.watch. But on this page, i found fs.readStream and fs.writeStream. Maybe its possible with this. – Sam Dec 04 '12 at 08:57
  • 1
    I guess it depends on how you want to observe the file, doesn't it? If your goal is to observe the actual changes, ie. what was written then its fs.watchFile(); that you should use. This is whenever a file is accessed. I'll update my answer. – Henrik Andersson Dec 04 '12 at 08:59
  • I agree, i will test it, the file mustn't be locked. It it works i give you my √ – Sam Dec 04 '12 at 09:19
  • 9
    I would recommend against using fs.watchFile() as it has issues on different OSes etc. Try https://github.com/paulmillr/chokidar instead. – mtsr Dec 04 '12 at 14:59
  • Yes, that is true but I had no idea this api did exist! I havent used it myself and if OP is open to use 3rd party libs then great! :) I myself will upgrade my stuff at home to this lib now that I know about it. – Henrik Andersson Dec 04 '12 at 15:02
7

Also you could use node-watch. Here's an easy example:

const watch = require('node-watch')

watch('README.md', function(event, filename) {
  console.log(filename, ' changed.')
})
feupeu
  • 819
  • 7
  • 25
1

I do not think you need to have observe file changes or use a NoSQL database for this (if you do not want to). My advice would be to look at events(Observer pattern). There are more than enough tutorials on this topic available online (Google). For example Felix's article about Using EventEmitters

This publish/subcribe semantic can also be achieved with NoSQL. In Redis for example, I think you should have a look at pubsub.

In MongoDB I think tailable cursors is what you are looking for. On their blog they have a post explaining pub/sub.

mouckatron
  • 1,289
  • 2
  • 13
  • 23
Alfred
  • 60,935
  • 33
  • 147
  • 186
  • Hi Alfred, pubsub and table cursors sounds like what i need, if i can't use node.js. thanks. – Sam Dec 04 '12 at 10:19
  • 1
    Hi Sam, actually EventEmitter is part of NodeJS and is really the recommended way to do pubsub like behaviour (much simpler than with a a file). Unless you use the file for persistence anyway, but even then, look at EventEmitter, as it's very very simple to set up. – mtsr Dec 04 '12 at 15:01
  • exactly like mtsr said. EventEmitter is part of NodeJS. – Alfred Dec 04 '12 at 16:19
  • In my usecase, i need to have file or a database, because i need to listen to the events from different servers. i have more than one server who wants to listen on the same instance. – Sam Dec 04 '12 at 19:27
  • 1
    Multi-server I would consider either Redis pubsub, which is fast and easy, but will lose events if one of your servers fail or go all out and use a Message Queue like http://rabbitmq.com with https://github.com/postwait/node-amqp. This gives you guaranteerd at-least-once delivery and allows durable messaging (where messages are saved across restarts). RabbitMQ + AMQP is also very easy to setup. – mtsr Dec 04 '12 at 20:45