-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Persistent MPDClient #31
Comments
I was thinking about similar issue in my script, which is using mpd module. It is matter of mdp daemon, which disconnect every client afrter some time of inactivity, default period there is one minute and could be configured in mpd.conf via connection_timeout variable. Mpd module throws that exception when trying to write to closed socket after that disconnection. Another invoke of connect method should be enough to issue next commands to mpd daemon.
I've used last way and individually handled that exceptions in my python script, but thinking about future better solution for that.. create proxy object for MPDClient, which will reconnect automatically after throwing that exception. Generally i think, that including that auto reconnect functionality directly into python-mpd2 will be very useful. |
On Tue, Dec 31, 2013 at 5:58 PM, msmucr [email protected] wrote:
Ah, so it's mpd that disconnects the client! I will probably handle the |
In a different library I use/have committed to, the client tries to connect before every send, if no connection is available and returns an error in case of failure after this action. A different solution might be something like a ConnectionError handler, because library user might have different strategies how to recover from an error. Maybe it could even be a combination of both. |
Hello Jörg, i've checked mpd module guts very briefly and thought little bit about its internal exception handling. Currently it is raised mostly at place, where module reads response from server and checking newline at its end. Simple reconnection in possible internal handler wouldn't be enough for recovery at that moment, it would be necessary to repeat last command after successful reconnection and parse response again. So it needed to store all connection details and last commands with arguments to some internal property of MPDClient instance. I haven't tried password protected server yet, but it will also maybe needs another send of password. |
I'm having the same troubles here. We're moving to MPD with Orochi (see dbrgn/orochi#45) and handling this issue in the python-mpd2 library would be the better way in my opinion than to handle it all over our code with try-except blocks. |
You could connect and disconnect every time you send a command. from contextlib import contextmanager
import mpd
HOST, PORT = '127.0.0.1', 6600
client = mpd.MPDClient()
@contextmanager
def connection():
try:
client.connect(HOST, PORT)
yield
finally:
client.close()
client.disconnect()
def queue(path):
with connection():
try:
client.add(path)
except mpd.CommandError:
return 'invalid path'
return 'queued' |
Ah, that would actually be a great workaround in my case. Still, support for persistent connections would be even better. |
As msmucr said, I could add a callback hander in _read_line(), which an application can overwrite. But just resending the last command can be dangerous, because it is unknown in which state the connection broke (it might be that the command was executed, but the connection broke during the response). This will not replace the try-catch statements around all mpd commands. But it will remove some boiler code, because the program does not need to recover from each mpd command. About the persistence connection issue: this could be solved by sending a ping command from time to time. The problem is, that this would be require some kind of event loop or timer, which is not available in every python script. |
I'm having the same problem using mopidy instead of mpd. Traceback (most recent call last): |
So... it there any update & solution for this issue? |
@handsomegui My solution was to do a ping at a regular interval. See line 307 at https://github.com/ways/RadiOS/blob/master/RadiOS.py. Works for me. |
I solved this problem by creating a client class that tries to ping before each command, and if it fails, reestablishes the connection. By pinging first, we avoid bad side-effects from interrupted commands. It uses the 'commands' command to determine which commands are available, and then intercepts any available command function (except for ping, which it uses internally). I've been using it for a few days, and it seems stable. I hope you find it useful. edit moved to its own repo, voila: https://github.com/schamp/PersistentMPDClient/ |
We have now two backends to handle network events better: |
Maybe you'll find the following information interesting:
|
MPD runs on a fairly short client timeout[1], so you actually do *need* to handle disconnects reliably as a matter of course. Since we have the Go library 'watcher' running, and it doesn't seem to be affected by timeouts (probably handles it internally) we can have the watcher connection open until an interesting event happens, at which we actually connect to MPD and fetch the data associated with the event. As such, I've actually been able to remove parallelism, since it's not needed. A much simpler and more robust design. [1] Mic92/python-mpd2#31 (comment)
Are there other reasons, apart from default timeout, that MPD server may break connection? I'm trying to use
|
This is probably related to #64. I solved this using https://piripherals.readthedocs.io/en/latest/piripherals.mpd.html (https://github.com/quantenschaum/piripherals). |
Basically, I try to do the same trick as in the linked code, with forced disconnect/connect on |
For now I've solved the problem by not relying on |
Just guessing here, but |
It is not thread safe. You would need to use a lock around it. |
Yes, locking is one possibility. I used a dedicated thread for calling mpd methods. Instead of locking and calling mpd directly from different threads, I queued calls to mpd in a |
Hi, Cheers, Stephan EDIT:
|
|
Hi, no it doesn't catch it ... (To catch the very first ConnectionError when trying to connect is no problem with 'except ConnectionError:' |
This may actually not be part of this issue, but people may find it useful anyways. Could you @Stephanowicz please post a minimal example to reproduce this? |
Hmm - if You look in the other posts with error messages in this thread You'll see that they all have this If You already have the lib running it's quite simple to reproduce by killing mpd :D ...I'll see if I find time to make a simple example with different try/catches |
Ok, here's a script for testing At first, mpd wil be stopped and then the script tries to connect - this will raise the default ConnectionError Cheers, Stephan
|
I'm writing a web-based front end to MPD. I instantiate and connect MPDClient when my program starts. At first calling commands works fine, but after some time of inactivity,
A further attempt to connect:
Is there a way to avoid the ConnectionError? Will I have to catch the exception and reconnect, or connect and disconnect every time I issue a command?
The text was updated successfully, but these errors were encountered: