how to get data from an object Store from index number n to k.
For example if we have 100 records in an store (ProductStore), an I need to get from index 11 to 20 or 50 to 60. I need to use this in pagination. In mysql we can use LIMIT and OFFSET clouse,is there any equivalent to OFFSET in Indexeddb.
You can use cursor.advance to skip past some records. There is no limit with cursors, you simply stop iterating by counting how many times you iterated.
Something like this:
function query(db, criteria, offset, limit) {
return new Promise((resolve, reject) => {
const results = [];
const transaction = db.transaction('store');
transaction.oncomplete = event => resolve(results);
transaction.onerror = event => reject(event.target);
const store = transaction.objectStore('store');
const index = store.index('index');
const request = index.openCursor(criteria);
let advanced = offset === 0;
let counter = 0;
request.onsuccess = event => {
const cursor = event.target.result;
if (!cursor) {
return;
}
if (!advanced) {
advanced = true;
cursor.advance(offset);
}
counter++;
results.push(cursor.value);
if (counter >= limit) {
return;
}
cursor.continue();
};
});
}
Related
I have a scenario in K6 where I get 2 values at the same timestamp from datadog. The first value is an incorrect spike. The second one is the correct value which I need.
I use K6 Trend to collect the values from Datadog. It collects it as 2 different values due to which my max value comes incorrectly as one of those spikes. How to collect it such that when the timestamp is same the latest value gets extracted?
Current implementation:
index.js:
//thresholds and scenarios get loaded in K6
export const getPaymentIdRPS = new Trend("get_payment_id_rps");
export function setup() {
//setup data
}
//this is the scenario with the issue
export function collectGetPaymentIdMetrics(data){
metrics.getPaymentIdRPS= payments.queryGetPaymentIdRPS();
metrics.getPaymentIdRPS.points.forEach(val => {
getPaymentIdRPS.add(val[1], tags);
});
}
In different library, payments.js:
function queryGetPaymentIdRPS() {
const queries = setQueryEnv();
const response = datadog.metricsQuery(queries.getPaymentIdRPS, 10); //(query, duration of extraction)
return parseMetricQuery(response); //these functions defined towards end of this Q.
}
The above returns:
INFO[0032] rps val= [1666798390000,54.5] source=console
INFO[0037] rps val= [1666798390000,15.571428571428573] source=console
INFO[0042] rps val= [1666798400000,19] source=console
INFO[0047] rps val= [1666798400000,5.428571428571429]
Hence max = 54.5 but I want max as 15.57 by storing [1666798390000,15.571428571428573] and [1666798400000,5.428571428571429] only.
metricsQuery:
metricsQuery(query, seconds) {
//Delay the query start/end timestamps to allow datadog to process metrics;
const DATADOG_INGESTION_DELAY = 30;
let start = Math.ceil(Date.now() / 1000) - seconds;
let end = Math.ceil(Date.now() / 1000);
start = start - DATADOG_INGESTION_DELAY;
end = end - DATADOG_INGESTION_DELAY;
//null body in 2nd param
let res = this.queryClient.get(
`/query?from=${start}&to=${end}&query=${query}`,
null,
{ tags: { name: `Datadog /metric` } }
);
check(res, {
"DD metric query OK": (r) => r.status === 200,
}) || fail(JSON.stringify(res));
check(res, {
"DD metric query valid": (r) => r.json().status != "error",
}) || fail(JSON.stringify(res.json().error));
return res;
}
};
parseMetricQuery:
export function parseMetricQuery(response) {
const responseBody = response.json();
//Check invalid response
if (responseBody.series === undefined || response.status != 200) {
fail("Failed to get Datadog metric");
}
//Check 0 response, map will fail if array is empty
if (responseBody.series.length === 0) {
return {
sum: 0,
length: 0,
average: 0,
points: [],
url: response.request.url,
};
} else {
const length = responseBody.series[0].length;
var series = responseBody.series[0].pointlist;
var sum = 0;
sum = series
.map((val) => {
return val[1];
})
.reduce((previousValue, currentValue) => previousValue + currentValue, 0);
return {
sum: sum,
length: length,
average: sum / length,
points: series,
url: response.request.url,
};
}
}
Since each iteration of K6 is like a fresh start, we can't have any global map whose values remain intact to compare timestamps already recorded. Hence I can't compare whether timestamp is already recorded and hence replace value of that timestamp rather than append to Trend list.
I am trying to solve the problem where the script enters a website, takes the first 10 links from it and then goes on those 10 links and then goes on to the next 10 links found on each of these 10 previous pages. Until the number of visited pages will be 1000.
This is what it looks like:
I was trying to get this by using for loop inside promise and recursion, this is my code:
const rp = require('request-promise');
const url = 'http://somewebsite.com/';
const websites = []
const promises = []
const getOnSite = (url, count = 0) => {
console.log(count, websites.length)
promises.push(new Promise((resolve, reject) => {
rp(url)
.then(async function (html) {
let links = html.match(/https?:\/\/(www\.)?[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()#:%_\+.~#?&//=]*)/g)
if (links !== null) {
links = links.splice(0, 10)
}
websites.push({
url,
links,
emails: emails === null ? [] : emails
})
if (links !== null) {
for (let i = 0; i < links.length; i++) {
if (count < 3) {
resolve(getOnSite(links[i], count + 1))
} else {
resolve()
}
}
} else {
resolve()
}
}).catch(err => {
resolve()
})
}))
}
getOnSite(url)
I think you might want a recursive function that takes three arguments:
an array of urls to extract links from
an array of the accumulated links
a limit for when to stop crawling
You'd kick it off by calling it with just the root url, and await all of the returned promises:
const allLinks = await Promise.all(crawl([rootUrl]));
On the initial call the second and third arguments could assume default values:
async function crawl (urls, accumulated = [], limit = 1000) {
...
}
The function would fetch each url, extract its links, and recurse until it hit the limit. I haven't tested any of this, but I'm thinking something along these lines:
// limit the number of links per page to 10
const perPageLimit = 10;
async function crawl (urls, accumulated = [], limit = 1000) {
// if limit has been depleted or if we don't have any urls,
// return the accumulated result
if (limit === 0 || urls.length === 0) {
return accumulated;
}
// process this set of links
const links = await Promise.all(
urls
.splice(0, perPageLimit) // limit to 10
.map(url => fetchHtml(url) // fetch the url
.then(extractUrls)); // and extract its links
);
// then recurse
return crawl(
links, // newly extracted array of links from this call
[...accumulated, links], // pushed onto the accumulated list
limit - links.length // reduce the limit and recurse
);
}
async fetchHtml (url) {
//
}
const extractUrls = (html) => html.match( ... )
I was hoping to create a counter which would increment to the eventual number of followers. I have other code, but I just included the part that would affect the incrementation. Currently, when I run the program the HTML file only displays the final number of followers, and the word "Followers" showing it is able to get the proper number, but it isn't able to have an incrementation animation as I would like. How would I go about fixing this?
var text_field = document.getElementById('followers');
fetch(api)
.then((response) => {
return response.json();
})
.then((data) => {
var number = data['Count'][0][0];
const updateCount = () => {
const target = number;
const count = text_field.innerText;
const increment = target / speed;
if (count < target) {
text_field.innerText = count + increment;
setTimeout(updateCount, 5);
} else {
text_field.innerText = target + ' Followers';
}
};
updateCount();
});
The innerText property returns a string value. Use the parseInt function before any calculations.
var text_field = document.getElementById("followers");
function counter(){
var number = 100;
const updateCount = () => {
const target = number;
const count = parseInt(text_field.innerText); //parsing
const speed=number;
const increment = target / speed;
if (count < target) {
text_field.innerText = count + increment;
setTimeout(updateCount, 5);
} else {
text_field.innerText = target;
}
};
updateCount();
}
counter();
<div id="followers">1</div> Followers!!!
I am trying to generate fixed length nonce (length 9).
But my code is printing sometimes nonce of 8 length and sometime 9 length.
this is what I am trying to do but with different approach (I have modified it for fixed nonce length)
I am not able to understand why it is printing nonce of length 8 when i am passing length as 9 as argument??
It would be great if someone can tell why this is happening.
Below is complete Nodejs code
var last_nonce = null;
var nonce_incr = null;
// if you call new Date to fast it will generate
// the same ms, helper to make sure the nonce is
// truly unique (supports up to 999 calls per ms).
module.exports = {
getNonce: function(length) {
if (length === undefined || !length) {
length = 8;
}
var MOD = Math.pow(10, length);
var now = (+new Date());
if (now !== last_nonce) {
nonce_incr = -1;
}
nonce_incr++;
last_nonce = now;
var nonce_multiplier = ((nonce_incr < 10) ? 10 : ((nonce_incr < 100) ? 100 : 1000));
var s = (((now % MOD) * nonce_multiplier) + nonce_incr) % MOD;
return s;
}
}
//test code
if(require.main === module) {
console.time("run time");
//importing async module
var async = require('async');
var arr = [];
//generating 1000 length array to use it in making 1000 async calls
//to getNonce function
for(var i=0; i<1000; i++) arr.push(i);
//this will call getNonce function 1000 time parallely
async.eachLimit(arr, 1000, function(item, cb) {
console.log(module.exports.getNonce(9));
cb();
}, function(err) {console.timeEnd("run time");});
}
Sample output:
708201864 --> nonce length 9
708201865
708201866
70820190 --> nonce length 8 (why it is coming 8?? when passed length is 9)
70820191
70820192
70820193
70820194
70820195
70820196
70820197
70820198
70820199
708201910
708201911
708201912
708201913
708201914
708201915
708201916
708201917
708201918
In case someone needs it, here is a nonce generator free from convoluted logic, allowing you to control both character sample and nonce size:
const generateNonce = (options) => {
const {
length = 32,
sample = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
} = options || {};
const getRand = () => Math.floor(Math.random() * sample.length);
return Array.from({ length }, () => sample.charAt(getRand())).join('');
};
If you prefer Typescript:
const generateNonce = (options?: { sample?: string, length?: number }) => {
const {
length = 32,
sample = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
} = options || {};
const getRand = () => Math.floor(Math.random() * sample.length);
return Array.from({ length }, () => sample.charAt(getRand())).join('');
};
I am new to the async programming and currently stuck with this simple task. I have a Mysql table which has 20k records and need to process all the records. The current approach is looping in batch of records.
let limit = 100;
let offset = 0;
sequelize.query(`Select * from abc limit ${limit} offset ${offset}`, {type: sequelize.QueryTypes.SELECT}).then((records) => {
// process
return processResult;
});
Therefore, i need to increase the offset in the while loop.
while (/*....*/) {
let p = sequelize.query(`Select * from abc limit ${limit} offset ${offset}`, {type: sequelize.QueryTypes.SELECT}).then((records) => {
// process records
return processResult;
});
offset += limit;
}
My question is what is the condition in the while loop in order to stop it ? Since p is always a Promise, thus I cannot use it as the stop condition
You can use the .each() of bluebird Promise.
var Promise = require('bluebird');
let limit = 100;
let offset = 0;
let queryStrings = [];
let max = 20000;
while (offset < max) {
queryStrings.push(`Select * from abc limit ${limit} offset ${offset}`);
offset += limit;
}
let p = Promise.each(queryStrings, (queryString)=> {
return sequelize.query(queryString, {type: sequelize.QueryTypes.SELECT}).then((records) => {
// process records
if(/* need to break */){
return Promise.reject(new Error('...'));
}
return processResult;
});
});
update
If you don't know the maximum, you can do some recursion:
let _iterate = function (limit, offset) {
return sequelize.query(`Select * from abc limit ${limit} offset ${offset}`, {type: sequelize.QueryTypes.SELECT}).then((records) => {
// process records
if (/* need to break */) {
return Promise.reject(new Error(''));
}
offset += limit;
return _iterate(limit, offset);
});
};
let p = _iterate(100, 0);