diff --git a/doc/source/extending/index.rst b/doc/source/extending/index.rst index 00b78139..07814d81 100644 --- a/doc/source/extending/index.rst +++ b/doc/source/extending/index.rst @@ -92,5 +92,5 @@ thread which will not impact the stability of the API:: storyboard.plugin.worker = my-plugin-worker = my.namespace.plugin:EventWorker -To learn how to write a user preference plugin, please contribute to this -documentation. +To learn how to write an event worker plugin, `read more here +<./plugin_worker.html>`_. diff --git a/doc/source/extending/plugin_worker.rst b/doc/source/extending/plugin_worker.rst new file mode 100644 index 00000000..7ada986a --- /dev/null +++ b/doc/source/extending/plugin_worker.rst @@ -0,0 +1,99 @@ +========================================== +Extending StoryBoard: Event Worker Plugins +========================================== + +Overview +-------- + +It is sometimes useful to have a method to react to StoryBoard's API events. +This can be done using Event Worker plugins, which recieve a notification +whenever a POST, PUT, or DELETE action occurs on the API. The plugin can then +decide how to process each event asynchronously so as not to impact the +stability of the API. + +Your workers will be detected by `storyboard-worker-daemon` when it starts, +and a number of worker processes will be created. When a daemon finds a +message in the Rabbit queue, it passes the message to the handle() function +of each worker plugin it has found. + +Note: In order for event worker plugins to work, your StoryBoard config file +will need to contain `enable_notifications = True`. + +Event Worker Plugin Quickstart +------------------------------ + +Step 1: Create a new python project using setuptools +#################################################### + +This is left as an exercise to the reader. Don't forget to include storyboard +as a requirement. + +Step 2: Implement your plugin +############################# + +Add a registered entry point in your plugin's `setup.cfg`. The name should be +reasonably unique:: + + [entry_points] + storyboard.plugin.worker = + my-worker-plugin = my.namespace.plugin:MyEventWorker + +Then, implement your plugin by extending `WorkerTaskBase`. You may register +your own configuration groups, please see +`oslo.config `_ +for more details.:: + + 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) + + +Step 3: Install your plugin +########################### + +Finally, install your plugin, which may require you switch into storyboard's +virtual environment. Pip should automatically register your plugin:: + + pip install my-storyboard-plugin diff --git a/doc/source/index.rst b/doc/source/index.rst index 1bcf78fe..0205b423 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -57,6 +57,7 @@ Extending StoryBoard Overview Plugins: Cron Workers + Plugins: Event Workers Client API Reference