How to use an async timer - python

I have a Python Server running on Win10, communicating with an Android App (written in JavaScript) as a Client, using Sockets.
While the App is in the foreground everything works OK. Once the App is sent to the background (depending on available memory in the mobile), communication stops, and the Server hangs waiting for a reply from the Client.
I could find no way to keep the Android App if the foreground, and I do not have the source code.
The only solution I could think of is to have an Async timer, which after (say 60 seconds) signals the Server to terminate the App, and re-open the Server awaiting for the App to re-connect.
Here is my PSEUDO code:
OpenSocket() # waits for Client to connect
while True:
send(message) # to Client
start async.timer # sleep for 60 seconds
timer != finished:
reset timer
rec = receive.message() # do processing
else:
send(TerminatingMessage)
OpenSocket()
I would appreciate any help to code the above !

When an app is in the background on Android it's rapidly killed off. Within 2 minutes. To prevent that you could use a foreground service. That will increase the length of time it stays alive, but will not help permanently. It also will not help if the phone screen is turned off. When the screen is off you enter a power saving mode called Doze, where apps only get a brief window for IO every 15 minutes.
Basically- this type of architecture is inappropriate for an Android app. Your best bet is to rearchitect. High priority push messages can restart your app if its killed while backgrounded and can override Doze, so long as you don't send too many. Beyond that, we'd need to know how often your app sends and receives data and how important it is that it's timely to help.

Related

strange while loop behavior with time.sleep above 90 s

I'm struggling understanding a "weird" behavior of my simple script. Basically, it works as expected if time.sleep() is set as 60s but as soon as I put a value above 90 (90 is the limit apparently in my case), the loop doesn't work properly. I discovered this when I was trying to pause the script for 3 mins.
Here's my script
from gpiozero import CPUTemperature
import time
import paho.mqtt.client as mqtt #import the client1
import psutil
broker_address="192.168.1.17"
client = mqtt.Client("P1") #create new instance
client.connect(broker_address) #connect to broker
#time.sleep(60)
while True:
cpu = CPUTemperature()
print(cpu.temperature)
#a=cpu.temperature
#print(psutil.cpu_percent())
#print(psutil.virtual_memory()[2])
#print(a)
client.publish("test/message",cpu.temperature)
#client.publish("test/ram", psutil.virtual_memory()[2])
#client.publish("test/cpu", psutil.cpu_percent())
time.sleep(91)
In this case, with 91s it just prints the value of cpu.temperature every 91s, whereas with a value like 60s, besides printing, it also publishes the value via mqtt every cycle.
Am I doing something wrong here? Or for a longer sleep I need to change my code? I'm running this on a RaspberryPi.
Thanks in advance
EDIT:
I solved modifying the script, in particular how mqtt was handling the timing
here's the new script
mqttc=mqtt.Client("P1")
#mqttc.on_connect = onConnect
#mqttc.on_disconnect = onDisconnect
mqttc.connect("192.168.1.17", port=1883, keepalive=60)
mqttc.loop_start()
while True:
cpu = CPUTemperature()
print(cpu.temperature)
mqttc.publish("test/message",cpu.temperature)
time.sleep(300)
The MQTT client uses a network thread to handle a number of different aspects of the connection to the broker.
Firstly, it handles sending ping request to the broker in order to keep the connection alive. The default period for the keepalive period is 60 seconds. The connection will be dropped by the broker if it does not receive any messages in 1.5 times this value, which just happens to be 90 seconds.
Secondly, the thread handles any incoming messages that the client may have subscribed to.
Thirdly, if you try to publish a message that is bigger than the MTU of the network link, calling mqttc.publish() will only send the first packet and the loop is needed to send the rest of the payload.
There are 2 ways to run the network tasks.
As you have found, you can start a separate thread with the mqttc.loop_start()
The other option is to call mqttc.loop() within your own while loop

implementing a networked multiplayer game loop in twisted

