Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

I'm building a 3D game in the browser using THREE.js. Lots of fun, but I came across the following situation:

An object in my 3D scene is continuously moving around, driven by user input. I need to save the object's position to my database in real-time.

Let's start at the front-end. Angular.js is watching my object's position using its built-in $watch functionality. The object's position can change multiple times per second.

On each change, I emit an event to the backend Node.js server using Socket IO, like so:

socket.emit('update', { 
    id: id,
    position: position
});

In the back-end, the event is caught and immediatly emitted to other members in the same Socket IO Room. This way, everyone in this room will have the most real-time update possible.

Now, because the event can happen multiple times per second, I don't want to update my MongoDB collection on each change, since this would cause a lot of overhead. Instead, I'm looking for a way of incidentally saving data to the database.

I've came up with a solution by using Node.js setInterval function, which saves data every 1000ms. For each distinct id (which is unique per object) received on the backend, a new key is created on an JavaScript object, thus keeping track of changes on a per-object basis.

The (simplified) code on the backend:

let update_queue = new Object();

// ...

// Update Event
socket.on('update', (msg) => {

    // Flag Changes
    if (!update_queue[msg.id]) update_queue[msg.id] = { changes: true };

    // Set Interval Timer
    if (!update_queue[msg.id].timer) {

        update_queue[msg.id].timer = setInterval(() => {

            if (!update_queue[msg.id].changes) {
                clearInterval(update_queue[msg.id].timer);
                return;
            }

            // This saves data to MongoDB
            Object3DCollection.update(msg.id, msg.position)
                .then((res) => {
                    console.log('saved');
                });

            // Unflag Changes
            update_queue[msg.id].changes = false;

        }, 1000);
    }

    // Immediate Broadcast to Socket Room
    socket.broadcast.to('some_room').emit('object_updated', msg);
});

The Question

Is this a proper way of handling very frequent socket data and still saving it to a database? Or are there any other suggestions/solutions that are more robuust or work better.

Note

I do not want to wait for my object to be saved to the database and then emit the saved data to the rest of the socket room. The delay of database write operations is not suitable for the real-time game situation I'm dealing with.

Thanks in advance! All suggestions/solutions are appreciated and will be considered.

share|improve this question
1  
sounds reasonable to me. you can lose buffered transactions if your server crashes, but that aside it's fine. – dandavis Aug 3 at 20:22
    
great, good to hear. I will invest some time in handling an optional crash to be as safe as possible. thanks for the response. – Nicky Aug 3 at 20:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.