Yvan Dredi
Yvan Dredi

Reputation: 21

Meteor Keeping track of server side var on the client side

first question here but i really don't know where to go. I cannot find anything that help me on google.

i'm doing huge processing server side and i would like to keep track of the state and show it on the client side. For that purpose i have a variable that i'm updating as the process go through. To keep track of it i'm using that client side:

Template.importJson.onCreated(function () {
    Session.set('import_datas', null);
    this.autorun(function(){
        Meteor.call('readImportState', function(err, response) {
            console.log(response);
            if (response !== undefined) {
                Session.set('importingMessage',response);
            }
        });
    })
});

I'm reading it from template that way (in template.mytemplate.helpers):

readImportState: function() {
        return Session.get('importingMessage');
    },

And here is the server side code to be called by meteor.call:

readImportState: function() {
        console.log(IMPORT_STATE);
        return IMPORT_STATE;
    }

The client grab the value at start but it is never updated later.... What am i missing here? If somebody could point me in the right direction that would be awesome. Thank you :)

Upvotes: 2

Views: 99

Answers (1)

David Weldon
David Weldon

Reputation: 64312

TL;DR

As of this writing, the only easy way to share reactive state between the server and the client is to use the publish/subscribe mechanism. Other solutions will be like fighting an uphill battle.

In-memory State

Here's the (incorrect) solution you are looking for:

  1. When the job starts, write to some in-memory state on the server. This probably looks like a global or file scoped variable like jobStates, where jobStates is an object with user ids as its keys, and state strings as its values.
  2. The client should periodically poll the server for the current state. Note an autorun doesn't work for Meteor.call (there is no reactive state forcing the autorun to execute again) - you'd need to actually poll every N seconds via setInterval.
  3. When the job completes, modify jobStates.
  4. When the client sees a completed state, inform the user and cancel the setInterval.
  5. Because the server could restart for any number of reasons while the job is running (and consequently forget its in-memory state), we'll need to build in some fault tolerance for both the state and the job itself. Write the job state to the database whenever it changes. When the server starts, we'll read this state back into jobStates.
  6. The model above assumes only a single server is running. If there exist multiple server instances, each one will need to observe the collection in order to write to its own jobStates. Alternatively, the method from (2) should just read the database instead of actually keeping jobStates in memory.

This approach is complicated and error prone. Furthermore, it requires writing the state to the database anyway in order to handle restarts and multiple server instances.

Publish/Subscribe

  1. As the job state changes, write the current state to the database. This could be to a separate collection just for job states, or it could be a collection with all the metadata used to execute the job (helpful for fault tolerance), or it could be to the document the job is producing (if any).
  2. Publish the necessary document(s) to the client.
  3. Subscribe for the document(s) on the client and use a simple find or findOne in a template to display the state to the user.
  4. Optional: clean up the state document(s) periodically using with something like synced cron.

As you can see, the publish/subscribe mechanism is considerably easier to implement because most of the work is done for you by meteor.

Upvotes: 1

Related Questions