Custom Actors
Custom Actors are Actor classes that support type definitions. Therefore, developers can extend and customize them to model any kind of business object.
Although Hantera has several Actor classes, the only custom actors are Asset and Ticket. The Order, Payment, and Sku actors are designed for specific use cases. For instance, Order can only model data such as orders, invoices, and deliveries. So, it lacks the flexibility to represent data outside of its scope.
In contrast, the Asset and Ticket actors generalize well to custom data. Through Type definitions, developers can define custom Actor types, subtypes, and relations in the Registry. For example, Ticket can have Support, RMA, Complaint, and Shipment Ticket types.
Custom Actors are important because they:
- Support custom types which can model any business data
- Accurately model custom business objects that don’t fit special-use actors
- Extend the Graph by creating more nodes and edges to map data relationships
Key Features of a Custom Actor
Custom Actors model general business objects because of the following features:
1. Type Key
The type key is a unique global name that points to a type’s node in the Graph. It is used to create and query instances of a type.
2. Items
An Item is an arbitrary entity that acts like a subtype of a type. In the Graph, an Item is a node that maps to a specified type. A custom Actor may have many types of Items. It can also have many instances of each Item. Just like the main Actor, each Item must have a type key. In addition, it may have Relations with other nodes too.
3. Relations
A custom type can define Relations to other nodes in the Graph. Each Relation will manifest as an edge to the related nodes. This means that a custom Actor’s related Graph node may contain Edges not normally supported by the Actor. Items can also define Relations, allowing for complex and accurate modeling of business data.
While the Actor’s main Graph node automatically generates Edges for the Actor’s typed Items, Relations could be added between types of Items as well. See the example below.
How to create Items and Relations
Create Items and Relations by sending a Message to a custom Actor. The applyCommands message mutates the state of Asset and Ticket Actor instances by applying the specified methods to them.
Valid commands used to create and modify Items and Relations are the following (these links point to the Ticket version of these commands, but they are identical with other Actors):
How Custom Actors Extend the Graph?
The Graph is a separate read-only representation of data in Hantera. It mirrors Actor types and relationships with other entities, and automatically generates nodes and edges based on type definitions in the Registry.
A custom Actor is represented as a node in the Graph. Once a new Asset/Ticket Type is defined in the Registry, the Graph generates a new node. For example, a Ticket type defined as shipment will get a node shipment with node name as ticket.shipment. Therefore, shipment acts as a unique and global name in the Graph and Portal, while ticket.shipment is used for querying the node and defining custom Graph fields.
As seen above, each type can have Items and Relations attached to it. If an Item, package, is added to shipment, the Graph generates a new node package with node name ticket.shipment.package. A new edge named package is attached to the main node.
Relations are likely named. For example, if shipment type has an order relation named orders, the ticket.shipment node will have an edge called orders.
In short:
| Entity | Convention |
|---|---|
| Actor nodes | <base set>.<typeKey> |
| Item nodes | <base set>.<typeKey>.<itemTypeKey> |
| Relation edges | <base set>.<relationKey> |
| Inverse relation edges | <base set>.<typeKey>[.<itemTypeKey>] |
Since all the nodes and edges are generated from type definitions, the Graph is a read-only mirror representation of data models. Therefore, you can query the Graph but cannot modify it. That way, you always get an accurate representation of your data.
Access Control
Access control of custom nodes are based on the base node and refined using
ABAC. The attribute is typeKey and an identity needs
a matching access attribute.
For example, an identity with attribute-limited ACE typeKey@graph/ticket:query can only query tickets where it has
a matching value for the typeKey access attribute.
How to Define a Custom Actor Type?
Actor Type definitions are sent through YAML files to the Registry. The paths for the definitions also depend on the Actor. The convention looks like this: actors/<actor>/types/<typeKey>
Schema
Set the following properties in the YAML file when creating a new Type:
Type Definition Schema
graphSetName | string (required) Global name of the graph root node where actor type is contained. |
itemEdgeName | string (optional, required if Items defined)Name of the edge in the graph pointing an item to main actor type. |
defaultNumberPrefix | string (optional) For Actors that have auto-increment natural keys (most data-focused Actors), this determines the default number prefix to use. If not specified, the Actor’s default prefix will be used. This is useful when different types should have different number series. |
items | map of string to Item Definition Schema (optional) The Item types that are allowed on this Type. |
relations | map of string to Relation Schema (optional) The Relations that are allowed on this Type. |
Item Definition Schema
relations | map of string to Relation Schema (optional) Zero or more Relations Schemas |
graphSetName | string (required) Global name of the graph node where Item is contained. |
edgeName | string (required) Name of the edge of the Item. |
Relation Definition Schema
node | string The name of the Node allowed in this Relation. |
cardinality | ’single’ or ‘many’ Whether the relation allows one or more relations. This will be enforced by the Actor upon creating Relations. |
inverseName | string (optional) An additional identifier to add to the inverse edge. Optional if there’s only one Relation between the same nodes, otherwise required for all but one Relation. |
Common Type Definition Errors
The Registry doesn’t enforce schema upon writing. This means that if you incorrectly type a Custom Actor, the Registry may pick it up regardless. Fortunately, you can use the a CLI command, h_ manage signals to check if there were any errors.
Still, common pitfalls to avoid include:
- not setting
graphSetNamefor every Actor type and Item - not setting
itemEdgeNameandedgeName, where required - Including numbers in the
defaultNumberPrefixvalue. The prefix must only be alphabets.
Example: Define a Shipment Ticket Type
Let’s say you want to model a shipment containing a delivery being shipped to a customer. A shipment has a limited lifespan, so this makes Ticket Actor the best option.
In this example, shipment will contain items package and event, as well as have order and delivery relations. We will store events for each package as well as Shipment-specific events (common for all packages).
To model this, we will apply the following manifest:
uri: /registry/actors/ticket/types/shipmentspec: value: graphSetName: shipment itemEdgeName: head defaultNumberPrefix: "SHIP" items: event: graphSetName: event edgeName: edgeEvent relations: package: node: 'ticket.shipment.package' cardinality: single package: graphSetName: package edgeName: edgePackage relations: delivery: node: delivery cardinality: singleIt’s important to note that while Relations are bi-directional in the Graph, the Relation is controlled by the entity that defines it. So we can’t add an event to a package in the above case. Instead we must add the package to the event.