Meteor.js server method queue - meteor

I have a method in Meteor that takes a bit of time to execute, and this method is called a lot of times with different params.
But the client can change the params while the data is still being loaded, so I want the server to be able to clear the method queue in some way. Is that possible
So just for the example:
Server:
Meteor.methods({
'getLongTimeExecutedData': function (settings, reset) {
let self = this;
if(reset) {
// How to reset my entire queue here.
}
Meteor._sleepForMs(1000);
let myData = { settings: settings, timestamp: new Date() };
return myData;
}
});
Client:
Meteor.call('getLongTimeExecutedData', { param1: 'test' , param2: 1 }, false);
Meteor.call('getLongTimeExecutedData', { param1: 'test' , param2: 2 }, false);
Meteor.call('getLongTimeExecutedData', { param1: 'test' , param2: 3 }, false);
...
// Reset queue on server with true here
Meteor.call('getLongTimeExecutedData', { param1: 'test2' , param2: 1 }, true);
Meteor.call('getLongTimeExecutedData', { param1: 'test2' , param2: 2 }, false);
Meteor.call('getLongTimeExecutedData', { param1: 'test2' , param2: 3 }, false);
...
I don't want to use this.unblock(), because the method is using a MS SQL connection, and if it still executes, it takes up a lot of unwanted request to the server.
Hope somebody have some ideas? :)
// Peter

there are several job queue projects available for this
https://github.com/artwells/meteor-queue
https://github.com/vsivsi/meteor-job-collection

Related

ExtJS 6.01 How to update tpl after store loaded

Let's say I have a component with tpl in HTML format, which has a variable named testname, default value is null.
A listener of beforerender calls to a function in viewController, and in this function, I need to load a store and a callback function to update the variable testname in the view, based on the store record returned.
The problem I met is the order of code execution. The function in the viewController always ended first before the store.load callback get executed. Therefore the front view will never get updated. I have tried to setup the asynchronousLoad to false but it doesn't help.
Here is the code in the viewController.
onViewRendering: function(theView) {
console.log('setp 1');
var theStore = Ext.create('App.store.Test');
theStore.load({
asynchronousLoad: false,
callback: function(record) {
console.log('setp 2');
if (record) {
theView.data.testname = 'updated';
}
}
});
console.log('setp 3');
}
Console log displays in step 1, 3, 2.
And here is the code in the View:
Ext.define('App.view.TestView', {
extend: 'Ext.component',
data:{
testname:null
},
tpl:'<p>{testname}</p>',
listeners: {
beforerender: 'onViewRendering'
}
})
Here is the store code:
Ext.define('App.store.Test', {
extend: 'Ext.data.Store',
alias: 'store.test',
autoLoad: true,
remoteFilter: true,
fields: ['id', 'name'],
proxy: {
type: 'direct',
directFn: 'test.getTest'
}
})
I am new to Extjs and really need some help here, thanks in advance!
To update tpl after store load, you have to call setData method like below:
Code snippet:
onViewRendering: function(theView) {
console.log('setp 1');
var theStore = Ext.create('App.store.Test');
theStore.load({
asynchronousLoad: false,
callback: function(record) {
console.log('setp 2');
if (record) {
theView.setData({testname: 'updated'}); //setData method
}
}
});
console.log('setp 3');
}

How to access server aggregate on the client side within meteor

