Plugin fails to starts when using @webhook annotation (The setup method 'add_url_rule' can no longer be called on the application. It has already handled its first request, any changes will not be applied consistently.)
Describe the bug Plugin fails to starts when using @webhook annotation.
Error message is: (PipelineNotifier is the name of a plugin)
Error: PipelineNotifier failed to activate: PipelineNotifier failed to start : The setup method 'add_url_rule' can no longer be called on the application. It has already handled its first request, any changes will not be applied consistently.
To Reproduce Intermittent behaviour. Happens only for our integration environment. Looks like a race condition. Happens only for particular plugins (not all).
Plugin which has an issue:
class PipelineNotifier(BotPlugin):
PIPELINE_STATUS_COMPLETE: str = "complete"
PIPELINE_STATUS_FAILED: str = "failed"
@webhook("/pipeline/notify")
def pipeline_notify(self, request: dict):
self.log.debug(f"gitlab event: {repr(request)}")
try:
event = PipelineNotifierEvent(contributors=request["contributors"],
notify_users=request["notify_users"],
notify_channel=request["notify_channel"],
project=request["project"],
version=request["version"],
release_version=request["release_version"],
job_url=request["job_url"],
pipeline_status=request.get("pipeline_status", ""),
channels_to_notify=request.get("channels_to_notify", []))
self.handle_pipeline_notifier_event(event)
except KeyError as e:
self.log.debug(f"unexpectedly missing key from object. {repr(e)}")
...
... other internal methods used
Plugin which with no issue:
from errbot import BotPlugin, webhook
from errbot.storage import StoreException
class DevxNotifier(BotPlugin):
@webhook("/devx/notify")
def devx_notify(self, request: dict):
self.log.debug(f"devx notify: {repr(request)}")
try:
self.send_card(to=self.build_identifier(request['channel_name']), link=request['link_url'], title=request['title'], color=request['color'], body=request['body'])
except Exception as e:
self.log.error(f"Error sending card: {e}")
return {"status": "error", "message": f"Error sending card: {e}"}
@property
def is_slack_backend(self) -> bool:
self.log.debug(f"Bot mode configured : {self._bot.mode}")
return self._bot.mode == "slackv3"
def init_storage(self) -> None:
"""work around storage backend bug
There is currently a bug in errbot where init_storage is not
idempotent, but is called multiple times if initialisation fails due to a
spurious error (e.g. slack API rate limiting).
We don't use storage, so we will just ignore errors in initialisation
(which are likely errbot.store.StoreAlreadyOpenError)
"""
try:
super().init_storage()
except StoreException:
pass
Expected behavior No error and plugin is activated
Screenshots If applicable, add screenshots to help explain your problem.
Environment (please complete the following information):
- Errbot version: 6.2.0
- OS version: Debian
- Python version: 3.9
- Using a virtual environment: no
- Using Docker: yes
Additional context As I understand it conflicts intermittently with flask used inside errbot https://github.com/errbotio/errbot/blob/653656d8dd96e84c3b7974bf2cbec30806bd6cdf/errbot/core_plugins/wsview.py#L56
flask_app.add_url_rule(
uri_rule, view_func=callable_view, methods=verbs, strict_slashes=False
)
when errbot server is initialised already and @webhook can not initialise URL once again.
@hiaik could you provide an idea how you are executing the tests or integrations? Are you using the test backend to check the plugins or running a bot and calling web hook endpoints directly?
@sijis
running a bot and calling web hook endpoints directly that is the way.
I deploy errbot to the dev env where I can see that problem always for now. Production env does not have it which makes me thinking it is a race condition.
For the dev env deployment, the error is
...
messageError: PipelineNotifier failed to activate: PipelineNotifier failed to start : The setup method 'add_url_rule' can no longer be called on the application. It has already handled its first request, any changes will not be applied consistently.
...
code of PipelineNotifier is in description.
Therefore, every call to the @webhook("/pipeline/notify") of PipelineNotifier plugin ends with 404 reply
<!doctype html>
<html lang=en>
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
It started only from errbot update to 6.2.0 from 6.1.9 (we also updated dependent lib from requests~=2.27.1 to requests~=2.31.0).
Now when we need to test PipelineNotifier plugin on test env, we downgrade versions:
- errbot to 6.1.9
- requests~=2.27.1
and is working well (plugin loads and starts correctly).