Interfaces used for replication of tables from a server or table provider to a client. On the client side the table will be written into a local database. On the server side the table could be anything. The replication relies on a underlying websocket connection which provides JsonApi for message exchange.
The libraries for the replicator (client) and publisher (server), cover the following features:
File | common/interface/replication.h |
Classes |
IReplicator UReplicator IPublisher UPublisher |
class IReplicator : public UJsonApiContext {
public:
virtual ~IReplicator() {};
virtual void Update(const char * domain, const char * instance, const char * guid = 0, ulong64 usn = 0) = 0;
virtual void AddColumn(const char * remote, const char * local, enum ReplicationType type, bool update) = 0;
virtual class IReplicatorArray * AddArray(const char * remote, const char * local, bool update, const char * reference) = 0;
virtual void Initialize(const char * row) = 0;
virtual void Added(ulong64 id) = 0;
virtual void Deleted(ulong64 id) = 0;
virtual void DeletedConfirm(ulong64 id) = 0;
virtual void DeletedConfirm(ulong64 id, ulong64 usn, const char * columns) = 0;
virtual void Updated(ulong64 id, ulong64 mask=0xffffffffffffffffLL) = 0;
virtual void Start() = 0;
virtual void Stop() = 0;
static class IReplicator * createReplicator(class UReplicator * user, const char * remote, const char * domain, const char * instance, const char * domainProperty, const char * instanceProperty, class IDatabase * database, const char * local, bool add, bool del);
static class IReplicator * createReplicator(class UReplicator * user, const char * remote, const char * domain, const char * instance, const char * guid, ulong64 usn, const char * domainProperty, const char * instanceProperty, bool columnInfo, class IDatabase * database, const char * local, bool add, bool del);
};
The IReplicator function is the virtual interface class returned when creating the replicator. The public interface functions of this class are called to perform any operations.
This functions is called to create the replicator as part of the initialization.
class UReplicator * user | Use the UReplicator class as base class of one of your classes. The virtual functions of this class are called so signal events from the replicator the the user of the replicator. |
const char * remote | The remote table name, used to publish the table. This name is used inside the replication protocol as "api" property. |
const char * domain, instance | If the App Service can receive AppWebsocket connections from multiple domains and instances, these parameters can be used to only use matching connections for the replication. |
const char * guid, ulong64 usn | This information is used to determine at which point the replication has to start. The guid identifies the remote database. This is used to verify that the connection is still to the same database. If this information does not match a full replication has to be done. The usn indicates at what last change the replication has to start. If the server determines that not all change information is available from this point also a full replication is done. |
const char * domainProperty, instanceProperty |
The name of the properties used to send domain and instance in the message
which is used to decide, that this AppWebsocket connection can be used for
replication. Note: Use "domain" for domainProperty and "pbx" for instanceProperty to replicate from an innovaphone PBX |
bool columnInfo | Set this paramter to true to receive a Json string with column information on the ReplicatorAdded, ReplicatorDeleted. ReplicatorDeletedConfirm, ReplicatorDeletedConfirmComplete and ReplicatorUpdated callbacks. If the parameter is false a null pointer is passed instead. |
class IDatabase * database | The database pointer |
const char * local | The name of the local database table, into which the remote table is replicated |
bool add | If true, the replicator announces that it may add to the replicated table. If this is not possible on the publisher of the table, the replication won't start. |
bool del | If true, the replicator announces that it may delete from the replicated table. If this is not possible on the publisher of the table, the replication won't start. |
For this to work, the AppInstance class needs to use JsonApiContext as base class.
class <Your App Name>> : public AppInstance, ... , public JsonApiContext
After createReplicator is called the interface has to be registered in the JsonApiContext
replicator = IReplicator::createReplicator(this, ...);
RegisterJsonApi(replicator);
When an AppWebsocket connection is established, which may be used for the replication, this AppWebsocket connection needs to be added to the JsonApiContext:
class <Your App Session>> : ..., public AppWebsocket, ... {
// when receiving a message indicating this session is used for replication
class JsonApi * jsonApi = <App Instance class>->CreateJsonApi(<Table Name>, this, msg, base);
if (jsonApi) jsonApi->JsonApiStart();
Function may be called to update domain, instance, guid and usn (see creatReplicator). The replication is restarted when this function is called
After the replicator is created, the columns which should be replicated must be configured. This is done by calling AddColumn for each column.
const char * remote | The column name under which it is published |
const char * local | The local database column name |
enum ReplicationType type |
|
bool update | The replicator user may update this column |
An column in the table can consist of an array of objects. This array is added with the AddArray function the same way as simple elements are added with AddColumn. The array of objects is represented as table with columns, with each elemnt of the object as column.
const char * remote | The column name under which it is published |
const char * local | The local database column name |
bool update | The replicator user may update this column |
const char * reference | The name of the column in the database table used for the join to a column of "id" in the array table. |
Called to initialize the local database table. Must be called, after the replicator is created and all columns are added. The UReplicator::Initialited function is called when the initialization is complete.
const char * row |
The Initialize creates a database table "replicator_full", which is used to
store the replicated rows after the initial full replication, so that the
rows not present on the publisher anymore can be deleted. This table has a
column "id" as unique id and uses the column "row" to link to the replicated
table. The argument row is the SQL defintion used for the column.
Example: "BIGINT REFERENCES users(id) ON DELETE CASCADE NOT NULL" |
Called when a row was added to the local table, so that the replicator can replicate the change to the publisher
ulong64 id | The id of the row added |
Called when a row is to be deleted locally, so that the replicator can replicate the deletetion to the publisher. The actual database delete should be done after the DeletedConfirm callback
ulong64 id | The id of the row to be deleted |
Call to acknowlegde an incoming Deleted call. Only after the DeletedConfirm call the row is deleted from the table.
ulong64 id | The id of the row to be deleted |
ulong64 usn | The squence number of the deleted row. This information should be echoed back from the ReplicatorDeleted call. |
const char * columns | A Json datastructure containing the columns of the deleted row. The information may not the complete information as before the delete. Only the first column may be available. |
Called when a row was updated in the local table, so that the replicator can replicate the change to the publisher
ulong64 id | The id of the row updated |
Call to start the replicator after it was stopped. After initialization the replicator is started automatically, so there is no need to call Start.
Call to stop the replicator
class UReplicator {
public:
virtual void ReplicatorInitialized() = 0;
virtual void ReplicatorAdded(ulong64 id) = 0;
virtual void ReplicatorAdded(ulong64 id, ulong64 usn, const char * columns) {};
virtual void ReplicatorDeleted(ulong64 id) = 0;
virtual void ReplicatorDeleted(ulong64 id, ulong64 usn, const char * columns) {};
virtual void ReplicatorDeletedConfirm(ulong64 id) = 0;
virtual void ReplicatorDeletedConfirm(ulong64 id, ulong64 usn, const char * columns) {};
virtual void ReplicatorDeletedConfirmComplete(ulong64 id) = 0;
virtual void ReplicatorDeletedConfirmComplete(ulong64 id, ulong64 usn, const char * columns) {};
virtual void ReplicatorUpdated(ulong64 id, ulong64 mask) = 0;
virtual void ReplicatorUpdated(ulong64 id, ulong64 usn, const char * columns) {};
virtual void ReplicatorSessionInitializing() {}
virtual void ReplicatorSessionStarted(const char * guid) {};
virtual void ReplicatorSessionInitialized() {}
virtual void ReplicatorSessionClosed() {}
virtual void ReplicatorStopped() = 0;
virtual void ReplicatorUpdate(class json_io & msg, word base, bool initial) {};
virtual void ReplicatorStart(class json_io & msg, word base, char * & tmp) {};
};
Called when replicator initialization is complete
Called when a row was added by the replicator
ulong64 id | The id of the row added |
ulong64 usn | If not 0, this value should be saved. |
const char * columns | column information as a Json datastructor it columnInfo was set in createReplicator, should be echoed back to the DeleteConfirm call. |
Called when a row was deleted on the publisher. Locally the row is deleted only after DeletedConfirm is called. If id is already 0, the row is deleted locally already, so no DeleteConfirm should be called.
ulong64 id | The id of the row deleted. If this is not 0, the DeletedConfirm function should be called to start the deletion in the database. |
ulong64 usn | If id is 0, the row is deleted already. In this case the usn, shall be saved locall to start replication at this usn the next time. |
const char * columns | column information as a Json datastructor it columnInfo was set in createReplicator |
Called when a row can be deleted locally after a Deleted was called. The function DeleteConfirm of the replicator should be called to start local deletion of the row.
ulong64 id | The id of the row deleted |
ulong64 usn | The received usn, should not be saved, but echoed back to the DeletedConfirm call. |
const char * columns | column information as a Json datastructor it columnInfo was set in createReplicator, should be echoed back to the DeleteConfirm call. |
Called when a row was deleted locally after a DeletedConfirm call
ulong64 id | The id of the row deleted |
ulong64 usn | If not 0, this value should be saved. |
const char * columns | column information as a Json datastructor it columnInfo was set in createReplicator, should be echoed back to the DeleteConfirm call. |
Called when a row was updated by the replicator
ulong64 id | The id of the row deleted |
ulong64 mask | A 1 is set in this value for each updated column, with the bit position beeing the position of the column in the AddColumn calls. |
ulong64 usn | If not 0, this value should be saved. |
const char * columns | column information as a Json datastructor it columnInfo was set in createReplicator, should be echoed back to the DeleteConfirm call. |
Indicates that the replicator is waiting for a matching AppWebsocket connection
Indicates the a ReplicateStartResult was received and the initial replication started.
Indicates that the initial replication is complete
Indicates that the replication AppWebsocket connection was closed and the replicator is waiting for a matching AppWebsocket connection
Called when stopping of the replicator is complete after call to Stop().
Callback to add custom arguments to the ReplicateStart message. The JSON properties, which may be added here depend on the publisher of the table.
class IPublisher : public UJsonApiContext {
public:
virtual ~IPublisher() {};
virtual void AddColumn(const char * remote, const char * local, enum ReplicationType type, bool update) = 0;
virtual void Initialize(const char * row) = 0;
virtual void Added(ulong64 id) = 0;
virtual void Deleted(ulong64 id) = 0;
virtual void DeletedConfirm(ulong64 id) = 0;
virtual void Updated(ulong64 id, ulong64 mask) = 0;
virtual void Stop() = 0;
static class IPublisher * createPublisher(class UPublisher * user, const char * remote, class IDatabase * database, const char * local, const char * sequence, bool add, bool del);
};
This functions is called to create a publisher as part of the initialization.
class UPublisher * user | Use the UPublisher class as base class of one of your classes. The virtual functions of this class are called so signal events from the publisher to the user of the publisher. |
const char * remote | The remote table name, used to publish the table. This name is used inside the replication protocol as "api" property. |
class IDatabase * database | The database pointer |
const char * local | The name of the local database table, from which the remote table is replicated |
bool add | If true, the publisher allows to add to the local table. |
bool del | If true, the publisher allows to delete from the local table. |
After the publisher is created, this function is called to add columns to the replicator. The column in a local database is specified together with the name under which the column is published.
const char * remote | The name under which the column is published |
const char * local | The name of the local database column |
enum ReplicationType type | The type of the column |
bool update | Indicates if the column my be updated from remote |
To be called after all columns have been added to initialize local datastructures and database tables
const char * row | SQL type to for a database column used to join to a row of the published table |