Bit of a noob question. I'm using meteor-native-mongo on the server to access the aggregate function in MongoDB, however, I'm not sure how I return and access the results on the client side. In the past subscribing and then accessing the collections on the client was pretty straightforward using the collection.find({}) function, however, I don't understand how to do it with the aggregate function. Can someone please explain.
Meteor.publish('companies', function(limit) {
db.collection('companies').aggregate([{ $group: { _id: { location: "$google_maps.geometry_location" }, companies: { $addToSet: { name: "$company_name" } }, count: { $sum: 1} } }, { $match: { count: { $gt: 1 } } }]).toArray((err, result) => {
console.log(result);
return result;
});
});
Use this.added, this.changed, this.removed from https://docs.meteor.com/api/pubsub.html#Subscription-added ...
Meteor.publish('companies', function(limit) {
var subscription = this;
db.collection('companies').aggregate([{ $group: { _id: { location: "$google_maps.geometry_location" }, companies: { $addToSet: { name: "$company_name" } }, count: { $sum: 1} } }, { $match: { count: { $gt: 1 } } }]).toArray((err, result) => {
subscription.added('companies-aggregate', 'geometry-grouping', {result: result});
});
});
// On the client:
var CompaniesAggregate = new Mongo.Collection('companies-aggregate');
// Inside a reactive context, like a helper
var result = CompaniesAggregate.findOne('geometry-grouping').result;
Naturally, to make it reactive, you'd have to know when the results of the aggregations would change. There is no automatic way to do that--you would have to resolve that logically, with your own code.
The best way to do that is to save the subscription variable in an array somewhere in a higher scope, and called changed on all the subscriptions for 'companies' for the geometry-grouping document, computing an updated result.
The commenter's solution won't be realtime; in other words, if one user makes a change to the e.g. company name or location, another user won't see those changes.

Getting the the last items in a Meteor Collection

I've got a Threads collection and I'd like to get the last post in each thread and publish those.
Anyone know the right query to do this?
I tried to do something like this, but it did not work. since the return value isn't a cursor.
var messages = Messages.find({ threadId: { $in: threadIds }});
// We found the messages. Now retrieve the last ones per thread.
return _.map(threadIds, function(threadId) {
console.log('Get %s', threadId);
Messages.find({ threadId: threadId }, {
limit: 1, sort: { createdAt: -1 }
});
});
I believe this solution is working for me.
I do have one gripe, which is that I'm not sure if the method will run if a new message is added to a thread.
var messages = Messages.find({ threadId: { $in: threadIds }});
// We found the messages. Now retrieve the last ones per thread.
var messageCursors = [];
_.each(threadIds, function(threadId) {
var lastMessage = Messages.find({ threadId: threadId }, {
sort: { createdAt: -1 }, limit: 1
});
messageCursors.push(lastMessage);
});
return messageCursors;

How to use encryption in ydn-db database library?

I am trying to implement setSecret to encrypt the values in indexeddb but get the error:
"unable to call method setSecret of undefined"
Code Below:
$(window).load(function () {
//Database Schema
var db_schema = {
stores: [
{
name: "Employees",
}
]
}
var secret = "Test";
db.setSecret(secret);
db = new ydn.db.Storage('Database', db_schema);
});
Following the link, but not sure where I'm going wrong any ideas:
Anyone encrpyted there indexddb values before?
Thanks
Sorry for documentation behind. I have updated the documentation. Now you have to put encryption key in database options.
var schema = {
version: 1,
stores: [{
name: 'encrypt-store',
encrypted: true
}]
};
var options = {
Encryption: {
expiration: 1000*15, // optional data expiration in ms.
secrets: [{
name: 'aaaa',
key: 'aYHF6vfuGHpfWSeRLrPQxZjS5c6HjCscqDqRtZaspJWSMGaW'
}]
}
};
var db = new ydn.db.Storage('encrypted-db-name', schema, options);
You have to use "-crypt" module to get that feature. It supports transparent data encryption using sha256 crypto, per record salting and key rotation. You still need server to generate encryption key and send to the client securely. There is also a demo app.
//Database Creation
//Database Schema
var db_schema = {
stores: [{
name: "DataTable",
encrypted: true
}
]
};
var options = {
Encryption: {
//expiration: 1000 * 15, // optional data expiration in ms.
secrets: [{
name: 'aaaa',
key: 'aYHF6vfuGHpfWS*eRLrPQxZjSó~É5c6HjCscqDqRtZasp¡JWSMGaW'
}]
}
};
//Create the database with the relevant tables using the schema above
db = new ydn.db.Storage('Database', db_schema,options);
$.ajax({
type: "POST",
url: "/home/DownloadData",
data: { File: file },
success: function (result) {
var Key = result.Data.Key;
var DownloadedData= {
Data: result.Data,
Data1: result.Data1,
Data2: result.Data2,
Data3: result.Data3
};
db.put('DataTable', DownloadedData, Key);
return false;
},
error: function (error) {
alert("fail");
}
});