i am working on a game project and i decide to go with twisted for the server part.
its a multiplayer shooting game.
now i want to integrate a main loop into the game (on server side) to process input and physics(for bullets and players).The inputs are recieved from the clients through websockets.
i want the game loop to run game at lets say. 50 fps.
if i follow the method for implementing a game loop mentioned in this atricle. i have this code below
previous = getCurrentTime()
def loop():
double lag = 0.0
while True:
current = getCurrentTime()
elapsed = current - previous
previous = current
lag += elapsed
processInput()
while (lag >= MS_PER_UPDATE):
update()
lag -= MS_PER_UPDATE
send_state_to_connected_clients()
In the article it mentions that:
If you’re making a game that runs in a web browser, you pretty much can’t write your own classic game loop. The browser’s event-based nature precludes it
Now i am having a difficult time understanding it as this applies to Twisted as it's also event based.(i think what it says is the while true statement will block the reactor forever.so what can we do to implement our own loop in twisted given its even based)
in the same article towards the bottom it mentions these points:
Use the platform’s event loop:
1. It’s simple. You don’t have to worry about writing and optimizing the core loop of the game
2. It plays nice with the platform. You don’t have to worry about explicitly giving the host time to process its own events, caching events, or otherwise managing the impedance mismatch between the platform’s input model and yours.
What i am looking for is a general approach towards implementing a game loop in twisted(for a networked multiplayer game).
should i use the inbuilt reactor by using the LoopingCall to call
my Loop? how does then it handles the issues
mentioned in the article.
should i create my own loop somehow? (ex by using threads/processes or some other construct to run the game loop seperate from reactor)
should i create my own reactor implementation somehow?
If I understand the problem accurately, you will have a Python server and players will play a real-time FPS in the browser. You will have to:
display the game in real-time
handle user events in the browser
send browser-event results to the server
parse the results on the server
send server events to the browser
handle server events in the browser
We already know that you are going to use WebSockets.
Display the game in real-time
You will need to display the graphics somewhere, maybe inside a canvas. You will need to implement lots of functions, like update health bar, display changes and so on. These will be triggered when you handle responses from the server.
Handle user events in the browser
If we assume that clicking is shooting, space is activate and so on, you will need some event handlers for those. In the browser you will need a browser-level validation. For instance, if the player intends to shoot, but there is no more ammo, then you do not even have to send a message to the server, maybe display a sound effect of the gun which signifies that shooting was unsuccessful. If, according to the data you have in the browser you have ammo, then the direction you shoot at should be sent to the server.
Send browser-event results to the server
When an event occurs in the browser and is evaluated, then the results in many cases will be sent to the server, which will handle them and eventually send a response to the browser.
Parse the results on the server
The server will have an event loop and will receive WebSocket messages from the browsers of the players. For example if the server receives a shoot event, then it will get the current coordinates of the player and the direction, calculate where the bullet goes and send a message to the players' browser. If someone is hit, then damage is to be calculated and determined whether the player dies, subsequently players will get WebSocket messages from the server and subsequently the sound of the bullet will be displayed along with the bullet's graphical display and potentially some blood, falling players and so on.
Send server events to the browser
The browsers will listen to WebSocket messages from the server and handle those.
Handle server events in the browser
We cannot trust user events, because some cheating could be involved, so when you shoot, the browser will handle the event and the server will receive a message. When the server sends a WebSocket message, the browsers will "believe" that the server sent an accurate response.
Technical needs
You will need a graphics API, user event listeners and WebSocket listeners in the browsers. On the server you will listen to client WebSocket messages.

How to continously integrate (CI) an forever running critical Python application?

I have written a crypto-trading bot in Python which runs 24-7. I want to continuously integrate new features and bug fixes to this app through CI software Jenkins. But the problem is I can't just kill the app, checkout the latest revision and restart the app; because the bot might have active trades to be sold (currently in a trade) at any given time. Killing the app would make the bot loose track of its orders. I was thinking of dumping my active trade data in a database, kill the app, update it, restart it and load the trade data from database to restore the bot's awareness of the trades. But I am not sure if this is best way to do this. Is there a better way to do this?
To sum up.
To save state consider using Redis
Listen to system signals to trigger graceful shutdown like so:
import signal
...
def handler_stop_signals(*args, **kwargs):
""" Handle system signals
only SIGTERM expected to trigger this"""
Log.log(__name__).info('Gracefully shutting down')
my_process.shutdown()
if __name__ == 'main':
signal.signal(signal.SIGTERM, handler_stop_signals)
No need for different process,cli, api. Register a listener and this callback will kick in once the signal is issued.
For more info go here
Then when you want to deploy new version with jenkins, just do your service stop or kill , then deploy and start.

