Initial Setup
TMS Echo replicates data between two or more databases. For TMS Echo to work, every database that will be part of this replication system needs to go through an initial setup process.
1. Update the database schema
TMS Echo saves lots of data in internal tables in the database. Those tables need to be created before you can use TMS Echo in that database.
2. Register Self Node
Each database in the replication system is called a node. A node is actually a concept and the database "becomes" a node when it's registered as a node (when some identity data is saved in some TMS Echo internal tables). This is needed to each database in the replication system has an "Id", so TMS Echo knows how to identify each different database.
3. Create the Echo Server for node communication (optional)
Nodes need to communicate with each other. This communication between the local node and a Remote Node might be a direct database connection or through an Echo server. If your case is the latter, then you need to start up the server.
4. Register Remote Node
Once you have turned all databases into nodes (i.e., registering the self node in each database, giving each of them an Id), you need to make each node know each other. This is done by registering the remote node. In TMS Echo there is no concept as "client/server", just nodes. So when you register a remote node, it just means makes node "A" knows that node "B" exists and vice-versa (a reference to node A is saved in the database B and vice-versa). But usually, you will have a typical client/server setup, where the "client" application/database is the replica of a central server database. So usually, it's the client application that will register itself as a node in the server.
Once you have done the steps above, the ecosystem is set up, and you can then implement the replication process in your application.
Database Schema
For TMS Echo to work it needs some tables to be present in the database schema. It uses those tables to save the nodes, the log of changes, batches, among other things.
It's very easy to create those tables using the TDatabaseManager object provided by TMS Aurelius. You just need to pass the correct TMappingExplorer object to the TDatabaseManager which holds all the mapped classes needed by Echo. Such mapping explorer is available in the TEcho.Explorer class property.
uses {...}, Echo.Main, Aurelius.Engine.DatabaseManager;
var
DB: TDatabaseManager;
begin
// Create needed tables and fields for TMS Echo usage
DB := TDatabaseManager.Create(Echo.Pool.GetConnection, TEcho.Explorer);
try
DB.UpdateDatabase;
finally
DB.Free;
end;
In the example above, the IDBConnection needed by the TDatabaseManager is provided from the connection pool of the TEcho object. This is just for convenience, you can use any IDBConnection just as you use in your TMS Aurelius application.
The above code is enough to create the needed tables in an existing database. If you want to validate the database update, you might get some warnings though, because the updater will indicate that there are already existing tables in the database (the tables used by your application).
If you want to avoid such warnings (which don't affect the update itself, it's just informative), you can mix classes from both mappings: the ones needed by your application, and the ones needed by TMS Echo. To do that, all you have to do is pass an TArray<TMappingExplorer> as the second parameter of the Create constructor, with all explorers you need. For example:
// Create needed tables and fields for TMS Echo usage
DB := TDatabaseManager.Create(Echo.Pool.GetConnection,
TArray<TMappingExplorer>.Create(
TMappingExplorer.Default, // include tables needed by application
TEcho.Explorer // include tables for TMS Echo
);
{...}
Nodes
A node represents a copy (replica) of the database. In other words, in a replication system where you have multiple databases, each database is named a node. Each database has a list of nodes that it knows of including the self node. The self node represents the local database itself, and the other nodes listed in the local database represent the other databases that will replicate with the local one.
Self Node
To define that a database is a node in the replication system, you need to create a node and then define it as the self node. The Echo variable in the example is an instance of a TEcho class.
var
NodeManager: IEchoNodeManager;
begin
{ First thing TMS Echo requires is to define the SelfNode. Each database
in the TMS Echo replication system is known as a "node" and must be
identified. So if the SelfNode of this database is not defined yet, we must do it }
// Get the NodeManager for the local database
NodeManager := Echo.GetNodeManager;
// If SelfNode is already defined, no need to define it again
if NodeManager.SelfNode <> nil then Exit;
// SelfNode is not defined, so let's create a Node instance with the id
// specified by the NodeId variable. It can be any string value, it just needs
// to be unique among all other databases being replicated.
NodeManager.CreateNode('client1');
// Now define this newly created node as the SelfNode
NodeManager.DefineSelfNode(DBName);
Remote Node
Strictly speaking, there is no such "local node" and "remote node". All databases in the replication system are just nodes. But we often refer to a node either as "local" or "remote", and this has a meaning from the programming point of view.
A local node is the node (database) your application is working with, and the database you always have direct access to (a "local" database).
A remote node is a node that you push data to or pull data from, and is represented in TMS Echo by the IEchoRemoteNode interface. It's just another database, but the difference is that the database at remote node can be accessed in two ways:
1. Using a direct database connection
In this case, the application will access the remote database (node) directly, in a client/server manner. To push data to or pull data from the remote node, the application will in essence perform SQL operations directly in the remote database. This is how to retrieve the IEchoRemoteNode interface in this scenario:
var
ServerDatabasePool: IDBConnectionPool;
{...}
RemoteNode := Echo.GetRemoteNode(ServerDatabasePool);
2. Using a Echo server (based on XData)
In this case, the application will communicate with the remote node using an Echo server. To push data to or pull data from the remote node, the application will perform Http requests to the server, which in turn will save/load data in the remote database. This is useful when the remote database is not directly accessible. For this scenario to work, you have to be sure that an Echo server is running at the remote node. This is how to retrieve the IEchoRemoteNode interface in this scenario:
var
RemoteNode: IEchoRemoteNode;
{...}
RemoteNode := Echo.GetRemoteNode('http://serverhost/tms/echo/servernode');
Registering Remote Nodes
Once you have defined the self node for the database, you can register additional remote nodes that represent the database which the local node will exchange data with.
This is needed because when Echo is routing the data, it needs to know to which nodes the data will be routed to. The registration needs to be made just once and it represents a bidirectional communication.
To register the local node in a remote node, you just need to retrieve the IEchoRemoteNode interface and call RegisterNode method:
var
RemoteNode: IEchoRemoteNode;
...
RemoteNode.RegisterNode;
When you do this TMS Echo will:
Create a node entry in the remote database representing the local node. So when routing happens at the remote database server, changes will be routed to local node.
Create a note entry in the local database representing the remote node. So when routing happens at the local database, changes will be routed to the remote node.
Creating the Echo Server
A local node communicates with a remote node via direct database connection or through an Echo server. If you want to have the nodes communicate via the server, you need to be sure the server is running.
The Echo server is just a TMS Sparkle module using the TMS XData technology. You can refer to documentation of both products, mainly TMS Sparkle, to learn more about how to create the server. This is basically what you need to setup (assuming the ConnectionPool variable has a valid reference to an IDBConnectionPool interface):
uses Sparkle.HttpSys.Server, Echo.Server, {...};
{...}
FSparkleServer: THttpSysServer;
FEchoModule: TEchoServerModule;
{..}
FSparkleServer := THttpSysServer.Create;
FEchoModule := TEchoServerModule('http://+:80/myechoserver', ConnectionPool);
FSparkleServer.AddModule(FEchoModule);
FSparkleServer.Start;
The URL for the server in the example is just an example, you should use the one that fits your needs.