Phonegap/Cordova query Web SQL Database - javascript

I'm developing an Android/iOS mobile application using cordova/phonegap.
When my app is ready, It's going to create, if needed, the database (DB) using Web SQL.
After creation, I'm going to make a DB query to know whether a user already exists in DB or not. Depending on query result, I will either show a form to user or simply present a welcome message.
DB Initialization code (when application is ready):
app.db.transaction(app.initDB, app.dbError, app.queryUser);
If previous code runs ok, the funcion app.queryUser gets executed:
app.queryUser = function(tx){
tx.executeSql('SELECT name, mail from User', [], app.renderUserData, app.dbQueryError);
}
And my function app.renderUserData:
app.renderUserData = function(tx, results){
if(results.rows.length < 1) {
console.log("You have NO data!");
inputUserData();
} else {
console.log("You have data!");
showUserData(results.rows.item(0).name, results.rows.item(0).mail);
}
}
Inside this function, depending on whether user has associated data or not on DB, I'm going to call one of two functions that injects some HTML DOM on the page.
In the middle of any of these functions - inputUserData() or showUserData() - sometimes (seems like it's random) the code just stops executing, and calls the error callback function app.dbError() (from my app.db.transaction call) gets called with following message:
"the statement callback raised an exception or statement errorcallback did not return false"
And it just happens while I'm testing this on my Android phone, because when using the app on Chrome dev tools, or using Apache Ripple the app does what it's supposed to do.
If someone needs more info about the code, etc, just ask..
Thanks in advance for the help.
EDIT
There is app.dbQueryError()
app.dbQueryError= function(err){
console.log("QUERY ERROR: " + err.message + "\nCode=" + err.code);
}

Related

IBM MQ cmit and rollback with syncpoint

Infra-Overview:
I have a setup where I am reading a set of messages from IBM MQ and processing those messages in k8 cluster env and sending it to the destination host.
Issue:
I observed that sometimes the flow of the messages is huge and before sending it to the destination host our pod gets failed and restarts, by this we are losing all the messages as we are following a read-and-delete approach from ibmmq example
Expected Solution:
I am looking for a solution where, until these messages are sent to the destination host, we don't lose the track of the messages.
What I tried:
We have a concept of unit of work in IBM MQ but since we can't expect a delay in reading and processing, I can't wait for a single message to get processed and then read the another message as it might have a major performance setback.
Code language:
NodeJs
As the comments suggest there are a number of ways to skin this cat, but you will need to use transactions.
As soon as you create the connection with the transaction option, the transaction scope begins. This gets closed and next transaction begins when you either commit or rollback.
So you should handle the messages in batches, that make sense to your application, and commit when the batch is complete. If your application is killed by k8s then all uncommitted read messages will get rolled back, via back out queue process to stop poison messages.
Section added to show sample code, and explanation of backout queues.
In your normal processing, if an app gets stopped before it has had time to process the message, you will want that message returned to the queue. So that the message is still available to be processed.
To enable this rollback you need to or in the MQC.MQPMO_SYNCPOINT into the get message options
gmo.Options |= MQC.MQGMO_SYNCPOINT
Then if all goes well, you can commit.
mq.Cmit(hConn, function(err) {
if (err) {
debug_warn('Error on commit', err);
} else {
debug_info('Commit was successful');
}
});
or rollback
mq.Back(hConn, function(err) {
if (err) {
debug_warn('Error on rollback', err);
} else {
debug_info('rollback was successful');
}
});
If you rollback, the message goes back to the queue. Which means it is also the next message that your app will read. This can generate a poison message loop. So you should also set up a backout queue with pass all context permissions for your app user and a backout threshold.
Say you set the threshold to 5. The message can be read 5 times, with rollback. Your app needs to check the threshold and decide that it is a poison message and move it off the queue.
To check the backout threshold (and the backout queue name) you can use the following code
// Remember to or in the Inquire option on the Open
openOptions |= MQC.MQOO_INQUIRE;
...
attrs = [ new mq.MQAttr(MQC.MQIA_BACKOUT_THRESHOLD),
new mq.MQAttr(MQC.MQCA_BACKOUT_REQ_Q_NAME) ];
mq.Inq(hObj, attrs, (err, selectors) => {
if (err) {
debug_warn('Error retrieving backout threshold', err);
} else {
debug_info('Attributes have been found');
selectors.forEach((s) => {
switch (s.selector) {
case MQC.MQIA_BACKOUT_THRESHOLD:
debug_info('Threshold is ', s.value);
break;
case MQC.MQCA_BACKOUT_REQ_Q_NAME:
debug_info('Backout queue is ', s.value);
break;
}
});
}
});
When getting the message your app can use mqmd.BackoutCount to check how often the message has been rolled back.
if (mqmd.BackoutCount >= threshold) {
...
}
What I have noticed, that if this is in the same application instance that is repeatedly calling rollback on the same message, then at the threshold a MQRC_HOBJ_ERROR error is thrown. Which your app can check for, and then discard the message.
If its a different app instance then it doesn't get the MQRC_HOBJ_ERROR error, so it can check the backout threshold and can discard the message, remembering to commit the discard action.
See https://github.com/ibm-messaging/mq-dev-patterns/tree/master/transactions/JMS/SE for more information.
As an alternative you could use keda - https://keda.sh - which works with k8s
to monitor your queue depth and scale according to the number of messages waiting to be processed, as opposed to CPU / memory consumption. That way you can scale up when there are lots of messages waiting to be processed, and slowly scale down then the queue becomes manageable. Here is a link to getting started - https://github.com/ibm-messaging/mq-dev-patterns/tree/master/Go-K8s - the example is for a Go app, but equally applies to Node.js

How to allow JavaScript to receive a message sent to a specific user (or self) using Signal R?

I previously asked this question but it was closed for duplication owing to this thread (SignalR - Sending a message to a specific user using (IUserIdProvider) *NEW 2.0.0*) - but this doesn't show the JavaScript as made clear in my title.
I have a WebForm application in ASP.Net that uses SignalR to push live data to the user logged in. The setup works perfectly, but realised I am broadcasting messages to all clients, which whilst it doesn't cause the wrong data to displayed to the logged in user, does cause the JavaScript function to get called for all users when just one has a data push.
I have amended the Hub code to broadcast to a specific user (User) and provided the User ID, and I have also tried Client with a Connection ID. Both fire off fine in the codebehind, but the javascript will not update the front end.
I believe it's because the JavaScript has not been modified to listen for a message sent to the user, but I'm not sure how I need to adapt the code to allow the message to be received.
The 2 tried lines in Hub here:
context.Clients.User(Me.Context.User.Identity.GetUserId()).ReceiveNotification(notifCount)
context.Clients.Client(Me.Context.ConnectionId).ReceiveNotification(notifCount)
JavaScript/jQuery function for the SignalR message here:
$(function () {
var nf = $.connection.notificationHub;
nf.client.receiveNotification = function (notifCount) {
// Update data
}
$.connection.hub.start().done(function () {
nf.server.sendNotifications();
}).fail(function (e) {
alert(e);
});
//$.connection.hub.start();
});
For calling back to the client (or self) you should use:
Clients.Caller.addContosoChatMessageToPage(name, message);
And for calling users you should use:
Clients.Client(Context.ConnectionId).addContosoChatMessageToPage(name, message);
Reference - docs

Updating data from Parse.com without re-login

I have a web app, that manages a budget for a user.
In the settings page, I can edit the budget, after clicking "save" I return to the main page, and there I have line that states the budget amount.
The problem is, that when I log in, I see the correct budget, after editing the budget and returning to the main page, I still see the old amount. Only after logging out and re-login again, that line in the main page updates to new amount.
Any solutions?
The code that saves the new budget:
$("#saveNewBudgetAmount").click(function(){
var User = Parse.User.extend("User");
var query = new Parse.Query(User);
var newBudget = $("#newBudgetSum").val();
query.equalTo("objectId", Parse.User.current().id);
query.first({
success: function (User) {
User.save(null, {
success: function (user) {
User.set("budget", newBudget);
User.save();
location ="Mainpage.html";
}
});
}
});
});
and the code that displays it on the main page:
var MBudget = (function () {
if (Parse.User.current()) {
return("Your monthly budget is:" +" "+Parse.User.current().get("budget")+" "+"<a href=Settings.html>(Edit)</a>");
}
A few things are happening.
First you should simplify your code, and use both alerts AND error handling so that you know if your code works, and when callbacks are made. You are also calling .save() once before any new values are set, so you have a useless save.
You also need to have a success and error callback for EVERY save function you use - .save() by itself is an asynchronous method, and since you are not calling a success function within your save method, so your app will navigate back to "Mainpage.html" before it is known whether or not the save function worked. Here is a much better implementation:
var newBudget = $("#newBudgetSum").val();
var currentUser = Parse.User.current();
currentUser.save(
{
// Set as many properties as you like in this field,
// think of it as a JSON object except you don't
// have to enclose the values in strings.
budget : newBudget,
}, {
success: function(user) {
alert("Budget successfully saved, new budget is: " + user.get("budget"));
},
error: function(error) {
// error functions will always have an error argument handed back to the client,
// with properties error.code and error.message. Error messages are incredibly useful.
alert("Budget save failed, error: " + error.code + " " + error.message);
}
});
Another tip is that I recommend all users of Parse.com to use alert() messages for their success and error callbacks while in development, for many reasons - but the key reasons are 1) it will alert you to whether or not the code worked, and 2) it will prevent accidental bugs from causing infinite requests to the Parse.com server, which does happen sometimes, and will cause them to charge your account.
The problem is this api : Parse.User.current() never sync data in the cloud. The data of Parse.User.current() is derived from localstorage. You have to refresh it manually by calling save or fetch method on it.
Parse.User.Current() return normal Parse.User object. You can use it directly without querying in advance. So you can just rewrite your first codes as following :
$("#saveNewBudgetAmount").click(function() {
var user = Parse.User.current() ;
var newBudget = $("#newBudgetSum").val();
user.set("budget", newBudget);
user.save(null,{
success: function(user) {
// feedback user and redirect page.
},
error: function(user, error) {
//You should always handle error.
console.error(error.message) ;
}
}) ;
});
With this code, the local data would refresh when ths save() call done successfully. On your main page the budget value of Parse.User.current() object would be correct.

Parse.com Adding Cloud code to html buttons

I'm testing some functions locally using my database created on parse.com and the functions run exactly as intended. I am trying now to put these functions on cloud code to reduce the amount of request sent to parse as well as run the queries in the cloud code instead of locally. For whatever reason I cant get these functions to work when I convert them to cloud code. Also, how would I make a button in html that can run a function in cloud code?
Before cloud code, my html button looked like this:
<button type="button" onclick="authenticate()">Log-In</button>
How would I create that button with cloud code that looks like this:
Parse.Cloud.define("authenticate()", function(request, response) {
var myname = document.getElementById("username").value;
var mypass = document.getElementById("psswd").value;
Parse.User.logIn(myname, mypass, {
success: function(user) {
// Do stuff after successful login.
if(myname == "test1" || myname == "test2"){
window.location.href="itSplash.html";
}
else{
window.location.href="ticketRequest.html";
}
},
error: function(user, error) {
// The login failed. Check error to see why.
alert("Failed to login: " + error.message);
}
});
});
for clarification that if statement just directs login to itSplash if username matches test1 or test2, and ticketRequest if its anyone else. We have a seperate page for different users. Also, that function works locally if I create it as a normal function authenticate(). When I converted it to cloud code as seen above it wont work. I create a seperate function name runAuthenticate() with a Parse.Cloud.run call inside that and it wouldnt work there. All I got was an Error saying define cannot be used on that Object. Any Help?
You can link the HTML button with a cloud code function by using Parse.Cloud.run.
Take a look at the Parse Cloud code
documentations.
This is how you can call the cloud code from javascript.
Parse.Cloud.run('hello', {}, {
success: function(result) {
// result is 'Hello world!'
},
error: function(error) {
// Error while running cloud code
}
});
As you have written, you can try calling a javascript method onclick on the HTML button and then call the Parse.Cloud.run method.
First, you don't have access to document or window in cloud code so you need to rethink where you're coming from.
Also, it isn't appropriate to have the user details sent to the cloud code, you should login on the web page using the SDK and then use the SDK to trigger the cloud code and it will send the user and auth details.
So, the whole premise of your authenticate function being in cloud code doesn't really work.
That doesn't mean you shouldn't use cloud code, it's just that you shouldn't use it for this purpose. You talk about making queries but you don't actually have any in the code you show - but that kind of thing is more likely to be movable to cloud code...

Simple form submission with Firebase; can I detect when offline?

I'm using Firebase perhaps slightly unconventionally -for simple form submission. Submission of my website's contact form simply results in:
ref.push({name:'dr foo', email:'1#2.com', message:'bar'}, myCallback);
The Firebase is hooked up to Zapier to send the site owner an email. All works well, but I'd like to be able to handle the user loosing their connection. When Firebase can't reach the server I'd like to display: "Please check your connection", or a similar message when the user hits the send button. The "Thanks, we'll be in touch"-type message should only be displayed on a successful write.
At first I tried including an if (error) branch in the callback, but of course disconnection is not something that Firebase considers an error as it "catches up" when it can.
I also tried the code in the docs which monitors .info/connected. While this wouldn't display a message on a form submission attempt, I was thinking I could instead display a warning if disconnected. The sample worked intermittently (Chrome 39, Firefox 30, Linux Mint), but the lag between disconnection and the event firing means it's probably not suitable for this case.
Is what I'm trying to do possible?
It indeed seems that the .info/connected values only changes once some other data transfer occurs (and fails).
The only way I can come up with is by using the transaction mechanism with applyLocally set to false. E.g.
function testOnlineStatus() {
var ref = new Firebase('https://your.firebaseio.com/');
ref.child('globalcounter').transaction(function(count) {
return (count || 0) + 1;
}, function(error, committed, snapshot) {
if (error) {
alert('Are you offline?');
}
}, false /* force roundtrip to server */);
}
setInterval(testOnlineStatus, 2000);
This one triggered for me after about 15 seconds.

Categories