What is the proper way to handle periodic housekeeping tasks in Python/Pyramid/CherryPy?

I have a python web-app that uses Pyramid/CherryPy for the webserver.
It has a few periodic housekeeping tasks that need to be run - Clearing out stale sessions, freeing their resources, etc...
What is the proper way to manage this? I can fairly easily just run a additional "housekeeping" thread (and use a separate scheduler, like APscheduler), but having a separate thread reach into the running server thread(s) just seems like a really clumsy solution. CherryPy is already running the server in a (multi-threaded) eventloop, it seems like it should be possible to somehow schedule periodic events through that.
I was lead to this answer by #fumanchu's answer, but I wound up using an instance of the cherrypy.process.plugins.BackgroundTask plugin:
def doHousekeeping():
print("Housekeeper!")
-
def runServer():
cherrypy.tree.graft(wsgi_server.app, "/")
# Unsubscribe the default server
cherrypy.server.unsubscribe()
# Instantiate a new server object
server = cherrypy._cpserver.Server()
# Configure the server object
server.socket_host = "0.0.0.0"
server.socket_port = 8080
server.thread_pool = 30
# Subscribe this server
server.subscribe()
cherrypy.engine.housekeeper = cherrypy.process.plugins.BackgroundTask(2, doHousekeeping)
cherrypy.engine.housekeeper.start()
# Start the server engine (Option 1 *and* 2)
cherrypy.engine.start()
cherrypy.engine.block()
Results in doHousekeeping() being called at 2 second intervals within the CherryPy event loop.
It also doesn't involve doing something as silly as dragging in the entire OS just to call a task periodically.
Have a look at the "main" channel at http://cherrypy.readthedocs.org/en/latest/progguide/extending/customplugins.html
Do yourself a favour and just use cron. No need to roll your own scheduling software.

Python-Twisted Reactor Starting too Early

I have an application that uses PyQt4 and python-twisted to maintain a connection to another program. I am using "qt4reactor.py" as found here. This is all packaged up using py2exe. The application works wonderfully for 99% of users, but one user has reported that networking is failing completely on his Windows system. No other users report the issue, and I cannot replicate it on my own Windows VM. The user reports no abnormal configuration.
The debugging logs show that the reactor.connectTCP() call is executing immediately, even though the reactor hasn't been started yet! There's no mistaking run order because this is a single-threaded process with 60 sec of computation and multiple log messages between this line and when the reactor is supposed to start.
There's a lot of code, so I am only putting in pseudo-code, hoping that there is a general solution for this issue. I will link to the actual code below it.
import qt4reactor
qt4reactor.install()
# Start setting up main window
# ...
from twisted.internet import reactor
# Separate listener for detecting/processing multiple instances
self.InstanceListener = ListenerFactory(...)
reactor.listenTCP(LISTEN_PORT, self.InstanceListener)
# The active/main connection
self.NetworkingFactory = ClientFactory(...)
reactor.connectTCP(ACTIVE_IP, ACTIVE_PORT, self.NetworkingFactory)
# Finish setting up main window
# ...
from twisted.internet import reactor
reactor.runReturn()
The code is nested throughout the Armory project files. ArmoryQt.py (containing the above code) and armoryengine.py (containing the ReconnectingClientFactory subclass used for this connection).
So, the reactor.connectTCP() call executes immediately. The client code executes the send command and then immediately connectionLost() gets called. It does not appear to try to reconnect. It also doesn't throw any errors other than connectionLost(). Even more mysteriously, it receives messages from the remote node later on, and this app even processes them! But it believes it's not connected (and handshake never finished, so the remote node shouldn't be sending messages, but might be a bug/oversight in that program).
What on earth is going on!? How could the reactor get started before I tell it to start? I searched the code and found no other code that (I believe) could start the reactor.
The API that you're looking for is twisted.internet.reactor.callWhenRunning.
However, it wouldn't hurt to have less than 60 seconds of computation at startup, either :). Perhaps you should spread that out, or delegate it to a thread, if it's relatively independent?

Categories