Skip to main content

Event-Driven Architecture

Overview

OpenRegister implements a comprehensive event-driven architecture built on Nextcloud's IEventDispatcher (PSR-14 compatible). Every mutation across all entity types dispatches a typed PHP event that can be consumed by any Nextcloud app, delivered to external systems via webhooks, or pushed to real-time subscribers via GraphQL SSE.

The architecture distinguishes between:

  • Pre-mutation events (e.g., ObjectCreatingEvent) — implement StoppableEventInterface so hooks can reject or modify operations before persistence
  • Post-mutation events (e.g., ObjectCreatedEvent) — notify downstream systems after persistence is complete

Event Types

Object Events

Event ClassTriggerStoppable
ObjectCreatingEventBefore object insertYes
ObjectCreatedEventAfter successful insertNo
ObjectUpdatingEventBefore object updateYes
ObjectUpdatedEventAfter successful updateNo
ObjectDeletingEventBefore object deleteYes
ObjectDeletedEventAfter successful deleteNo

Pre-mutation events carry the object entity. Update events carry both $oldObject (snapshot before change) and $newObject (the incoming state).

Other Entity Events

Events are dispatched for mutations on all entity types:

EntityEvents
RegisterRegisterCreating/Created/Updating/Updated/Deleting/Deleted
SchemaSchemaCreating/Created/Updating/Updated/Deleting/Deleted
SourceSourceCreating/Created/Updating/Updated/Deleting/Deleted
ConfigurationConfigurationCreating/Created/Updating/Updated/Deleting/Deleted
ViewViewCreating/Created/Updating/Updated/Deleting/Deleted
AgentAgentCreating/Created/Updating/Updated/Deleting/Deleted
ApplicationApplicationCreating/Created/Updating/Updated/Deleting/Deleted
ConversationConversationCreating/Created/Updating/Updated/Deleting/Deleted
OrganisationOrganisationCreating/Created/Updating/Updated/Deleting/Deleted

All entity types follow the same before/after naming convention, giving 39+ typed event classes in total.

Consuming Events

Any Nextcloud app can subscribe to OpenRegister events by registering an event listener in its Application.php:

use OCA\OpenRegister\Event\ObjectCreatedEvent;

$dispatcher->addListener(ObjectCreatedEvent::class, function (ObjectCreatedEvent $event) {
$object = $event->getObject();
// react to the new object
});

Stopping Propagation

Pre-mutation events implement StoppableEventInterface. A listener can reject an operation:

$dispatcher->addListener(ObjectCreatingEvent::class, function (ObjectCreatingEvent $event) {
if (!$this->validate($event->getObject())) {
$event->stopPropagation(); // object will NOT be persisted
}
});

This is the mechanism used by Schema Hooks and reference validation.

Event Payload (CloudEvents v1.0)

When events are forwarded to external systems (webhooks, realtime SSE), payloads conform to CloudEvents v1.0:

{
"specversion": "1.0",
"type": "nl.conduction.openregister.object.created",
"source": "https://nextcloud.example.nl/apps/openregister",
"id": "evt-abc123",
"time": "2026-03-21T12:00:00Z",
"datacontenttype": "application/json",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"register": "meldingen-register",
"schema": "meldingen",
"object": { ... }
}
}

Event Listeners (Internal)

OpenRegister ships 8 internal event listeners in lib/Listener/:

ListenerEventsPurpose
WebhookEventListener55+ events across all entitiesDispatches webhook deliveries
SchemaHookListenerObjectCreating/Updating/DeletingFires synchronous schema hooks
AuditTrailListenerAll object eventsWrites audit trail entries
RelationIntegrityListenerObjectDeleting/UpdatingEnforces referential integrity
GraphQLSubscriptionListenerAll object eventsBridges events to SSE subscription buffer
SearchIndexListenerObjectCreated/Updated/DeletedKeeps Solr/Elasticsearch index current
RetentionListenerObjectCreatedApplies default archival metadata
NotificationListenerAll object eventsEvaluates notification rules

The DeepLinkRegistrationEvent is dispatched during Application::boot(). Consuming Nextcloud apps listen for this event to register URL templates for OpenRegister schema/register combinations. See Deep Link Registry.

Standards

StandardRole
CloudEvents v1.0Webhook and external event payload format
PSR-14Event dispatcher interface (IEventDispatcher)
StoppableEventInterfacePre-mutation rejection mechanism