How to put data in gundb at server side as a peer - gun

I thought gun instance in the server was also one of the peers.
But when I put data on the server, the peer can't get the data.
Here is my simple test code.
global.gun.get('servertest').put('yes'); // at server side
gun.get('servertest').once(console.log); // at client side
And it prints undefined.
please, let me know how to use a gun instance on server side.

On the server, run this to actually accept remote connections:
var server = require('http').createServer().listen(8080);
var gun = Gun({web: server});
On the client, run this to connect to your server:
var gun = Gun({peers: ["http://server-ip-or-hostname:8080/gun"]})
As a side note, even if you establish a peer connection to get your data, you still need to handle undefined, as once() might fire several times as data is coming in.
Relevant links:
https://gun.eco/docs/Installation#server:
https://github.com/amark/gun/tree/master/examples
https://github.com/skiqh/gun-cli
EDIT:
To be more explicit about my side note above -- the once callback on your client getting undefined for non-local data is actually by design. It means the client does not have the requested data available yet. It will however request it from its peers, which will try to answer with what they themselves can resolve (locally or from their respective peers). These answers will trigger the callback again (if they got through the CRDT algorithm I think).
Getting undefined on the client could also mean the server's response might have timed out and GUN considered it unanswered. You can prolong the waiting time with .once(callback_function, {wait: time_in_miliseconds}).
As per Hadar's answer, try using on() instead of once() to mitigate race conditions, i.e. your client requesting data from the server before you actually wrote it. Once you got your data and don't want any more updates, you can unsubscribe with gun.get('servertest').off()
Also, it might be noteworthy that GUN instances are not magically linked; having two of them connected does not mean they are one and the same in any way. Conceptually, they are peers in a distributed system, which in GUN's case gives you eventual consistency with all the limits and tradeoffs associated with that.

#skiqh
Hello, Thanks for your answer.
I initiated gun instance well in both server and client.
server
let server = https.createServer(options, app);
server.listen( port );
let gun = Gun({ file: 'data', web: server });
global.gun = gun; // <-- my gun instance on server side
global.gun.get('servertest').put('yes'); <-- I tried to put data
// listening~~~~~
client
window.G = G;
let opt = {};
opt.store = RindexedDB(opt);
opt.localStorage = false;
opt.peers = ['https://my.link/gun'];
G.gun = Gun(opt); // <-- my gun instance on client
gun.get('servertest').once(console.log) // <-- it prints "undefined" even though I put data here by server!
I really want to know how to use methods like .put(), .get(), .on() etc.. on the server side using gun instance.
I tried doing this but failed as I attached the result on my post.
Please, Let me know what Im doing something wrong and the correct way.
Thank you

try gun.on instead of once. on will subscribe to all changes.
your example should work if you run .once only after you write something to the server.
using gun.on on client should work regardless and will trigger the moment the server write somehting

Related

gRPC and C#: receive message bigger than maximum allowed

I am doing some test to request some data to a remote database from a client. For that, I have a client gRPC that call a method in the gRPC, this gRPC server use EF to get the data and send the result to the client.
Well, in my case, I get about 3MB of data, that is higher than the default maximum size allowed for the channel.
I know that I can resolve the problem when I create the channel in the client, in this way, for example, to 60 mb:
var channel = GrpcChannel.ForAddress("http://localhost:5223",
new GrpcChannelOptions
{
MaxReceiveMessageSize = 62914560,
MaxSendMessageSize = 62914560,
});
But although I can increase this when I create the channel, I can't ensure that some query returns more data than the maximum allowed.
So I would like to know how I can handle this.
In this case, the method is unaray, it is not a stream.
Thanks.

How can I restrict data stored on GUN.js browser peers to data they subscribe to ONLY?

I'm new to GUN and it looks very promising for the project I'm working on. One thing I haven't been able to make happen is restricting data on a browser peer to just data that it requests or subscribes to with on(). The following example is my very simple test setup: I have two distinct "conversations", each represented by a distinct data node. One browser gets and puts to a "blue" data node, and the other browser gets and puts to a "red" node. Both browsers sync up to a single server peer. I'd like the server peer to store a copy of all data and each browser to only store the data it subscribes to. Using version 0.9.2.
On Browser1, I run the following:
var peers = ['http://localhost:8080/gun',];
var gun = Gun(peers);
var blue = gun.get('blue');
blue.on(data => console.log('Blue update!', data.message));
On Browser2, I run the following:
var peers = ['http://localhost:8080/gun',];
var gun = Gun(peers);
var red = gun.get('red');
red.on(data => console.log('Red update!', data.message));
The server node runs this:
var http = require('http');
var server = http.createServer();
var Gun = require('gun');
var gun = Gun({web: server});
server.listen(8080, function () {
console.log('Server listening on http://localhost:8080/gun')
})
I then use the console of each browser peer to post some data to the node it is subscribed to. I would expect that each browser's local storage should only contain data for the node it subscribes to, while the server's data.json should contain data for both nodes.
What I see is that the server is storing all data as expected, but in viewing the localstorage I see that the browsers are also storing everything, even the data they've never requested. Is this the intended behavior, or am I missing something? I thought browser peers only store data they subscribed to. While it makes sense for server peers to replicate data to maintain redundancy in the case of failures, I wouldn't want my app clients themselves to be storing countless conversations that they're not a part of.
Thanks for the help!

How to get peer certificate in cowboy_http_handler

