NODE JS Api working from Postman results in timeout from App - android

I have a Node js API written in express framework.
I am sending some data over all my api does is calculate number of Packages to make For example :- 100/10 = 10 packages to make.
Loops and creates packages in sales force and firebase one by one.
Works fine from postman.
Problem:
When i try to hit the api from my app it works fine when the package count is <= 10. when > 10 ,Lets say 25 it calculates packages and run a loop of 25 and creates packages,crashes after 11th iteration and restarts the route, calculate again 25 packages to create and resulting in "Over weight error".
1- thought it was from android error may be i was hitting two request one after an other ( this was not the case ).
2- Tried sending header "Connection" "Keep-Alive" ( as Postman does ) not working.
3- tried to put up the timeout in the below code it did not work either ( tried variations of time out like 0, 50,000 ms )
else {
console.log('=====By Item=============');
const supplierFinishedGood = {
Name: parentBatchDoc['itemName'],
Supplier_Product__c: parentBatchDoc['id'],
Package_Size__c: 'a090S000001ZQ5kQAG', // Hard coded PackageSize in 'Gram' as per SALESFORCE
On_Hand_Amount__c: childBatch['batchWeight']
}
console.log('=====By Item============= 2');
const SupplierFinishedProductID = await createSupplierFinishedProduct(supplierFinishedGood, bearerToken);
const Quantity_Packaged__c = Math.floor((childBatch['batchWeight'] - childBatch['batchTestAmount']) / noOfPackage);
console.log('=====By Item============= 3');
//console.log('Quantity_Packaged__c ==== Remaining_Grams_Available_for_Packaging__c', Quantity_Packaged__c, parentBatchSalesforce['Remaining_Grams_Available_for_Packaging__c']);
for (let index = 0; index < noOfPackage; index++) {
if (parentBatchSalesforce['Remaining_Grams_Available_for_Packaging__c'] > Quantity_Packaged__c) {
let package = {
Batch__c: childId,
Product__c: SupplierFinishedProductID,
Inventory_Location__c: 'a030S000003x7M7QAI', //Hard coded InventoryLocation 'StorageFinished' as per SALESFORCE
Number_Of_Items__c: noOfItemInPackage,
Quantity_Packaged__c: Quantity_Packaged__c,
Date_Packaged__c: datePackaged,
Expiration_Date__c: expirationDate
};
console.log('Before creating apcaktge ', index);
const packageID = await createPackage(package, bearerToken);
console.log('After creating package ', index, parentBatchSalesforce['Remaining_Grams_Available_for_Packaging__c']);
package['parentBatchId'] = parentId;
package['status'] = 'Ready to checkout';
package['uid'] = packageID;
const packageFBResponse = await db.collection('packages').doc(packageID).set(package, { merge: true });
reponseBody.push(packageID);
} else {
console.log('======Over
Weight====');
}
Above code is what produces the error.
There is a If condition before this it works fine i have tested it
as it has some other scenario.
End result should not be a timeout error.
API should create all the packages and return the result.

I have found a workaround. I am Playing around batch status and my code returns me the IDs which i need and packages are created.
This is not the ultimated best solution it is a work around. i am still open to know what the actual problem is.
parentBatchDoc['childBatches'][childId]['batchStatus'] = "In Processing";
const parentBatchDocResponse = await db.collection('batches').doc(parentId).set(parentBatchDoc, { merge: true });
if(parentBatchDoc['childBatches'][childId]['batchStatus'] !== "In Processing"){
===================Rest of the case of =======================
}

Related

Flutter HEALTH package get steps from user returns always null?

I am working on a personal project and I am using flutter to develop an app (cross platform) that reads in the user's health data from google fit (Android) or Apple Health. I am using this package and even the EXACT same code like in the documentation (I am currently only testing on Android):
Future fetchStepData() async {
int? steps;
// get steps for today (i.e., since midnight)
final now = DateTime.now();
final midnight = DateTime(now.year, now.month, now.day);
bool requested = await health.requestAuthorization([HealthDataType.STEPS]);
if (requested) {
try {
steps = await health.getTotalStepsInInterval(midnight, now);
} catch (error) {
print("Caught exception in getTotalStepsInInterval: $error");
}
print('Total number of steps: $steps');
setState(() {
_nofSteps = (steps == null) ? 0 : steps;
_state = (steps == null) ? AppState.NO_DATA : AppState.STEPS_READY;
});
} else {
print("Authorization not granted - error in authorization");
setState(() => _state = AppState.DATA_NOT_FETCHED);
}
}
Then I am calling this function with await and I also have inserted the correct permission in all Android Manifest files:
Also I set up an OAuth2 Client ID for the project and added my google account as a test user.
BUT THE FUNCTION SETS THE VARIABLE STEPS ALWAYS TO NULL? The boolean variable "requested" is true, so it seems like the actual connection is working?
I am really disappointed by myself guys and I really need help - THANK YOU!
I tried adding the correct android permissions, asking for permissions explicitly, different time intervalls but nothing worked for me, I always got a null value back.

Pasre server on AWS EC2 giving 141 error on cloud code

I am now using the below cloud code to only update "downloads" column on my parse server running on AWS EC2 instance. But I am getting the error code 141(invalid function)
Parse.Cloud.define("updateDownloads", async (request) => {
const query = new Parse.Query(request.params.className);
query.get(request.params.objectId)
.then((watchFace) => {
downloads = watchFace.get("downloads")
watchFace.set("downloads", downloads + 1);
await watchFace.save(null, { useMasterKey: true });
return "download updated";
}, (error) => {
return "something went wrong";
});
});
I have place my code in /opt/bitnami/cloud/main.js.
I even tried adding “cloud”: “/opt/bitnami/cloud/main.js” in config.json file but then the parse server gives 503 Service Unavailable error. So I removed it.
If you don't add the cloud code main.js file to your parse server configuration, parse server will never find your function, and that's why you get the invalid function error.
If you get error when adding the file, you are either adding it in a wrong way (you need to check your parse server initialization code) or the config.json is in wrong format or the cloud code has a problem.
The best way to figure it out is by checking your logs.
At a first glance, a problem that I see (may have others) is the usage of await in a function that is not async. You are also using a combination of async and then, which is little strange.
I'd recommend you to change the code to something like:
Parse.Cloud.define("updateDownloads", async (request) => {
const query = new Parse.Query(request.params.className);
const watchFace = await query.get(request.params.objectId);
const downloads = watchFace.get("downloads");
watchFace.set("downloads", downloads + 1); // You can use inc function to avoid concurrency problem
await watchFace.save(null, { useMasterKey: true });
return "download updated";
});

Uploading chunked file using Ionic4 and Angular HttpClient fails after some successful uploads with net::ERR_FILE_NOT_FOUND

i'm trying to upload a large file (500+Mb, but could be even bigger) to our php server, using an app written in Ionic4+Angular+Cordova, on an emulator with Android 10.
I set up a system to upload the file in chunks.
It reads the file choosen by the user using THIS PLUGIN, chunk by chunk (5Mb per chunk).
Then it proceeds to send it to our server performing a POST request with Content-type multipart/form-data.
The file goes to server, server saves it, says "OK", then the app proceeds to send the following chunk.
Everything works fine, for the first 25/29 chunks.
Then, the POST request fails with
POST http://192.168.1.2/work/path/to/webservices/uploadChunks.php net::ERR_FILE_NOT_FOUND
I tried:
starting at another point in the file instead of byte 0 - got the same error
reading the file chunk by chunk, without making any POST request- could cycle the whole 500Mb file
reading the file chunk by chunk and making the POST requests, but not sending the chunks with them - could execute every single call without any error, through the end of the file
reading the file chunk by chunk and sending them to ANOTHER webservice - got the same error
reading the file chunk by chunk and performing a POST request to another webservice, with content-type application/json and putting the formData object into the request body (not sure this is a valid test tho) - could execute every single call without any error, through the end of the file
Checking out memory snapshots taken in chrome inspector during different chunks upload did not show any sign of memory leak.
The case was tested on a rather old device, where the same procedure caused the app to exit, without signaling any error (not even in logcat apparently).
Here is the piece of code used to chunk and send the file:
const generatedName = 'some_name_for_file';
// Path obtained from fileChooser plugin
let path_to_file = 'content://com.android.externalstorage.documents/document/primary%3ADownload%2Ffilename.avi'
const min_chunk_size = (5 * 1024 * 1024);
// Converting path to file:// path
this.filePath.resolveNativePath(path_to_file).then((resolvedPath) => {
return this.fileAPI.resolveLocalFilesystemUrl(resolvedPath);
}, (error) => {
console.log('ERROR FILEPATH');
console.log(error);
return Promise.reject('Can not access file.<br>Code : F - ' + error);
}).then(
(entry) => {
path_to_file = entry.toURL();
console.log(path_to_file);
(entry as FileEntry).file((file) => {
//Getting back to the zone
this.ngZone.run(() => {
// Re-computing chunk size to be sure we do not get more than 10k chunks (very remote case)
let file_chunk_size = file.size / 10000;
if (file_chunk_size < min_chunk_size) {
file_chunk_size = min_chunk_size;
}
//Total number of chunks
const tot_chunk = Math.ceil(file.size / file_chunk_size);
const reader = new FileReader();
let retry_count = 0; //Counter to check on retries
const readFile = (nr_part: number, part_start: number, length: number) => {
// Computing end of chunk
const part_end = Math.min(part_start + length, file.size);
// Slicing file to get desired chunk
const blob = file.slice(part_start, part_end);
reader.onload = (event: any) => {
if (event.target.readyState === FileReader.DONE) {
let formData = new FormData();
//Creating blob
let fileBlob = new Blob([reader.result], {
type: file.type
});
formData.append('file', fileBlob, generatedName || file.name);
formData.append('tot_chunk', tot_chunk.toString());
formData.append('nr_chunk', nr_part.toString());
// UPLOAD
const sub = this.http.post('http://192.168.1.2/path/to/webservice/uploadChunk.php', formData).subscribe({
next: (response: any) => {
console.log('UPLOAD completed');
console.log(response);
retry_count = 0;
if (response && response.status === 'OK') {
//Emptying form and blob to be sure memory is clean
formData = null;
fileBlob = null;
// Checking if this was the last chunk
if (part_end >= file.size) {
// END
callback({
status: 'OK'
});
} else {
// Go to next chunk
readFile(nr_part + 1, part_end, length);
}
//Clearing post call subscription
sub.unsubscribe();
} else {
//There was an error server-side
callback(response);
}
},
error: (err) => {
console.log('POST CALL ERROR');
console.log(err);
if (retry_count < 5) {
setTimeout(() => {
retry_count++;
console.log('RETRY (' + (retry_count + 1) + ')');
readFile(nr_part, part_start, length);
}, 1000);
} else {
console.log('STOP RETRYING');
callback({status:'ERROR'});
}
}
});
}
};
//If for some reason the start point is after the end point, we exit with success...
if (part_start < part_end) {
reader.readAsArrayBuffer(blob);
} else {
callback({
status: 'OK'
});
}
};
//Start reading chunks
readFile(1, 0, file_chunk_size);
});
}, (error) => {
console.log('DEBUG - ERROR 3 ');
console.log(error);
callback({
status: 'ERROR',
code: error.code,
message: 'Can not read file<br>(Code: 3-' + error.code + ')'
});
});
}, (error) => {
console.log('ERROR 3');
console.log(error);
return Promise.reject('Can not access file.<br>Code : 3 - ' + error);
}
);
I can not figure out what is going wrong. Can someone help me debug this, or knows what could be going on?
Thank you very much.
I still do not know what caused this issue, but i resolved using a PUT request instead of a POST request, sending the raw chunk, and putting additional data in custom headers (something like "X-nr-chunk" or "X-tot-chunk"). Upload completed fine without the error message.
I also used the cordova-advanced-http plugin, but i do not think it made a difference here, since it did not work with the POST request, like the other method (httpClient).
This has been tested on android only for now, not on iOS. I'll report if there is any problem. For now i consider this solved, but if you know what may have caused this problem, please share your thoughts.
Thanks everyone.

Firebase Cloud Function Triggered Twice

I'm trying to integrate Firebase Cloud Functions into an Android app. I'm new in Cloud Functions and Node.js.
So, I have the below simple node.js code to save data in Firestore database:
'use strict';
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const Firestore = require('#google-cloud/firestore');
exports.saveData = functions.https.onRequest((request, response) => {
var firestoreDB = new Firestore({
projectId: 'my_project_id',
keyFilename: 'my_key_file_name'
});
const line1 = request.body.line1;
const line2 = request.body.line2;
var data = {
name: line1,
number: line2
};
return firestoreDB.collection('myData').doc('firstDoc')
.add( data )
.then(ref => {
console.log('Data saved.');
response.end();
});
});
This code is working fine, but being executed twice. It writes the data into DB twice, it logs every single log twice in Firebase console log screen.
I have tried another function to send a message using FCM from Android device to Android device, it also send the message twice.
I checked Android side to make sure it's triggered once. I'm wondering if there is anything I'm missing out to make it work. Any help or suggestions appreciated.
You are not sending response from API so browser not getting any response and it retry the API untill timeout of 60 sec.
response.status(200).send('OK');
Enter this above line as show below -
exports.saveData = functions.https.onRequest((request, response) => {
var firestoreDB = new Firestore({
projectId: 'my_project_id',
keyFilename: 'my_key_file_name'
});
const line1 = request.body.line1;
const line2 = request.body.line2;
var data = {
name: line1,
number: line2
};
return firestoreDB.collection('myData').doc('firstDoc')
.add( data )
.then(ref => {
console.log('Data saved.');
response.status(200).send('OK');
});
});
So, the real problem was in Volley on Android (Java) side. By default, Volley makes the second attempt to reach the server if it doesn't hear back in 2.5 sec. Because I have had heavy operations and sometimes a drop in Internet speed, it always took more that 2.5 sec to respond back.
If anyone is facing similar issue, just double check Volley and make sure to add the following at the end of Volley request
stringRequest.setRetryPolicy(
new DefaultRetryPolicy(
15000, // timeout timimg of 15 sec
0, // number of retries. By default the number is 1
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
// Add the request to the RequestQueue.
MySingleton.getInstance().addToRequestQueue(stringRequest);

Ionic 2 / Ionic 3 : How to get current location of a device

None of the answers on stackoverflow worked for me. A lot of them are for Ionic 1 or those answers are deprecated or they are not working for android device.
I have seen a lot of solutions on stackoverflow about getting current location of device but non of them seems to be working for Android .
what i have tried:-
using geolocation.getCurrentPosition() , which is working for IOS and browser but not for Android.
using this.geolocation.watchPosition() , which is working for IOS and browser but not for Android.
using navigator.geolocation.getCurrentPosition(),which is working for IOS and browser but not for Android.
using fiddle solution provided by this question getCurrentPosition() and watchPosition() are deprecated on insecure origins
Anyway , all of these are deprecated by google due to :-
getCurrentPosition() and watchPosition() are deprecated on insecure
origins, and support will be removed in the future. You should
consider switching your application to a secure origin, such as HTTPS.
See goo.gl/rStTGz for more details.
what worked for me is (https://ionicframework.com/docs/native/background-geolocation/ ) & (https://www.joshmorony.com/adding-background-geolocation-to-an-ionic-2-application/ ) both of these are based on background-geolocation plugin but,it's taking almost 50-55 sec on Android device, again it's working fine for ios
The problem with joshmorony(https://www.joshmorony.com/adding-background-geolocation-to-an-ionic-2-application/ ) solution is foreground is not working for Android physical devices but working fine for browser and ios. Background tracking is working fine , which is taking almost 50 sec to give lat & lng for the first time.
Please help me with this. I want a way to get current location in minimum time. For your info, I am using google javascript map sdk / api .
I tried every solution provided by all of you and others also on internet. Finally i found a solution.You can try this plugin cordova-plugin-advanced-geolocation (https://github.com/Esri/cordova-plugin-advanced-geolocation ) from ESRI . But this plugin will work for Android not IOS. For ios you can go with same old approach . i.e - using this.geolocation.getCurrentPosition(...) or this.geolocation.watchPosition(..).
Add cordova-plugin-advanced-geolocation Plugin Like this :-
cordova plugin add https://github.com/esri/cordova-plugin-advanced-geolocation.git
then Add below line at the top of Class / Component
declare var AdvancedGeolocation:any; //at the top of class
Now add these lines inside relevant function of component ( P.S. - I have included code for both Android & IOS)
//**For Android**
if (this.platform.is('android')) {
this.platform.ready().then(() => {
AdvancedGeolocation.start((success) => {
//loading.dismiss();
// this.refreshCurrentUserLocation();
try {
var jsonObject = JSON.parse(success);
console.log("Provider " + JSON.stringify(jsonObject));
switch (jsonObject.provider) {
case "gps":
console.log("setting gps ====<<>>" + jsonObject.latitude);
this.currentLat = jsonObject.latitude;
this.currentLng = jsonObject.longitude;
break;
case "network":
console.log("setting network ====<<>>" + jsonObject.latitude);
this.currentLat = jsonObject.latitude;
this.currentLng = jsonObject.longitude;
break;
case "satellite":
//TODO
break;
case "cell_info":
//TODO
break;
case "cell_location":
//TODO
break;
case "signal_strength":
//TODO
break;
}
}
catch (exc) {
console.log("Invalid JSON: " + exc);
}
},
function (error) {
console.log("ERROR! " + JSON.stringify(error));
},
{
"minTime": 500, // Min time interval between updates (ms)
"minDistance": 1, // Min distance between updates (meters)
"noWarn": true, // Native location provider warnings
"providers": "all", // Return GPS, NETWORK and CELL locations
"useCache": true, // Return GPS and NETWORK cached locations
"satelliteData": false, // Return of GPS satellite info
"buffer": false, // Buffer location data
"bufferSize": 0, // Max elements in buffer
"signalStrength": false // Return cell signal strength data
});
});
} else {
// **For IOS**
let options = {
frequency: 1000,
enableHighAccuracy: false
};
this.watch = this.geolocation.watchPosition(options).filter((p: any) => p.code === undefined).subscribe((position: Geoposition) => {
// loading.dismiss();
console.log("current location at login" + JSON.stringify(position));
// Run update inside of Angular's zone
this.zone.run(() => {
this.currentLat = position.coords.latitude;
this.currentLng = position.coords.longitude;
});
});
}
EDIT : First installation is always going fine. But Sometimes you might get errors for no reason in subsequent installations. To make this error (any error with this plugin ) go away.Follow these steps :
1. Remove this plugin from your project (including config.xml and package.json).
2. Delete/Remove android platform.
3. Delete plugins folder.
4. Now reinstall this plugin again, following the steps above.
I have gone through the problem and find the solution.
the best way to get geolocation of the user is to use this plugin https://ionicframework.com/docs/native/geolocation/
do not forget to add this is app.moudle.ts as its a provider.
by simply adding this code in app component i was able to get location( do not forget to import and add in constructor)
this.geolocation.getCurrentPosition({ enableHighAccuracy: true }).then((resp) => {
console.log(resp);
}, Error => {
console.log(Error);
}).catch(Error => {
console.log(Error);
})
i only have the same error while i was using ionic cordova run
android --livereload that is insecure origin
but when i use ionic serve i can see the response in browser and also after
using ionic cordova run android
just to confirm response in android i check the chrome debugger.
It works for me
import { Geolocation } from '#ionic-native/geolocation/ngx';
import { NativeGeocoder, NativeGeocoderOptions, NativeGeocoderResult } from '#ionic-native/native-geocoder/ngx';
geoencoderOptions: NativeGeocoderOptions = {
useLocale: true,
maxResults: 5
};
constructor(
private geolocation: Geolocation,
private nativeGeocoder: NativeGeocoder
) {
getCurrentLocation() {
this.geolocation.getCurrentPosition()
.then((resp) => {
this.getGeoencoder(resp.coords.latitude, resp.coords.longitude);
}).catch((error) => {
console.log('Error getting location', error);
});
}
//geocoder method to fetch address from coordinates passed as arguments
getGeoencoder(latitude, longitude) {
this.nativeGeocoder.reverseGeocode(latitude, longitude, this.geoencoderOptions)
.then((result: NativeGeocoderResult[]) => {
const address = this.generateAddress(result[0]);
})
.catch((error: any) => {
// alert('Error getting location' + JSON.stringify(error));
});
}
//Return Comma saperated address
generateAddress(addressObj) {
let obj = [];
let address = "";
for (let key in addressObj) {
obj.push(addressObj[key]);
}
obj.reverse();
for (let val in obj) {
if (obj[val].length)
address += obj[val] + ', ';
}
return address.slice(0, -2);
}
you need to provide the permission for Android app as follows:
<feature name="Geolocation">
<param name="android-package" value="org.apache.cordova.GeoBroker" />
</feature>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
I ran into a similar problem. When I build from the terminal with the --prod flag, I no longer see this error since it is now requesting position over https.
Built without --prod flag
Built using the --prod flag
Edit: Sorry for the format, I hope that this makes a little more sense. I used the following function in a service that I could call from anywhere to get the latitude, longitude, accuracy, and timestamp. The key though is using the --prod flag in the terminal when building the app.
this.geolocation.getCurrentPosition().then(position => {
let locationObj = {
lat: position.coords.latitude,
lon: position.coords.longitude,
timestamp: position.timestamp,
accuracy: position.coords.accuracy
};
resolve(locationObj);
})
this method is working for bot android and browser
watchLocation() {
this.watchLocationUpdates = this.geolocation.watchPosition({ maximumAge: 60000, timeout: 25000, enableHighAccuracy: true })
.subscribe(resp => {
this.latitude = resp.coords.latitude;
this.longitude = resp.coords.longitude;
this.altitude = resp.coords.altitude;
this.accuracy = resp.coords.accuracy;
this.altAccuracy = resp.coords.altitudeAccuracy;
this.heading = resp.coords.heading;
this.speed = resp.coords.speed;
this.timestamp = new Date(resp.timestamp);
});
}
I found solution for me: use google api https://www.googleapis.com/geolocation/v1/geolocate?key={API_KEY}
If platform Android I use google api.

Categories

Resources