Description
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
errbot/errbot/core_plugins/wsview.py
Line 56 in 653656d
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.