My question for today: is there an official way to obtain peer ssl socket information (peer certificate to be exact) in cowboy_http_handler's Handler:handle(Req, State)?
Of course, I can scrape Req tuple (peer socket is the second field as of today) with erlang:element/2, but this is not future-proof and just doesn't look right.
Thanks in advance!
There is an exported call:
cowboy_req:get(socket, Req)
It returns the socket, or just about everything else there is in the Req object, currently:
bindings
body_state
buffer
connection
headers
host
host_info
meta
method
multipart
onresponse
path
path_info
peer
pid
port
qs
resp_body
resp_compress
resp_headers
resp_state
socket
transport
version
I'm not sure if it is in the documentation, I can't see it, but it's a lot better and less likely to fail than just getting a numbered element value out, and you can always add a unit test that checks that it works, so if it does get stamped/broken at some point you get a heads up. I don't expect it'll go anywhere though.

My SQL Server Can Only Handle 2 players?

I am developing a game using TCP. The clients send and listen the server using TCP. When the server receives a request, then it consults the database (SQL Server Express / Entity Framework) and sends a response back to client.
I'm trying to make a MMORPG, so I need to know all the players locations frequently, so I used a System.Timer to ask the server the location of the players around me.
The problem:
If I configure the timer to trigger for every 500ms a method that asks the server the currently players location, then I can open 2 instances of the client app, but it's laggy. If I configure to trigger for every 50ms, then when I open the second instance, the SQL Server throws this exception often:
"The connection was not closed. The connection's current state is open."
I mean, what the hell? I know I am requesting A LOT of things to the database in a short period, but how do real games deals with this?
Here is one code that throws the error when SQL Server seems to be overloaded (second line of the method):
private List<CharacterDTO> ListAround()
{
List<Character> characters = new List<Character>();
characters = ObjectSet.Character.AsNoTracking().Where(x => x.IsOnline).ToList();
return GetDto(characters);
}
Your real problem is ObjectSet is not Thread Safe. You should be creating a new database context inside ListAround and disposing it when you are done with it, not re-using the same context over and over again.
private List<CharacterDTO> ListAround()
{
List<Character> characters = new List<Character>();
using(var ObjectSet = new TheNameOfYourDataContextType())
{
characters = ObjectSet.Character.AsNoTracking().Where(x => x.IsOnline).ToList();
return GetDto(characters);
}
}
I resolved the problem changing the strategy. Now I don't update the players positions in real time to the database. Instead, I created a list (RAM memory) in the server, so I manage only this list. Eventually I will update the information to the database.

Can Flash be integrated with SQL?

Can Flash be used together with SQL? I have a Flash form and I need to connect it to SQL. If there is any example on the net about this topic. I can't find it.
You don't use ActionScript directly with an SQL database. Instead you make http requests from ActionScript to a server, specifying the correct parameters. A typical opensource setup, is a PHP script communicating with a MySQL DB, but you can use Java with Oracle, Ruby with CouchDB, .NET with SQL or any other possible configuration. The important point is that you must be able to call a server script and pass variables... typically a Restful setup.
Once your PHP script has been properly configured, you can use http POST or http GET to send values from ActionScript.
PHP:
<?php
$updateValue = $_POST["updateValue"];
$dbResult = updateDB( $updateValue ); //This should return the db response
echo( $dbResult );
?>
To call this script from ActionScript, you need to create a variables object.
var variables:URLVariables = new URLVariables();
variables.updateValue = "someResult";
The variable name .updateValue, must match the php variable exactly.
now create a URLRequest Object, specifying the location of your script. For this example the method must be set to POST. You add the variable above to the data setter of the request.
var request:URLRequest = new URLRequest( "yourScript.php" );
request.method = URLRequestMethod.POST;
request.data = variables;
Now create a URLLoader and add an event listener. Do not pass the request created above to the constructor, but to the load method.
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onComplete );
loader.load( request );
The handler would look something like this.
private function onComplete( e:Event ) : void
{
trace( URLLoader( e.target ).data.toString() );
}
This example shows how to update and receive a response from a server / db combo. However, you can also query a DB through the script and parse the result. So in the PHP example above, you can output JSON, XML or even a piped string, and this can be consumed by ActionScript.
XML is a popular choice, as ActionScript's e4x support treats XML like a native object.
To treat the response above like an XML response, use the following in the onComplete handler.
private function onComplete( e:Event ) : void
{
var result:XML = XML( URLLoader( e.target ).data );
}
This will throw an error if your xml is poorly formed, so ensure the server script always prints out valid XML, even if there is a DB error.
The problem with this is giving someone a flash file that directly accesses SQL server is very insecure. Even if it's possible, which I have seen SOCKET classes out there to do so for MySQL (though never used it), allowing users to remotely connect to your DB is insecure as the user can sniff the login information.
In my opinion, the best way to do this is to create a Client/Server script. You can easily do this with PHP or ASP.net by using SendAndLoad to send the data you need to pass to SQL via POST fields. You can then send back the values in PHP with:
echo 'success='.+urlencode(data);
With this, flash can access the data via the success field.
I don't personally code flash but I work with a company who develops KIOSK applications for dozens of tradeshow companies, and my job is to store the data, return it to them. This is the method we use. You can make it even cleaner by using actual web services such as SOAP, but this method gets the job done if its just you using it.
You should look into Zend Amf or even the Zend Framework for server side communication with Flash. As far as I know Zend Amf is the fastest way to communicate with PHP ( therefore your database ) also you can pass & return complex Objects from the client to the server and vice versa.
Consider this , for instance. You have a bunch of data in your database , you implement functions in ZF whereas this data is formatted and set as a group of Value Objects. From Flash , you query ZF , Zf queries the database , retrieve & formats your data, return your Value Objects as a JSON string ( for instance ). In Flash, you retrieve you JSON string , decode it and assign your Value Objects to whatever relevant classes you have.
There are plenty of tutorials out there regarding Flash communication with the Zend Framework.
Here's an example:
http://gotoandlearn.com/play.php?id=90