I'm new to LUA and I'm writing a tcp messaging library in LUA using Corona SDK. I stuck with a problem that socket reading operation hangs application UI even if it is run in coroutine.
How I start coroutine:
function Messaging:readLoop()
self.readCoroutine = coroutine.create(function() self:blockingLoop() end)
coroutine.resume(self.readCoroutine)
end
Blocking loop:
function Messaging:blockingLoop()
line,err,rest = self.sock:receive(BUFSIZE) -- <= Hangs UI if there is no incoming data
end
Of course I know that coroutines are not equal to threads, but I expected that LUA interpreter switched to another coroutine on blocking operation (like Python threads with GIL).
Is there any possibility to read from socket without blocking UI? For example with real threading or async approach? Thanks.
P.S. Eliminating BUFSIZ is not the option since I don't want to have UI blocked at all, even for 0.2..0.4 seconds (slow mobile network delay)
Corona contains LuaSockets which will let you do asynchronous socket communication, as seen here.
Corona has a network.request API for Asynchronous calls..
If you do not want to use that, take a look at this asynchronous http library.
Based on links posted by Mud and SatheeshJM, I finally made a messaging class which might be helpful for somebody
-- Messaging prototype
Messaging = {sock = nil, sockTimer = nil}
-- Messaging constructor
function Messaging:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Messaging:connect()
self.sock = socket.tcp()
print( self.sock:connect(HOST, PORT) )
self.sock:settimeout(0)
self.sockTimer = timer.performWithDelay(50, function() self:checkData() end, 0)
end
function Messaging:close()
timer.cancel(self.sockTimer)
self.sock:close()
end
function Messaging:checkData()
local data, status, rest = self.sock:receive()
local s
if data then
s = data
else
s = rest
end
if s:len() ~= 0 then
print ('received', s)
end
end
Important notes:
self.sock:settimeout(0) required to make socket non-blocking
local data, status, rest = self.sock:receive() <- In most cased data will be in "rest" variable when "timeout" error appeared, that is why we need a check below to learn how exactly the data transfered
Related
Env: Mac OS 12.1, JDK 17, Vert.x 4.2.4
Question: how to capture command line input from a verticle? Tried so far following in the public void start(Promise<Void> startPromise) throws Exception method:
getVertx().createSharedWorkerExecutor("sys-in").executeBlocking(promise -> {
try (final BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
String line;
int count = 0;
do {
System.out.print("message to MC: ");
line = br.readLine();
count++;
//doSth(line); // e.g. send line over multicast
} while (count < 3);
} catch (Throwable t) {
// log.info("<start> ", t);
} finally {
// bye(); // send a final message and close vertx
promise.complete();
}
});
This will start, get 3 nulls from br, and exit. Also tried a separated ExecutorService, in vain. Couldn't find any help in Vert.x doc either. Any hints are appreciated:
aware of the warnings of Vert.x when doing blocking stuff
Vert.x might not meant to be used this way, but would be cool if it (reading from command line) can be done with the same toolkit
I understand what you are trying to accomplish, but the problem is that that goes against fundamentals of verticles concept. Waiting for user input is potentially infinitely blocking operation i.e. there is no guarantee user will ever input the values. In that case, you are left with the verticle that is hung forever, spending resources and stuck in one spot. Multiply this if you are using worker verticles and you might have serious problems with the app. This issue is also emphasized here: https://vertx.io/docs/vertx-core/java/#blocking_code (under Warning).
In the link provided you can also find a suggested solution with a separate thread solution. Non-vertx thread won't mind being blocked and when the user input is provided can inform the vertx part of the application via the event bus that the user input dependent code can now be executed.
This might not be the solution you had in mind since it's not pure vertx, but have in mind that vert.x is just another tool, and that tool is not a good fit for what you are trying to accomplish here. However, it can be paired well with plain Java and it won't mind.
I asked how to make TCP server that send data all the time in here: Julia TCP select and it works great. I now I have new problem, so I thought to start new conversation.
I did this kind of connection like on the picture:
So Sender sends sometimes something to server 1 and server 1 reads it and updates what to send to server 2 and Server 2 calculates numbers and communicates with C program.
Here is my server 1 code:
notwaiting = true
message = zeros(10,14)
server = listen(5001)
connection = connect(5003)
while true
if notwaiting
notwaiting = false
# Runs accept async (does not block the main thread)
#async begin
sock = accept(server)
reply= read(sock, Float64, 11)
message[:,convert(Int64,reply[1])] = reply[2:11]
write(connection,reshape(message,140))
global notwaiting = true
end
end
write(connection,reshape(message,140))
if message[1,1] == -1.0
close(connection)
close(server)
break
end
sleep(0.01) # slow down the loop
end
Sender is:
Connection2= connect(5001)
message = [2.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0]
write(Connection2,message)
close(Connection2)
And server 2 is like this:
function Server2_connection()
println("Waiting for connection")
server2 = listen(5003)
conn_2 = accept(server2)
while isopen(conn_2)
try
message_server2 = round(read(conn_2,Float64,140),3)
ins_matrix = reshape(message_server2[1:140],10,14)
catch e
println("caught an error $e")
break
end
end
println("Connection closed")
close(conn)
close(server)
end
The problem is that everything together is really heavy. I mean that I can send 2 messages from sender and everything is running really slow. I can run the whole thing 10-15s and then it freezes. All the connections work, but really slowly. My question is am I missing something or have something that makes the servers really slow? How can I code this better way?
I don't have anymore problem with slowness. I got help from julia-users google forum and on of them(Tanmay K. Mohapatra) wrote better code for same purpose: https://gist.github.com/tanmaykm/c2ab61a52cc5afa0e54fe61905a48ef1 It works
same way.
One problem with both codes is that they don't close connections properly. If server 2 goes down, the server 1 gets writing error and server 1 stays in listen mode.
Other ways it works. Thanks to Tanmay!
Edit: found the slower....the thing what should slow things down, did it. The sleep command did slow things down, but it slowed down more than I expected. If I had sleep variable 0.001 seconds, it will slow down the whole system like 0.014s. So I removed sleep command and it works fine.
I'm working with libevent for the first time and have been having an issue trying to get my application to not run until the read callback is called. I am using bufferevents as well. Essentially I am doing is trying to avoid the sleep in my main application loop and instead have the OS wake up the process (via libevent) when there is data to be read off the socket. Anyone know how to do this? I found in an alpha build of libevent that you can set a base event loop to be EVLOOP_NO_EXIT_ON_EMPTY, but from looking at the libevent code that will just use up my whole proc I believe. I also read on this question that it is a bad idea to set a socket to blocking on windows which is why I haven't done that as a solution either. I will mark this with libuv and libev too since they are similar and might contribute to my solution.
you have to use the following api, some of the API may be oudated you can search google for new one.
struct event_base *base ;
struct event g_eve
base = event_init();
//after binding the socket register your socket for read event using below api
event_set(&g_eve, SockFd, EV_READ | EV_PERSIST, CallbackFunctin, &g_eve);
event_add(&g_eve, NULL);
event_base_dispatch(base);
We have a HTTP end-point that takes a long time to run and can also be called concurrently by users. As part of this request, we update the model inside a synchronized block so that other (possibly concurrent) requests pick up that change.
E.g.
MyModel m = null;
synchronized (lockObject) {
m = MyModel.findById(id);
if (m.status == PENDING) {
m.status = ACTIVE;
} else {
//render a response back to user that the operation is not allowed
}
m.save(); //Is not expected to be called unless we set m.status = ACTIVE
}
//Long running operation continues here. It can involve further changes to instance "m"
The reason for the synchronized block is to ensure that even concurrent requests get to pick up the latest status. However, the underlying JPA does not commit my changes (m.save()) until the request is complete. Since this is a long-running request, I do not want to wait until the request is complete and still want to ensure that other callers are notified of the change in status. I tried to call "m.em().flush(); JPA.em().getTransaction().commit();" after m.save(), but that makes the transaction unavailable for the subsequent action as part of the same request. Can I just given "JPA.em().getTransaction().begin();" and let Play handle the transaction from then on? If not, what is the best way to handle this use-case?
UPDATE:
Based on the response, I modified my code as follows:
MyModel m = null;
synchronized (lockObject) {
m = MyModel.findById(id);
if (m.status == PENDING) {
m.status = ACTIVE;
} else {
//render a response back to user that the operation is not allowed
}
m.save(); //Is not expected to be called unless we set m.status = ACTIVE
}
new MyModelUpdateJob(m.id).now();
And in my job, I have the following line:
doJob() {
MyModel m = MyModel.findById(id);
print m.status; //This still prints the old status as-if m.save() had no effect...
}
What am I missing?
Put your update code in a job an call
new MyModelUpdateJob(id).now().get();
thus the update will be done in another transaction that is commited at the end of the job
ouch, as soon as you add more play servers, you will be in trouble. You may want to play with optimistic locking in your example or and I advise against it pessimistic locking....ick.
HOWEVER, looking at your code, maybe read the article Building on Quicksand. I am not sure you need a synchronized block in that case at all...try to go after being idempotent.
In your case if
1. user 1 and user 2 both call that method and it is pending, then it goes to active(Idempotent)
If user 1 or user 2 wins, well that would be like you had the synchronization block anyways.
I am sure however you have a more complex scenario not shown here, BUT READ that article Building on Quicksand as it really changes the traditional way of thinking and is how google and amazon and very large scale systems operate.
Another option for distributed transactions across play servers is zookeeper which the big large nosql guys use BUT only as a last resort ;) ;)
later,
Dean
I am designing a Highly Concurrent CCR Application in which it is imperative that I DO NOT Block or Send to sleep a Thread.
I am hitting SQLConnection Pool issues - Specifically getting InvalidOperationExceptions when trying to call SqlConnection.Open
I can potentially retry a hand full of times, but this isn't really solving the problem.
The ideal solution for me would be a method of periodically re-checking the connection for availablity that doesn't require a thread being tied up
Any ideas?
[Update]
Here is a related problem/solution posted at another forum
The solution requires a manually managed connection pool. I'd rather have a solution which is more dynamic i.e. kicks in when needed
Harry, I've run into this as well, also whilst using the CCR. My experience was that having completely decoupled my dispatcher threads from blocking on any I/O, I could consume and process work items much faster than the SqlConnection pool could cope with. Once the maximum-pool-limit was hit, I ran into the sort of errors you are seeing.
The simplest solution is to pre-allocate a number of non-pooled asynchronous SqlConnection objects and post them to some central Port<SqlConnection> object. Then whenever you need to execute a command, do so within an iterator with something like this:
public IEnumerator<ITask> Execute(SqlCommand someCmd)
{
// Assume that 'connPort' has been posted with some open
// connection objects.
try
{
// Wait for a connection to become available and assign
// it to the command.
yield return connPort.Receive(item => someCmd.Connection = item);
// Wait for the async command to complete.
var iarPort = new Port<IAsyncResult>();
var iar = someCmd.BeginExecuteNonQuery(iarPort.Post, null);
yield return iarPort.Receive();
// Process the response.
var rc = someCmd.EndExecuteNonQuery(iar);
// ...
}
finally
{
// Put the connection back in the 'connPort' pool
// when we're done.
if (someCmd.Connection != null)
connPort.Post(someCmd.Connection);
}
}
The nice thing about using the Ccr is that it is trivial to add the following the features to this basic piece of code.
Timeout - just make the initial receive (for an available connection), a 'Choice' with a timeout port.
Adjust the pool size dynamically. To increase the size of the pool, just post a new open SqlConnection to 'connPort'. To decrease the size of the pool, yield a receive on the connPort, and then close the received connection and throw it away.
Yes, connections are kept open and out of the connection pool. In the above example, the port is the pool.