Skip to content

Event API Implementation #12

Open
Open
@cuebit

Description

@cuebit

This topic is open to consider implementation of the Event API, how best to proceed in designing such implementation that will continue to endure through future releases while being supportive of authors of the Vuex ORM ecosystem.

Global Events

As it stands, the @latest release observes selection and mutation hooks. These hooks are triggered on a singleton (the Query class) and accumulated from the models by way of declarative static methods.

The behaviour for event handling will need to change considering Query is no longer a singleton and potentially out-of-scope for such a requirement. However, global hooks still require a singleton for global event listening/broadcasting.

One suggestion being that the database instance, given it is a singleton in instance form and easily accessible, could be a point of listening/emitting. For example:

store.$database.on('query:beforeSelect', handler)

The benefit of this pattern enables event scoping by prefix (in string representation). This is purely for emitting and subscribing to an event. Models can still declare static methods.

Naming Convention

The subject of normalizing or changing the naming convention for these hooks internally are also up for debate. By internally we mean the name of events emitted rather than the method names bound to a model since these model methods do not subscribe to events directly, rather they are declared as reference handlers.

Selection Hooks

The current selection hooks are: beforeSelect, afterWhere, afterOrderBy and afterLimit.

Selection hooks pass a collection of models tappable for mutation to which a query instance is currently processing.

Mutation Hooks

The current mutation hooks are: beforeCreate, afterCreate, beforeUpdate, afterUpdate, beforeDelete and afterDelete.

Mutation hooks pass the model in the current iteration queue for persistence. Should a models handler return false, the model is skipped and not persisted.

Design Limitations

The crux with event handling is that it is stateless therefore a broadcasted event shouldn't be required to read, let alone expect, a response from subscribers – which proves problematic if events such as beforeCreate or beforeSelect may be required to return. The overhead caused by evaluating a response on each model that's listening inclusive of any additional subscribers to the event is cause for concern. In addition, the @latest release already possesses quantitive performance degradation and @next, at the time of writing, has no performance tests in place to verify any improvement on that front. So it's debatable how taxing this may still be.

For that reason, it's worth considering how to proceed with an idiomatic and synchronous Event API. For example, we may well continue to support return values from event handlers, consequently taking the natural hit on performance. Or we decide to cut ties with this approach and leave it down to user-land logic to process data before asking Vuex ORM to persist it.

Ecosystem

The Event API in its current form also works in favour of plugin authors. Not only can the Events API be integrated on objects that extend it, emitting internal events can enable plugin authors to tap into points for plugin logic. This isn't something we necessarily need to give too much thought, since plugin authors will often circumvent default behaviours through monkey-patching, but can grow as required for non-public logic.

Adding to this, plugins can leverage and adapt the Event API for its own use, rather than “bring your own” functionality which further bears weight on an application using assistive plugins.

Discuss.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions