扩展 StoryBoard:事件工作器插件

概述

有时需要一种响应 StoryBoard API 事件的方法。这可以通过事件工作器插件来实现,这些插件会在 API 上发生 POST、PUT 或 DELETE 操作时收到通知。插件然后可以决定如何异步处理每个事件,从而不影响 API 的稳定性。

您的工作器将在 storyboard-worker-daemon 启动时被检测到,并创建多个工作器进程。当守护进程在 Rabbit 队列中找到消息时,它会将消息传递给每个已找到的工作器插件的 handle() 函数。

注意:为了使事件工作器插件工作,您的 StoryBoard 配置文件需要包含 enable_notifications = True

事件工作器插件快速入门

步骤 1:使用 setuptools 创建一个新的 Python 项目

这留作练习给读者。不要忘记将 storyboard 作为依赖项包含进去。

步骤 2:实现您的插件

在您的插件的 setup.cfg 中添加一个注册的入口点。名称应合理且唯一

[entry_points]
storyboard.plugin.worker =
     my-worker-plugin = my.namespace.plugin:MyEventWorker

然后,通过扩展 WorkerTaskBase 实现您的插件。您可以注册自己的配置组,请参阅 oslo.config 以获取更多详细信息。

from storyboard.plugin.event_worker import WorkerTaskBase

class MyEventWorker(WorkerTaskBase):

    def enabled(self):
        '''This method should return whether the plugin is enabled and
        configured. It has access to self.config, which is a reference to
        storyboard's global configuration object.
        '''
        return True


    def handle(self, session, author, method, path, status, resource,
               resource_id, sub_resource=None, sub_resource_id=None,
               resource_before=None, resource_after=None):
        """This method takes information about an API event and does
        something with it, for example creating a SubscriptionEvent
        in the database for everyone subscribed to the affected resource.

        :param session: An event-specific SQLAlchemy session.
        :param author: The author's user record.
        :param method: The HTTP Method.
        :param path: The full HTTP Path requested.
        :param status: The returned HTTP Status of the response.
        :param resource: The resource type.
        :param resource_id: The ID of the resource.
        :param sub_resource: The subresource type.
        :param sub_resource_id: The ID of the subresource.
        :param resource_before: The resource state before this event occurred.
        :param resource_after: The resource state after this event occurred.
        """
        if resource == 'timeline_event':
            event = db_api.entity_get(models.TimeLineEvent, resource_id,
                                      session=session)
            subscribers = sub_api.subscription_get_all_subscriber_ids(
                'story', event.story_id, session=session)

            for user_id in subscribers:
                event_info = event.event_info
                db_api.entity_create(models.SubscriptionEvents, {
                    "author_id": author.id,
                    "subscriber_id": user_id,
                    "event_type": event.event_type,
                    "event_info": event_info
                }, session=session)

步骤 3:安装您的插件

最后,安装您的插件,这可能需要您切换到 StoryBoard 的虚拟环境。Pip 应该会自动注册您的插件

pip install my-storyboard-plugin