No ACK recieved in Gun.js - javascript

I am using Gun.js and on load I am putting a value in.
This is for a new website, and I have already tried making everything when the page loads instead of just in a script tag.
var mid = Date.now().toString() + "and" + (Math.round(Math.random()) + Math.round(Math.random())).toString();
var gun = Gun('https://gunjs.herokuapp.com/gun');
gun.get(`tictac/toe${mid}`).put({
"type": "test"
});
I expect it not to produce an error, but it is producing an error:
{err: "Error: No ACK received yet.", lack: true}
I don't know what to do.

#Mikey ,
No ACK received yet lack: true means that GUN has not received an acknowledgement that the data was correctly saved. This means your data may not be backed up.
Often times this happens because on other peers someone is running GUN as require('gun/gun') which does NOT include default storage adapters. On other (non-browser) peers, you should include GUN as require('gun') which DOES include default adapters (transport, storage, etc.).
In this case, it looks like you are connected to a testing peer (gunjs.herokuapp), please note that this is not for production use cases, and could be part of the problem.
For us to figure out what is going wrong, I highly encourage you to join our super friendly community ( https://gitter.im/amark/gun ) to help you out.

Related

Find free port not in use for apps - find some algorithm

I use the following API in my program to detrmine free port and provide it to application to run
portscanner.findAPortNotInUse(3000, 65000, '127.0.0.1', function(error, port) {
console.log('AVAILABLE PORT AT: ' + port)
})
https://github.com/baalexander/node-portscanner
This free port are given to application for use and working OK.
The problem is that if I provide a free port to application A and the application is doesn't occupied it yet(sometimes it takes some time...) and there is coming other application B and request a free port so it give to APP B the port of app A
Which cause to problem...
is there any elegant way to solve it?
my application doesn't have state so it cannot save to which app get which port...
There is solution that we can randomize the range but this is not robust ...
In my application Im getting the URL of the app that I should provide the free port to run.
update
I cannot use some broker or someting else that will controll this outside I need to find some algorithm (maybe with some smart random ) that can help me to do it internally i.e. my program is like singleton and I need some trick how to give port between 50000 to 65000 that will reduce the amount of collision of port that was provided to the apps
update 2
I've decided to try something like the following what do you think ?
using lodash https://lodash.com/docs/4.17.2#random to determine ports between with loops that provide 3(or more if that make sense) numbers for ranges like following
portscanner.findAPortNotInUse([50001, 60000, 600010], '127.0.0.1', function(err, port) {
if(err) {
console.log("error!!!-> " +err);
}else {
console.log('Port Not in Use ' + port);
}
//using that in a loop
var aa = _.random(50000, 65000);
Then If I got false in the port i.e. all 3 port are occupied ,run this process again for 3 other random number.comments suggestion are welcomed!!!
I try to find some way to avoid collision as much as possible...
I would simply accept the fact that things can go wrong in a distributed system and retry the operation (i.e., getting a free port) if it failed for whatever reason on the first attempt.
Luckily, there are lots of npm modules out there that do that already for you, e.g. retry.
Using this module you can retry an asynchronous operation until it succeeds, and configure waiting strategies, and how many times it should be retried maximally, and so on…
To provide a code example, it basically comes down to something such as:
const operation = retry.operation();
operation.attempt(currentAttempt => {
findAnUnusedPortAndUseIt(err => {
if (operation.retry(err)) {
return;
}
callback(err ? operation.mainError() : null);
});
});
The benefits of this solution are:
Works without locking, i.e. it is efficient and makes low usage of resources if everything is fine.
Works without a central broker or something like that.
Works for distributed systems of any size.
Uses a pattern that you can re-use in distributed systems for all kinds of problems.
Uses a battle-tested and solid npm module instead of handwriting all these things.
Does not require you to change your code in a major way, instead it is just adding a few lines.
Hope this helps :-)
If your applications can open ports with option like SO_REUSEADDR, but operation system keeps ports in the list in TIME_WAIT state, you can bind/open port you want to return with SO_REUSEADDR, instantly close it and give it back to application. So for TIME_WAIT period (depending on operation system it can be 30 seconds, and actual time should be decided/set up or found by experiment/administration) port list will show this port as occupied.
If your port finder does not give port numbers for ports in TIME_WAIT state, problem solved by relatively expensive open/close socket operation.
I'd advise you look for a way to retain state. Even temporary state, in memory, is better than nothing at all. This way you could at least avoid giving out ports you've already given out. Because those are very likely not free anymore. (This would be as simple as saving them and regenerating a random port if you notice you found a random port you've already given out). If you don't want collisions, build your module to have state so it can avoid them. If you don't want to do that, you'll have to accept there are going to be collisions sometimes when there don't need to be.
If the URLs you get are random, the best you can do is guess randomly. If you can derive some property in which the URLs uniquely and consistently differ, you could design something around that.
Code example:
function getUnusedPort(url) {
// range is [0, 65001). (inclusive zero, exclusive 65001)
const guessPort = () => Math.floor(Math.random() * 15001) + 50000;
let randomPort = guessPort();
while (checkPortInUse(randomPort)) {
randomPort = guessPort();
}
return randomPort;
}
Notes:
checkPortInUse will probably be asynchronous so you'll have to
accommodate for that.
You said 'between 50000 and 65000'. This is from 50000 up to and including 65000.
When managing multiple applications or multiple servers, where one must be right the first time (without retrying), you need a single source of truth. Applications on the same machine can talk to a database, a broker server or even a file, so long as the resource is "lockable". (Servers work in similar ways, though not with local files).
So your flow would be something like:
App A sends request to service to request lock.
When lock is confirmed, start port scanner
When port is used, release lock.
Again, this could be a "PortService" you write that hands out unused ports, or a simple lock in some shared resource so two things are getting the same port at the same time.
Hopefully you can find something suitable to work for your apps.
As you want to find an port that is not in use in your application, you could do is run following command:
netstat -tupln | awk '{print $4}' | cut -d ':' -f2
so in your application you will use this like:
const exec = require('child_process').exec;
exec('netstat -tupln | awk '{print $4}' | cut -d ':' -f2', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
var listPorts = stdout.split(/\n/)
console.log(listPorts); // list of all ports already in use
var aa = _.random(50000, 65000); // generate random port
var isFree = (listPorts.indexOf(aa)===-1) ? true : false;
if(isFree){
//start your appliation
}else{
// restart the search, write this in a function and start search again
}
});
this should give you list of all ports that are in use,so use any port except ones in the listPorts.

Preventing client side abuse/cheating of repeating Ajax call that rewards users

I am working on a coin program to award the members for being on my site. The program I have makes two random numbers and compares them, if they are the same, you get a coin. The problem I have is someone could go in the console and get "free" coins. They could also cheat by opening more tabs or making a program to generate more coins right now which I am trying to stop. I am thinking about converting it over to php from js to stop the cheating (for the most part) but I don't know how to do this. The code in question is:
$.ajax({
type: 'post',
url: '/version2.0/coin/coins.php',
data: {Cid : cs, mode : 'updateCoins'},
success: function (msg) {
window.msg=msg;
}});
And the code for the console is that with a loop around it. In the code above, "cs" is the id of the member so by replacing it with their id would cause them to get all the coins they would want.
Should I just have an include with variable above it? But then how would I display the success message which has the current number of coins. Also, this code is in a setInterval function that repeats every 15 milliseconds.
There are multiple ways you could do this, but perhaps the simplest would be to go in your server side code - when a request comes in, you check the time of last coin update, if there ins't one, you run your coin code and save the time of this operation in their session. If there is a stored time, ensure that it is beyond the desired time. If it is, continue to the coin update. If it isn't, simply respond with a 403 or other failure code.
In pseudo code:
if (!$userSession['lastCoinTime'] || $currentTime + $delay > $userSession['lastCoinTime']) {
// coin stuff
$userSession['lastCoinTime'] = // new time
} else {
// don't give them a chance at coin, respond however you want
}
However, since you're talking about doing this check every 15ms, I would use websockets so that the connection to the server is ongoing. Either way, the logic can be comparable.
Just in case there's any uncertainty about this, definitely do ALL of the coin logic on the server. You can never trust the user for valid data coming in. The most you can trust, depending on how your authentication is setup, is some kind of secret code only they would have that would just let you know who they are, which is a technique used in place of persistent sessions. Unless you're doing that, you would rely on the session to know who the user is - definitely don't let them tell you that either!

Postgresql. One process insert, second try to select but not found

Strange situation.
I try to start chat application.
I use postgresql 9.3 and tomcat as web server.
What is happens when one browser sending message another:
1 - Broswer A send message to server (tomcat)
2 - Tomcat put msg into database and get his id
INSERT INTO messages VALUES('first message') returning into MSGID id
3 - Tomcat resend message to Browser B (websocket recipient)
4 - Browser B send system answer: MSGID_READED
5 - Tomcat update database message
UPDATE messages SET readtime = now() WHERE id = MSGID
All works, but sometimes at point 5 update can't find message by MSGID...
Very strange, coz at point 2 I getting message record ID, but at 5, not.
May postgresql write slowly and this record not allow (not visible) from parallel db connection?
UPDATE
I found solution for me, just put insert inside begin/exception/end block.
BEGIN
INSERT INTO messages (...)
VALUES (...)
RETURNING id INTO MSGID;
EXCEPTION
WHEN unique_violation THEN
-- nothing
END;
UPDATE 2
In detail tests above changes with BEGIN block has no effects.
Solution in Javascript! I sent websocket messages from other thread and problem solved!
// WebSocket send message function
// Part of code. so is a web socket
send = function(msg) {
if (msg != null && msg != '') {
var f = function() {
var mm = m;
// JCC.log('SENT: [' + mm + ']');
so.send(mm);
};
setTimeout(f, 1);
}
};
Ok, so the problem is that normally writers do not block readers. This means that your first insert happens, and the second insert fires before the first one commits. This introduces a race condition in your application which introduces the problem you see.
Your best issue here is either to switch to serializable snapshot isolation or to do what you have done and do exception handling on the insert. One way or another you end up with additional exception handling that must be handled (if serializable, then a serialization failure exception may sometimes happen and you may have to wait for it).
In your case, despite the performance penalty of exception handling in plpgsql, you are best off to do things the way you are currently doing them because that avoids the locking issues and waiting for the transaction to complete.

Disconnect node-xmpp client

I am looking at node-xmpp and node-simple-xmpp and I am trying to make a simple client.
Everything works fine, except the disconnect.
I have made the following file after the example of simple-xmpp:
var xmpp = require('simple-xmpp');
xmpp.on('online', function() {
console.log('Yes, I\'m connected!');
xmpp.send('test2#example.com', 'Hello test');
// OK UNTIL HERE, DISCONNECT NOW
});
xmpp.connect({jid: 'test#example.com/webchat', password: 'test', reconnect: 'false'});
But I don't know how to disconnect. I tried to send a stanza with unavailable type:
stanza = new xmpp.Element('presence', {from: 'test#example.com', type: 'unavailable'});
xmpp.conn.send(stanza);
delete xmpp;
This is causing the client to go temporarily offline, but the problem is, it reconnects after a few seconds and keeps sending 'presence' stanza.
I have also tried calling xmpp.conn.end(), which also disconnects but it gives an error afterwards:
node_modules/simple-xmpp/node_modules/node-xmpp/lib/xmpp/connection.js:100
if (!this.socket.writable) {
^
TypeError: Cannot read property 'writable' of undefined
So, what am I doing wrong? I am sure there is an easy way to disconnect.
In the first case, <presence type='unavailable'/> does not always actually disconnect you; in your server, it looks like it might be, but your client is auto-reconnecting. delete xmpp is not actually causing your object to be cleaned up, it's just removing it from the local namespace.
In the second case send() isn't writing your stanza to the underlying socket immediately. If you close the socket with end() right afterwards, the socket is closed when the write actually happens.
If you add a short timeout after you call send(), before calling end() it will work. To make it good, you'll want your library developers to give you a callback when send() has actually written to the socket.
You should also check this out https://www.rfc-editor.org/rfc/rfc7395
In short if client is using to open connection it should use to kill that same connection.
To be more precise:
<close xmlns="urn:ietf:params:xml:ns:xmpp-framing" />
Solution of "Joe Hildebrand" also solved my problem, but this seemed more proper way for me.

JSJaC + Openfire: no connection with some users

ok, I'm finally at my wits' end. I have a have an XMPP server (Openfire) running, and trying to connect via JavaScript using JSJaC. The strange thing is that I can establish a connection for some users, but not for all. I can reproduce the following behavior: create two accounts (username/password), namely r/pwd and rr/pwd with the result:
r/pwd works
rr/pwd doesn't work.
So far, each account with a user name consisting of only one character works. This is strange enough. On the other side, old accounts, e.g., alice/a work. The whole connection problem is quite new, and I cannot trace it to any changes I've made.
And to make my confusion complete with any instant messenger supporting XMPP, all accounts work, incl., e.g., rr/pwd. So assume, the error must be somewhere in my JavaScript code. Here's he relevant snippet:
...
oArgs = new Object();
oArgs.domain = this.server;
oArgs.resource = this.resource;
oArgs.username = "r";
oArgs.pass = "pwd";
this.connection.connect(oArgs);
The code above works, but setting oArgs.username = "rr", and it fails.
I would be grateful for any hints. I'm quite sure that it must be something really stupid I miss here.
Christian
Adding oArgs.authtype = 'nonsasl' to the argument list when creating the xmpp connection using JSJaC solved my problem. I haven't tried Joe's command to alter the SASL settings in Openfire; I'm scared to ruing my running system :).

Categories