chore: remove gevent runtime dependency#343
Conversation
There was a problem hiding this comment.
Code Review
This pull request removes the gevent runtime dependency from the Dify Plugin SDK and its examples, transitioning the codebase to use standard blocking sockets and native threading. Key modifications include removing gevent monkey patching, updating worker configurations, and simplifying the server implementations for serverless, stdio, and TCP modes. The review feedback identifies a missing errno import in the TCP request reader that would cause a NameError, recommends using a production-grade WSGI server instead of the Flask development server, and suggests avoiding global signal handlers in library classes to prevent unexpected side effects in consuming applications.
| except BlockingIOError as e: | ||
| if native_socket.socket is gevent_socket.socket: | ||
| if e.errno != errno.EAGAIN: | ||
| raise | ||
| sleep(0) | ||
| continue | ||
| else: | ||
| if e.errno != errno.EAGAIN: | ||
| raise | ||
| continue |
There was a problem hiding this comment.
The errno module is used here but it is not imported in this file, which will cause a NameError if a BlockingIOError is caught. Furthermore, since the socket is now a standard blocking socket (created via socket.create_connection), BlockingIOError is unlikely to occur. If you wish to keep this block for defensive purposes, you should either import errno or simplify the exception handling as shown in the suggestion.
except BlockingIOError:
continue| self.app.run( | ||
| host=self.host, | ||
| port=self.port, | ||
| threaded=True, | ||
| use_reloader=False, | ||
| ) |
There was a problem hiding this comment.
The Flask.run() method uses the built-in Werkzeug development server, which is not suitable for production environments due to security and performance limitations. Since the gevent-based WSGIServer was removed, consider using a production-grade WSGI server like waitress or gunicorn if this component is intended to serve requests in a production-like environment.
| self.opt_lock = Lock() | ||
|
|
||
| # handle SIGINT to exit the program smoothly due to the gevent limitation | ||
| signal.signal(signal.SIGINT, lambda *_args, **_kwargs: os._exit(0)) |
There was a problem hiding this comment.
Setting a global signal handler for SIGINT using os._exit(0) in the constructor of a library class is generally discouraged. It can have unexpected side effects on the application using the SDK and prevents Python from performing graceful cleanup (e.g., running finally blocks or object destructors). Consider letting the application handle signals or using a more graceful shutdown mechanism.
Summary
Validation
Note: requested base
mediumis not present as a branch in this repository, so this PR targetsmainafter rebasing on latestorigin/main.