Distributed Architecture Guide
Use the Atoti Starter
In a Spring application, the different components used in distribution like the messenger will be automatically created by Atoti starter for Spring Boot com.activeviam.springboot:atoti-server-starter. Import this dependency in your project to perform this injection.
In the context of tests, Atoti comes with the class com.activeviam.atoti.server.test.api.DistributionTestHelper handling this setup. See the specific section for details about its setup and usage.
Configure your application
The first step to define an application is to define a database. This is done like in a non-distributed application (see Database Overview)
The second step is to define the data nodes and the query nodes. Here as an example of a data node definition:
final IActivePivotInstanceDescription datanode =
    StartBuilding.cube("datanode")
        .withSingleLevelDimension("trade")
        // define here the measures and the hierarchies of the data node
        .asDataCube()
        .withClusterDefinition()
        .withClusterId("Cluster")
        .withMessengerDefinition()
        .withProtocolPath("jgroups-protocols/protocol-tcp.xml")
        .end()
        .withApplicationId("app")
        .withConcealedHierarchies(List.of(HierarchyIdentifier.simple("trade")))
        .withConcealedMeasures("Value.SUM")
        .withConcealedBranches()
        .end()
        .build();
withLocalMessenger or the withNettyMessenger methods.
This is the moment to conceal the hierarchies, the measures or the branches if it applies here (see Recommendations)
And of a query node definition:
final IDistributedActivePivotInstanceDescription queryNode =
    StartBuilding.cube("querynode")
        .asQueryCube()
        .withClusterDefinition()
        .withClusterId("Cluster")
        .withMessengerDefinition()
        .withProtocolPath("jgroups-protocols/protocol-tcp.xml")
        .end()
        .withApplication("app")
        .withDistributingLevels(LevelIdentifier.simple("trader"))
        .withApplication("app2")
        .withoutDistributingLevels()
        .end()
        .build();
Once the nodes have been defined, they should be added to a manager:
final IActivePivotManagerDescription manager =
    StartBuilding.managerDescription("MyManager")
        .withCatalog("Catalog")
        .containingAllCubes()
        .withSchema("Schema")
        .withSelection(createSelection())
        .withCube(datanode)
        .withDistributedCube(queryNode)
        .build();
final ApplicationWithDatastore application =
    StartBuilding.application()
        .withDatastore(createDatastoreSchemaDescription())
        .withManager(manager)
        .build();
Leave a cluster
It is possible to join and leave the cluster programmatically like this:
// Join the cluster
((IMultiVersionDataActivePivot) multiVersionActivePivot).startDistribution();
// Leave the cluster
((IMultiVersionDataActivePivot) multiVersionActivePivot).stopDistribution();
If a data node leaves the cluster before sending all the expected query results to a query node, a ServiceUnavailableException is thrown.