my idea is to create a microservice that:
A- Reads everything from a collection
B- Does a loop with all that data
C- Inside the loop, each time calls another collection to get reference data from each item
ex:
#Cron('*/10 * * * * *')
async runEvery10Seconds() {
console.log("log 1");
let allDataFromCollection= await this.findAllData();
for (let i = 0; i != allDataFromCollection.length; i++) {
let item1Id = this.referencedb(allDataFromCollection[i].item1value);
let item2Id = this.referencedb(allDataFromCollection[i].item2value);
let item3Id = this.referencedb(allDataFromCollection[i].item3value);
// then I create a JSON with this new data
let data = {
item1 = item1Id ,
item2 = item2Id,
item3 = item3Id
}
this.sendHttpPost(data);
}//close for
}
Things never reach the HttpPost and the only output is the first console log ("log 1") in loop, until the code terminates with
5: 00007FF7428063BD v8::SharedArrayBuffer::Externalize+781
6: 00007FF7426B084C v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1516
7: 00007FF7426BBB8A v8::internal::Heap::ProtectUnprotectedMemoryChunks+1258
8: 00007FF7426B8D39 v8::internal::Heap::PageFlagsAreConsistent+2457
9: 00007FF7426AD961 v8::internal::Heap::CollectGarbage+2033
10: 00007FF7426ABB65 v8::internal::Heap::AllocateExternalBackingStore+1317
11: 00007FF7426C5E06 v8::internal::Factory::AllocateRaw+166```
Related
I am an absolute beginner in Scala, but have this problem to solve.
So i have a list of parameters
itemList = List('abc', 'def', 'ghi','jkl','mno', 'pqr')
I have these 3 parameter queries
val q1 = "env='dev1'&id='123'&listitem='xyz'"
val q2 = "env='dev2'&id='1234'&listitem='xyz'"
val q3 = "env='dev3'&id='12345'&listitem='xyz'"
val report1 = getReport(q1)
val report2 = getReport(q2)
val report3 = getReport(q3)
So I am trying to loop through the list, replace the listitem parameter in q1, q2 and q3 with the listitem and then run the http request report for each item in the list.
Since each getReport request is asynchronous, i need to wait , and so i cannot go to the next item in the list, as it would be if i were to do a loop.
So i would like to start up 3 threads for each item in the list and then combine the 3 reports into 1 final one, or i could do it sequentially.
How would i go about doing it with 3 Threads for each item in the list?
This is my idea:
val reportToken = [ q1, q2,q3 ]
val listTasks = [ getReport(q1) , getReport(q2) , getReport(q3) ]
for (i <- 1 to 3) {
val thread = new Thread {
override def run {
listTasks (reportToken(i))
}
val concat += listTask(i)
}
thread.start
Thread.sleep(50)
}
You can wrap each of your tasks in a Future, apply map/recover to handle the successful/failed Futures, and use Future.sequence to transform the list of Futures into a Future of list. Here's a trivialized example:
import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
def getReport(q: String) = q match {
case "q2" => throw new Exception()
case q => s"got $q"
}
val reportToken = Seq("q1", "q2", "q3")
val listTasks = reportToken.map( q => Future{ getReport(q) } )
// listTasks: Seq[scala.concurrent.Future[String]] = ...
val f = Future.sequence(
listTasks.map(_.map(Some(_)).recover{case _ => None})
)
// f: scala.concurrent.Future[Seq[Option[String]]] = ...
Await.result(f, Duration.Inf)
// res1: Seq[Option[String]] = List(Some(got q1), None, Some(got q3))
For more details about Futures, here's a relevant Scala doc.
Assuming def getReport(str: String): Future[HttpResponse]
Future.sequence(itemList.map( item => {
for {
report1 <- getReport(q1.replace("xyz", item))
report2 <- getReport(q2.replace("xyz", item))
report3 <- getReport(q3.replace("xyz", item))
} yield {
(report1, report2, report3)
}
})).onComplete {
case Success(res) => // do something
case Failure(err) => // handle error
}
I have a multidimensional object and using Vue, I am trying to make the inner object reactive.
My object looks like this:
data() {
return {
myObject: {}
}
}
And the filled data looks like this:
myObject: {
1: { // (client)
0: "X", // (index) : (value)
1: "Y"
},
2: {
0: "A",
2: "B"
}
}
If I try using:
let value = "X";
let client = 1;
let index = 1;
let obj = {};
obj[client][index] = value;
this.myObject = Object.assign({}, this.myObject, obj);
It throws an error:
TypeError: Cannot set property '0' of undefined
And if I try below, it overwrites the initial values as it is initially setting the object to {}
let obj = {};
obj[index] = value;
let parentObj = {};
parentObj[client] = obj;
this.myObject = Object.assign({}, this.myObject, parentObj);
What is the proper way of adding the values to the multidimensional object?
In javascript, dim2Thing[1][1] = ... expressions require dim2Thing[1] to exist. This is why you get the error you mentioned. So you can do two expressions, which should work fine:
dim2Thing[1] = dim2Thing[1] || {}
dim2Thing[1][1] = otherThing
For the last block, you mention that it "overwrites the initial values"
I think what's actually happening here is just that Object.assign is not recursive. It only merges top-level keys. So if parentObj has a key that over-laps with this.myObj, then sub-keys will be lost.
Object.assign({ a: { b: 2} }, { a: { c: 3 } }) // returns { a: { c: 3 } }
This is what I interpret your code as trying to do - though I am unfamiliar with vue.js at this time, so I cannot assure it will have the desired result to your webpage:
let value = "X";
let client = 1;
let index = 1;
const newObj = Object.assign({}, this.myObject);
// if you have lodash _.set is handy
newObj[client] = newObj[client] || {}; // whatever was there, or a new object
newObj[client][index] = value
this.myObject = newObj
Just use an array, thats reactive by design.
If you need to get elements from the array in your template or anywhere just add a find method
// temp
late
<div v-for="(value, idx) in myArray">{{find(obj => obj.id === idx)}}</div>
methods: {
find (searchFunction) {
return this.myArray.find(searchFunction)
}
}
I'm trying to do the following using Node.js and the 'oracledb' node:
Consult Database A to get all bills released on a specific date.
Assign the result to a variable list.
Use the function .map() on list, and inside this function consult Database B to get client's info by a common key, for each item of list.
The problem is: the Database B requests are done all together, so if there's 1000 bills to map, it returns only 100 and treats the rest as error. It is probably related to the number of requests at the same time.
So, given the details, I'd like to know if there's a way to divide the number of requests (e.g. 100 at the time), or any other solution.
ps.: i apologize in advance for my mistakes. I also apologize for not demonstrate on code.
Here's an example of how you can do this by leveraging the new executeMany in v2.2.0 (recently released) and global temporary tables to minimize round trips.
Given these objects:
-- Imagine this is the table you want to select from based on the common keys
create table t (
common_key number,
info varchar2(50)
);
-- Add 10,000 rows with keys 1-10,000 and random data for info
insert into t (common_key, info)
select rownum,
dbms_random.string('p', 50)
from dual
connect by rownum <= 10000;
commit;
-- Create a temp table
create global temporary table temp_t (
common_key number not null
)
on commit delete rows;
The following should work:
const oracledb = require('oracledb');
const config = require('./dbConfig.js');
const startKey = 1000;
const length = 2000;
// Uses a promise to simulate async work.
function getListFromDatabaseA() {
return new Promise((resolve) => {
const list = [];
const count = length - startKey;
for (let x = 0; x < count; x += 1) {
list.push(startKey + x);
}
resolve(list);
});
}
// The list returned from A likely isn't in the right format for executeMany.
function reformatAsBinds(list) {
const binds = [];
for (let x = 0; x < list.length; x += 1) {
binds.push({
key: list[x]
});
}
return binds;
}
async function runTest() {
let conn;
try {
const listFromA = await getListFromDatabaseA();
const binds = reformatAsBinds(listFromA);
conn = await oracledb.getConnection(config);
// Send the keys to the temp table with executeMany for a single round trip.
// The data in the temp table will only be visible to this session and will
// be deleted automatically at the end of the transaction.
await conn.executeMany('insert into temp_t (common_key) values (:key)', binds);
// Now get your common_key and info based on the common keys in the temp table.
let result = await conn.execute(
`select common_key, info
from t
where common_key in (
select common_key
from temp_t
)
order by common_key`
);
console.log('Got ' + result.rows.length + ' rows');
console.log('Showing the first 10 rows');
for (let x = 0; x < 10; x += 1) {
console.log(result.rows[x]);
}
} catch (err) {
console.error(err);
} finally {
if (conn) {
try {
await conn.close();
} catch (err) {
console.error(err);
}
}
}
}
runTest();
After I posted the solution above, I thought I should provide an alternative that keeps the keys going from Node.js to the DB "in memory". You'll have to run tests and review explain plans to see which is the best option for you (will depend on a number of factors).
Given these objects:
-- This is the same as before
create table t (
common_key number,
info varchar2(50)
);
-- Add 10,000 rows with keys 1-10,000 and random data for info
insert into t (common_key, info)
select rownum,
dbms_random.string('p', 50)
from dual
connect by rownum <= 10000;
-- But here, we use a nested table instead of a temp table
create or replace type number_ntt as table of number;
This should work:
const oracledb = require('oracledb');
const config = require('./dbConfig.js');
const startKey = 1000;
const length = 2000;
// Uses a promise to simulate async work.
function getListFromDatabaseA() {
return new Promise((resolve) => {
const list = [];
const count = length - startKey;
for (let x = 0; x < count; x += 1) {
list.push(startKey + x);
}
resolve(list);
});
}
async function runTest() {
let conn;
try {
const listFromA = await getListFromDatabaseA();
const binds = {
keys: {
type: oracledb.NUMBER,
dir: oracledb.BIND_IN,
val: listFromA
},
rs: {
type: oracledb.CURSOR,
dir: oracledb.BIND_OUT
}
};
conn = await oracledb.getConnection(config);
// Now get your common_key and info based on what's in the temp table.
let result = await conn.execute(
`declare
type number_aat is table of number index by pls_integer;
l_keys number_aat;
l_key_tbl number_ntt := number_ntt();
begin
-- Unfortunately, we have to bind in with this data type, but
-- it can't be used as a table...
l_keys := :keys;
-- So we'll transfer the data to another array type that can. This
-- variable's type was created at the schema level so that it could
-- be seen by the SQL engine.
for x in 1 .. l_keys.count
loop
l_key_tbl.extend();
l_key_tbl(l_key_tbl.count) := l_keys(x);
end loop;
open :rs for
select common_key, info
from t
where common_key in (
select column_value
from table(l_key_tbl)
)
order by common_key;
end;`,
binds
);
const resultSet = result.outBinds.rs;
console.log('Showing the first 10 rows');
for (x = 0; x < 10; x += 1) {
let row = await resultSet.getRow();
console.log(row);
}
} catch (err) {
console.error(err);
} finally {
if (conn) {
try {
await conn.close();
} catch (err) {
console.error(err);
}
}
}
}
runTest();
The formatting for the binds was different (a bit simpler here). Also, because I was executing PL/SQL, I needed to have an out bind cursor/result set type.
See this post regarding cardinality with nested tables:
http://www.oracle-developer.net/display.php?id=427
If you try both, please leave some feedback about which worked better.
I am using the watch method from the onoff module to watch to status of the input, the callback function will be called for any change in the input (from 0 to 1 or from 1 to 0) which is what I want.
The problem is when I first run the application if the main is on (inputMain is 1 ) or the main is off (inputMain is 0 ) the callback function is not executed because there is no change in the value of the input.
So if the main is on I can't call the main() function until it becomes off then on, this problem only happens when I first run the application.
How do I get around this ? Is there a better approach to handle relays ?
var GPIO = require('onoff').Gpio,
inputMain = new GPIO(17,'in','both'),
inputGen1 = new GPIO(4,'in','both'),
inputGen2 = new GPIO(27,'in','both'),
inputGen3 = new GPIO(22,'in','both'),
outMain = new GPIO(11,'high'),
outGen1 = new GPIO(15,'high'),
outGen2P = new GPIO(18,'high'), // Generator 2 power
outGen2SM = new GPIO(23,'high'), //Generator 2 starting motor
outGen2 = new GPIO(24,'high'), // Generator 2 contactor
outGen3P = new GPIO(25,'high'),
outGen3SM = new GPIO(8,'high'),
outGen3 = new GPIO(7,'high'),
objects =[outMain,outGen1,outGen2P,outGen2SM,outGen2,outGen3P,outGen3SM,outGen3];
// Checking if there is main or not which is the refrence for all other power sources
inputMain.watch(function(err,state){
if (state)
main(1);
});
// Switch to Main contactor
function main (arg) {
console.log('test');
if (arg == 1) {
value = [0,1,1,1,1,1,1,1];}
else {
value = [0,0,0,0,0,0,0,0];
}
out(value);
}
// Turn on all the relays depending on values of the array ...
function out(value) {
for ( var i = 0; i< value.length; i++) {
if (value[i] == 0 ) {
var a = objects[i];
} else {
objects[i].writeSync(value[i]);
}
}
setTimeout(function() {
a.writeSync(0);
},5000);
}
I'm afraid you will need to call read or readSync for that.
...
outGen3SM = new GPIO(8,'high'),
outGen3 = new GPIO(7,'high'),
objects =[outMain,outGen1,outGen2P,outGen2SM,outGen2,outGen3P,outGen3SM,outGen3];
//Forces the first output update
main(inputMain.readSync());
How do I do a recycle for GetNextDocument or GetNextCategory in a NotesViewNavigator? Neither takes an argument so you can't use the conventional method of using a temp variable to pre get the next document like you might in a view.
I suppose the solution would be to just use getNext with an argmenumnt but can GetNextDocument / GetNextCategory still be used?
The error I am getting is on line 20. Without the recycle the code runs fine. From what I understand recycle destroys the object so I can understand the reason for the error. My questition is if there is another way around this?
[TypeError] Exception occurred calling method NotesViewNavigator.getNextDocument() null
occurs on line 20
1: var viewName = "vwParticipantsProjectIDEquipmentIDUsername";
2:
3:
4: var v:NotesView = database.getView(viewName);
5: var nav:NotesViewNavigator = v.createViewNavFromCategory(sessionScope.get("ExportProjectID"));
6:
7:
8: var viewEnt:NotesViewEntry = nav.getFirstDocument();
9:
10: while (viewEnt != null)
11: {
12:
13: if (viewEnt.isDocument())
14: {
15:
16: var doc:NotesDocument = viewEnt.getDocument();
17: }
18:
19: viewEnt.recycle();
20: viewEnt = nav.getNextDocument();
21: }
This is the pattern that I tend to use:
var documentEntry = nav.getFirstDocument();
while( documentEntry != null ){
var nextDocumentEntry = nav.getNextDocument();
// do stuff
documentEntry.recycle();
documentEntry = nextDocumentEntry;
}
Why don't you try to apply the old pattern like this:
var viewName = "vwParticipantsProjectIDEquipmentIDUsername",
v:NotesView = database.getView(viewName),
nav:NotesViewNavigator = v.createViewNavFromCategory(sessionScope.get("ExportProjectID")),
viewEnt:NotesViewEntry = nav.getFirstDocument(),
tmp:NotesViewEntry;
while (viewEnt !== null)
{
if (viewEnt.isDocument())
{
var doc:NotesDocument = viewEnt.getDocument();
}
tmp = viewEnt;
viewEnt = nav.getNextDocument();
tmp.recycle();
}
I did not test it, but I guess that works...