errbotio / errbot

Errbot is a chatbot, a daemon that connects to your favorite chat service and bring your tools and some fun into the conversation.
http://errbot.io
GNU General Public License v3.0
3.12k stars 612 forks source link

StoreAlreadyOpenError("Storage appears to be opened already") #1586

Closed mmclane closed 2 years ago

mmclane commented 2 years ago

Need help with

Issue description I am writing my first real errbot plugin. This plugin looks up the name of the person currently oncall in pagerduty. I want to set it up so that this runs repeatedly and the plugin remembers who it last saw. Then if that person changes it will send a message letting us know the new person is onall.

I have the code largely written but am having issues with this fuction:

    @botcmd    
    def pagerduty_activate(self, msg, args):
        super().activate()
        self.start_poller(5, self.pagerduty_repeating)

If I don't include the super().activate(), the poller doesn't seem to run.
When I include the super().activate() line and run the function I get the following error.

An error happened while processing a message ("!pagerduty activate"): Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/errbot/core.py", line 574, in _execute_and_send
    reply = method(msg, match) if match else method(msg, args)
  File "/errbot/plugins/pagerduty/pagerduty.py", line 72, in pagerduty_activate
    super().activate()
  File "/usr/local/lib/python3.10/site-packages/errbot/botplugin.py", line 454, in activate
    super().activate()
  File "/usr/local/lib/python3.10/site-packages/errbot/botplugin.py", line 212, in activate
    self.init_storage()
  File "/usr/local/lib/python3.10/site-packages/errbot/botplugin.py", line 205, in init_storage
    self.open_storage(self._bot.storage_plugin, self.name)
  File "/usr/local/lib/python3.10/site-packages/errbot/storage/__init__.py", line 32, in open_storage
    raise StoreAlreadyOpenError("Storage appears to be opened already")
errbot.storage.StoreAlreadyOpenError: Storage appears to be opened already

I get the same error when I run this locally or in a container on my k8s cluster.

Steps to reproduce You can see my entire bot and setup here: https://github.com/mmclane/gir The plugin in question is: https://github.com/mmclane/gir/tree/main/plugins/pagerduty

Environment (please complete the following information):

Additional info If you have any more information, please specify it here.

nzlosh commented 2 years ago

For anyone who may come across this issue in the future, the answer was provided by @marksull via gitter.

@mmclane you shouldn't be doing the super().activate in your pagerduty_activate() method because activate() would have already been called when the plugin loaded. The only time you would want to do the super().activate() is if you were overriding activate with your own implementation, for example, if you wanted to call your_method every 60 seconds and wanted to start this as soon as the plugin was started.

def activate(self):
super().activate()
self.start_poller(60, self.your_method, 1)
mmclane commented 2 years ago

Removing the super().activate() allows the function to run but I don't see the results of the function stated in the start_poller function. For example, I have this plugin:

from datetime import datetime
from errbot import BotPlugin, botcmd

class Callback(BotPlugin):
  @botcmd
  def test_activate(self, msg, args):
    self.start_poller(60, self.test_callback)  # callbacks every minute

  @botcmd
  def test_callback(self, msg, args):
    now = datetime.now().time().strftime('%H:%M:%S')
    yield now

Here is my output after multiple minutes.

[@CHANGE_ME ➡ @errbot] >>> !plugin reload Callback
Plugin Callback reloaded.

[@CHANGE_ME ➡ @errbot] >>> !test callback
08:07:02

[@CHANGE_ME ➡ @errbot] >>> !test activate

[@CHANGE_ME ➡ @errbot] >>> !test callback
08:09:52
marksull commented 2 years ago

Alright, so a few things...

1) The log will be your friend. I suspect if you check the log you will be seeing an exception when the poller calls your method.

2) You are calling start_poller with the test_callback method but providing no additional arguments. Because you wrapped test_callback with a @botcmd decorator, the method definition expects msg and args to be passed, but your start_poller is not providing either. Two solutions here:

a) start the poller with the extra args self.start_poller(60, self.test_callback, None, None), b) add defaults to your method definition def test_callback(self, msg=None, args=None)

3) Because the poller is manually triggering the method, there is NO msg associated with the call, so you will need to manually construct a message rather than yield a response.

The way I normally implement my poller methods is to separate them from botcmd like so:

class Callback(BotPlugin):

    def activate(self, msg, args):
        super().activate()
        self.start_poller(60, self.test_poller) 

    def test_poller(self):
        now = datetime.now().time().strftime('%H:%M:%S')
        room = self.query_room("the room where you want this message to go")
        self.send(room, f"Poller was run at: {now}"

    @botcmd
    def test_callback(self, msg, args):
        test_poller()
nzlosh commented 2 years ago

Mark's spot on. Small side note, the @botcmd shouldn't decorate activate since it's not intended to be a bot command. The example already points out the use of self.send for bot initiated messages and you can see other examples of messaging here https://errbot.readthedocs.io/en/latest/user_guide/plugin_development/messaging.html

marksull commented 2 years ago

Thanks for catching my type @nzlosh

mmclane commented 2 years ago

So you put super().activate() in your activate function.. but I just removed that.

mmclane commented 2 years ago

Ah.. but its not decorated either..

marksull commented 2 years ago

So you put super().activate() in your activate function.. but I just removed that.

Read up on Python inheritance/supers. That is a Python thing not an Errbot thing.

mmclane commented 2 years ago

Thank you all for your help. I believe I have this all sorted out. If your interested you can follow the link to my git repo to see my solution.