I want to collect the most recent 10 items from my datastore. I believe I am supposed to do this using .child() and .limitToLast(), which emits an event every time a result has been added to the child.
I don't necessarily know if there are 10 items in total, so a simple counter won't work.
How do I know when Firebase is finished giving me results?
Example lookup code:
var plots = [];
firebaseDatastore.child("plots").orderByChild("unicode-timestamp").limitToLast(10).on("child_added", function(snapshot) {
// Add the new item to the list
plots.push(snapshot.val());
});
I need to know when the final plot has been added, regardless of whether it has hit the limit.
A Firebase query never really ends. It continues to monitor (in your case) the plots by unicode-timestamp and keep a "window" of the last 10 plots.
So:
child_added:timestamp1
child_added:timestamp2
...
child_added:timestamp9
child_added:timestamp10
And then when you add another plot:
child_removed:timestamp1
child_added:timestamp11
If you are not looking to use this behavior, you have two options:
use a value event and then snapshot.forEach over the child nodes
keep a counter and off your listener when you've reached the number of children you expect
Related
I'm currently using a platform to store orders that changes through time. I'm using Prometheus to also scrape when an order is created or when it changes its status. Find an example of the object below.
order = {id: <id>, status : <ORDERED, LOADED, DELIVERED>, time: <time>}
In order to save the order into Prometheus, I'm doing the following.
prom_order.inc(order)
I'm currently using a counter. However, after some a while, the metrics API keeps tracks of very old records. Also, Prometheus will save orders with the same id and the different statues. So, if the order went from ORDERED to DELIVERED, it will appear 3 different times. I'm wondering if there is a better metric to use for this case. Probably a metric that only preserves the last state? Maybe a metric that goes to zero ? Is there a metric that can be reset when is no longer needed? Is it possible maybe to delete or decrease a metric based on one of the labelNames?
I think it will better to remove the label "status" (ORDERED, LOADED, DELIVERED) and use the value of the metric to indicate the status:
0 = ORDERED
1 = LOADED
2 = DELIVERED
BTW: Do you have a label called "time"? You could use the "timestamp" for this, couldn't you?
I am using tabulator package 4.3.0 to work on a webpage. The table generated by the package is going to be the control element of a few other plots. In order to achieve this, I have been adding a dataFiltered function when defining the table variable. But instead of getting the order of the rows in my data object, I want to figure a way to get the index of the rows in the filtered table.
Currently, I searched the manual a little bit and have written the code analogue to this:
dataFiltered: function(filters,rows){
console.log(rows[0]._row.data)
console.log(rows[0].getPosition(true));
}
But the getPosition always returned -1, which refers to that the row is not found in the filtered table. I also generated a demo to show the real situ when running the function. with this link: https://jsfiddle.net/Binny92/3kbn8zet/53/.
I would really appreciate it if someone could help me explain a little bit of how could I get the real index of the row in the filtered data so that I could update the plot accordingly and why I am always getting -1 when running the code written in this way.
In addition, I wonder whether there is a way to retrieve the data also when the user is sorting the table. It's a pity that code using the following strategy is not working in the way I am expecting since it is not reacting to the sort action and will not show the information when loading the page for the first time.
$('#trialTable').on('change',function(x){console.log("Yes")})
Thank you for your help in advance.
The reason this is happening is because the dataFiltered callback is triggered after the rows are filtered but before they have been laid out on the table, so they wont necessarily be ready by the time you call the getPosition function on them.
You might do better to use the renderComplete callback, which will also handle the scenario when the table is sorted, which would change the row positions.
You could then use the getRows function passing in the value "active" as the first augment return only rows that have passed the filter:
renderComplete: function(){
var rows = table.getRows("active");
console.log(rows[0].getPosition(true));
}
On a side note i notice you are trying to access the _row property to access the row data. By convention underscore properties are considered private in JavaScript and should not be accessed as it can result in unstable system behaviour.
Tabulator has an extensive set of functions on the Row Component to allow you to access anything you need. In the case of accessing a rows data, there is the getData function
var data = row.getData();
I'm trying to find a better way to ensure certain documents are removed from a mongo collection at a specific time, which is unique to each document. I also need to run some methods when the items are removed. I've looked into TTL indexes, but it seems they don't allow any kind of callback, and from what I read the process that removes the documents only runs once per minute, which isn't specific enough for what I need. The following is what I came up with:
var check_frequency = 30000;
Meteor.setInterval((function() {
// figure out what elements will expire within the next check period
var next_check = moment().add(check_frequency, 'milliseconds');
var next_string = next_check._d.toISOString();
var ending_items = items.find({'time_to_end': {$lt : next_string}});
ending_items.forEach(function(db_object) {
var time_from_now = moment(db_object.time_to_end) - moment();
Meteor.setTimeout(function() {
removeAndReport(db_object._id);
}, time_from_now);
});
}), check_frequency);
My concern is I'm not sure how Meteor.setTimeout() works with threading, so if I have hundreds or thousands of these calls I'm wondering if it will cause problems. Can anyone recommend a better way to accomplish this?
Thanks in advance.
edit: Running background jobs with Meteor or cron isn't my only concern. I realize I could accomplish the same thing with a cron job, but I'd rather not query my databases once per second to only find 3 expiring items vs. querying the database once every 30 seconds, and figure out which elements will expire in the next time period.
It seems like an easier solution is to store the removal date in each document, rather than the TTL. Imagine you had a collection called Messages, and each document had a removeAt field. Then you can do something like the following:
var timeout = 500;
Meteor.setInterval((function() {
// remove any messages that should have been removed in the past
Messages.remove({removeAt: {$lte: new Date}});
}), timeout);
Notes:
Make sure to index removeAt so the remove doesn't need to scan your whole collection.
Technically this won't breack if it runs on multiple server instances, but ideally it would only run on one. Maybe it could be run in it's own process.
Working with React.js is really enjoyable.
I built a simple comment app based on the official tutorial.
You can add, edit, and delete comments. They are pulled via GET every 10 seconds.
At one point, the tutorial mentions optimistic updates: updating the UI before the server has responded in the case of a create, update or delete operation.
Since comments are part of a list, React suggests to assign a unique key to each comment.
I therefore use the database id of each comment as a key. That works fine for update and delete operations.
However, in the case of a create operation, I do not know the database id of a comment until it has been actually created server-side, and therefore I don't know what value to assign to the key.
At that point in time, the comment is added to the comment list but has no key/ID and therefore cannot be edited or deleted, until the list gets updated during the next API poll.
Can I work around that?
If you need the key to remain the same across updates, one option is to assign a temporary id to to an unused property. Then, use a function to retrieve the correct key for your list item models. As long as you account for the tempId property when updating the item, you can keep the key the same as long as the list remains in memory.
While you may not always care if the optimistic item gets removed and re-added, it can simplify your CSS when using on-enter or on-leave animations in your list. This also helps when you have stateful list item components.
Example:
let tempIds = 1; // 1 and up are truthy
// where ever you add the new item to your list
const newList = [...list, {...newItem, tempId: tempIds++}];
// get the right id
function getKey(instance) {
if (instance.tempId) {
return instance.tempId;
} else {
return instance.id;
}
}
// in your list render function
<List>
{list.map(model => (
<Item
key={getKey(model)}
//other props go here
/>
))}
</List
You need keys that are unique, consistent, and available. Your database IDs can't provide the third requirement, but you can--using local "client IDs". Obviously, you're responsible for guaranteeing their uniqueness and consistency.
You can add, edit, and delete comments. They are pulled via GET every 10 seconds.
We always POST to a resource which in returns yields the JSON response containing data we need, in your case ID. The delay is up to ~100ms which is fine.
If you set a temporary ID which is not equal to the one database is going to provide then React will re-render again once it receives the new data, just you will see two identical items as key is not the same.
I want to have an array in Redis (using Node) where I can add values to it and specify how long I want it to stay in there. After that time limit, they should be deleted, and ideally be able to call something so I know what just left. ex. I may get a request with 120s, so I want to add that value to a map for that long and then have it deleted.
Is there a better way to do this? I thought of using the EXPIRE but that seems to be just for keys, not elements in an array?
Any thoughts would be great.
This is what I am doing:
app.get('/session/:length', function(req, res) {
var length = parseInt(req.param('length'), 10);
addToArray(length, ip)
var ip = req.connection.remoteAddress;
res.json({ip: ip, length: length});
});
Basically, I when I add it to the array I want it to only keep it in the array for the time that is passed in. So if you say 30 seconds, it's in that array for 30s, and then is gone, and calls a callback. Maybe there is a better way to solve this problem?
What I do now is keep the times added and ip, time in an array and periodically loop through the array checking and deleting, but thought maybe it would be possible in redis to automatically do this.
While there isn't an automatic way to do that in Redis, the common approach to these kind of problems is to use a Redis sorted set. In your case, set the IP as the member's value and the expiry time (now + time to live) as the score using epoch representation.
Instead of looping periodically, you can just call ZREMRANGEBYSCORE every once in a while.
Since set members are unique, however, that means that you'll only be able to save each IP once. If that's OK, just update the score for an IP with every hit from it, otherwise make the member value unique by concatenating the IP with the timestamp.
Lastly, to get the IPs that haven't "expired", use ZRANGEBYSCORE to get members that have scores (expiry times) higher than now. Similarly and before deleting with ZREMRANGEBYSCORE, get the keys that expired for the callback logic that you mentioned.