clotho/docs/OBJECT_BOUNDARY.md
2026-05-15 00:09:01 +02:00

4.9 KiB

Object Boundary

What Is the Object Boundary?

Clotho has no lazy loading. When you call session.load(Employee.class, rid), you receive the fully assembled object — root vertex plus everything within its declared boundary — in one operation. Nothing is deferred.

The object boundary is the set of edges and vertices Clotho traverses and assembles when loading a @VertexType instance. It is declared entirely in the Java class using @Include and @Via. Everything outside the boundary is accessed via @Query traversals written by the developer.


Declaring the Boundary: @Include and @Via

@VertexType("Order")
public class Order extends ClothoVertex {
    String status;

    @Include @Via("HAS_LINE")
    List<OrderLine> lines;

    @Include @Via("HAS_BILLING_ADDRESS")
    Address billingAddress;
}
  • @Include marks the field as part of this object's boundary.
  • @Via specifies the ArcadeDB edge label to traverse.
  • The field type determines what is loaded (see below).

Both annotations are required together. @Include without @Via is a compile-time error.


What Gets Loaded: Field Type Rules

Field type is a @VertexType class

Clotho traverses the edge, loads the target vertex (and its own boundary recursively), and discards the edge itself (edge properties are not available).

@Include @Via("HAS_BILLING_ADDRESS")
Address billingAddress;  // Address is a @VertexType; edge properties ignored

Field type is an @EdgeType class

Clotho loads the full edge object — edge properties, plus @OutVertex and @InVertex fields if declared on the edge class.

@Include @Via("HAS_LINE")
List<OrderLineEdge> lines;  // OrderLineEdge is an @EdgeType; edge props + vertices loaded

Edge-only inclusion (no @InVertex on the edge class)

When the @EdgeType class declares no @InVertex field, the target vertex is not fetched. Useful when you need the edge's own properties but not the vertex it points to.

@EdgeType("TAGGED_WITH")
public class TagEdge extends ClothoEdge {
    @OutVertex Order order;
    // No @InVertex — Tag vertex is never loaded
    String tagValue;
    int weight;
}

// In Order:
@Include @Via("TAGGED_WITH")
List<TagEdge> tags;  // Only edge properties; Tag vertices stay in the DB

Edge Direction

Default direction is OUT (follow outgoing edges from the current vertex). Override per field with @Direction:

@Include @Via("ASSIGNED_TO") @Direction(Direction.IN)
List<Task> assignedTasks;  // follow INCOMING ASSIGNED_TO edges to find tasks

@Include @Via("CONNECTED") @Direction(Direction.BOTH)
List<Node> neighbors;  // follow edges in both directions

The global default can be changed in session factory configuration:

clotho.default-direction=OUT

Multi-Hop Boundaries

@Include is applied recursively. If OrderLine itself has @Include fields, they are loaded as part of loading Order.

@VertexType("Order")
public class Order extends ClothoVertex {
    @Include @Via("HAS_LINE")
    List<OrderLine> lines;       // hop 1
}

@VertexType("OrderLine")
public class OrderLine extends ClothoVertex {
    int quantity;
    BigDecimal unitPrice;

    @Include @Via("HAS_NOTE")
    List<Note> notes;            // hop 2 — loaded as part of Order
}

Loading an Order traverses: Order → HAS_LINE → OrderLine → HAS_NOTE → Note.

There is no depth limit. The developer is responsible for designing boundaries that do not load unbounded portions of the graph.


Cycle Detection

Clotho tracks visited ARIDs during a boundary load. If a traversal reaches a vertex it has already loaded in the current operation, it uses the existing instance and stops traversing further — it does not loop. The developer still bears responsibility for not creating boundaries that load huge subgraphs.


Persistence of Boundary Elements

When session.save(order) is called:

  1. The root Order vertex is upserted (created if ARID is null, updated if set).
  2. Each @Include field is recursively persisted in the same way.
  3. Elements reachable via multiple paths are saved exactly once (identity map deduplication).
  4. Removed items are NOT automatically deleted. If you remove an OrderLine from order.lines, calling save() does not delete the OrderLine vertex or its edges. Call session.delete(orderLine) explicitly.

Design Guidance

The boundary should reflect ownership, not just connectivity. Include elements that:

  • Are always loaded and managed together with the root
  • Are not meaningful without the root (e.g., OrderLine without Order)
  • Form a bounded transaction unit

Do NOT include:

  • Large, unbounded collections (e.g., all products a customer ever bought)
  • Elements that are independently meaningful and queried on their own
  • Elements reachable via long traversal chains across the domain

For everything outside the boundary, write a @Query on a @ClothoRepository interface.