Implementation
Multi-Client Synchronization API
The Multi-Client Synchronization API enables DimensionIQ widgets running in separate browser sessions or host applications to stay synchronized in real time.
The API is based on a simple event-driven architecture:
- A widget emits a DIQ_Eventwhen a change occurs.
- The host application publishes the event to a synchronization backend.
- The backend broadcasts the event to connected clients.
- Receiving hosts dispatch the appropriate refresh command back to their widgets.
The synchronization backend acts only as a relay and does not interpret or modify event data.
DIQ_Event
interface DIQ_Event {
name: string;
payload?: string;
}
Widget Event Callback
Widgets notify the host of synchronization events using the optional
callbacks.onEvent({
name: "drawings.changed",
payload: JSON.stringify({
revisionKey: revisionKey
})
});
Events should be emitted only after the underlying operation has completed successfully.
Supported Events
| Event Name | Payload | Description |
|---|---|---|
drawings.changed | Event-specific | Drawing created, updated, deleted, or revised |
groups.changed | Event-specific | Dimension group created, updated, deleted, or recalculated |
dimensions.changed | Event-specific | Dimensions created, updated, or deleted |
group-folders.changed | Event-specific | Dimension group folder created or modified |
Host Event Publishing
Hosts are responsible for publishing events to a synchronization service that can be accessed by all connected clients.
callbacks.onEvent = (event: DIQ_Event) => {
fetch(`${apiBaseUrl}/events`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(event)
});
};
Any transport mechanism may be used, including:
- REST APIs
- Server-Sent Events (SSE)
- WebSockets
- Message brokers
- In-process event buses
Receiving Events
When an event is received from the synchronization backend, the host should dispatch the appropriate refresh command to the widget.
sync.events$.subscribe(ev => {
const scope = ev.payload
? JSON.parse(ev.payload)
: {};
switch (ev.name) {
case "drawings.changed":
bridge.sendCommand(
"refreshDrawings",
scope
);
break;
case "groups.changed":
bridge.sendCommand(
"refreshDimensionGroups",
scope
);
break;
case "dimensions.changed":
bridge.sendCommand(
"refreshDimensions",
scope
);
break;
case "group-folders.changed":
bridge.sendCommand(
"refreshDimensionGroupFolders",
scope
);
break;
}
});
Unknown event names should be ignored to maintain forward compatibility with newer widget versions.
Bridge Refresh Commands
DimensionIQ provides a set of refresh commands that allow a host application to notify a widget that underlying data may have changed.
These commands are typically invoked in response to synchronization events received from other clients. The host deserializes the event payload and forwards it directly to the corresponding refresh command.
bridge.sendCommand(commandName, payload);
The payload is passed through unchanged and is interpreted by the receiving widget. Hosts are not required to understand, validate, or transform the payload contents.
Supported Refresh Commands| Command | Purpose |
|---|---|
refreshDrawings | Refreshes drawing data |
refreshDimensionGroups | Refreshes dimension group data |
refreshDimensions | Refreshes dimension data |
refreshDimensionGroupFolders | Refreshes dimension group folder data |
Behavior Notes
- Refresh commands automatically ignore events that do not apply to the currently active project or revision
- Refresh commands perform no action when no project or revision is loaded
- Event payloads should contain sufficient scope information to allow widgets to determine whether a refresh is required
- Synchronization is designed to minimize data transfer by refreshing only affected data sets rather than reloading the entire application state