Grid content JSON conversion

I have a grid where user and add new rows as many as they want. After adding all the rows, they click the "Save" button. On Save button click, I want to send all the data entered by the user in JSON format to the server side code (i.e. a servlet in my case)
Below is the model and store definition:
Ext.define('Plant', {
extend: 'Ext.data.Model',
fields: [
// the 'name' below matches the tag name to read, except 'availDate'
// which is mapped to the tag 'availability'
{name: 'common', type: 'string'},
{name: 'botanical', type: 'string'},
{name: 'light'},
{name: 'price', type: 'float'},
// dates can be automatically converted by specifying dateFormat
{name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y'},
{name: 'indoor', type: 'bool'}
]
});
// create the Data Store
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Plant'
});
On click of the save button, I am able to get the store like this:
{
text: 'Save',
handler : function(){
//Getting the store
var records = grid.getStore();
console.log(records.getCount());
Ext.Ajax.request({
url: '/CellEditing/CellEditingGridServlet',
method: 'POST',
jsonData: {
//How to assign the store here such that
//it is send in a JSON format to the server?
},
callback: function (options, success, response) {
}
});
}
But I don't know like how to convert the store content into JSON and send it in the jsonData of the ajax request.
I want the JSON data something like this in the server side:
{"plantDetails":
[
{
"common": Plant1,
"light": 'shady',
"price": 25.00,
"availDate": '05/05/2013',
"indoor": 'Yes'
},
{
"common": Plant2,
"light": 'most shady',
"price": 15.00,
"availDate": '12/09/2012',
"indoor": 'No'
},
]
}
Please let me know how to achieve this.
Regards,
Agreed with Neil, the right way to do this is through an editable store outfited with a proxy and a writer. See example here: http://docs.sencha.com/ext-js/4-1/#!/example/grid/cell-editing.html
Store
writer :
{
type : 'json',
allowSingle : true
}
Experiment with allowSingle as per your use case
In your controller
//if you want to set extra params
yourStore.getProxy().setExtraParam("anyParam",anyValue);
// sync the store
yourStore.sync({success : function() {
yourGrid.setLoading(false);
.. },
scope : this // within the scope of the controller
});
You should be creating the model with a new id ( you can ignore it at the server side and use your own key generation , but it lets extjs4 for its internal purposes know that a new record has been created).
creating a model instance
var r = Ext.create('yourModel', { id: idGen++, propA : valA , ... });
insert to grid
store.insert(0,r);
var editPlugin = grid.getPlugin(editPluginId);
editPlugin.startEdit(0,1);
Once you receive a response back the id's can be update to their true value.
in the Store
reader :
{
type : 'json',
root : 'yourdata',
successProperty : 'success',
idProperty : 'id'
}
If you were to use the same grid for handling and editing then you could use the write event or the appropriate event
for more advanced handling in the Store
listeners :
{
write : function(store,operation, eOpts)
{
var insertedData = Ext.decode(operation.response.responseText);
.. do something
}
}
I would recommend using the mvc architecture of Extjs4
This is what I tried and it seems to work:
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Plant',
proxy: {
type: 'ajax',
url: '/CellEditing/CellEditingGridServlet',
writer: {
type: 'json',
root: 'plantDetails'
}
}
handler : function(){
grid.getStore().sync();
But I am getting an additional parameter in the JSON at the server side:
"id": null
I don't have this id set in my model then where is this coming from? Is there some way to set some values to it rather than having a default null value?

Resources