replication.h

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 information

Filecommon/interface/replication.h

Classes IReplicator
UReplicator
IPublisher
UPublisher

Classes

IReplicator

class IReplicator : public UJsonApiContext {
public:
    virtual ~IReplicator() {};
    virtual void Update(const char * domain, const char * instance) = 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 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);
};

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.

Public functions

createReplicator

This functions is called to create the replicator as part of the initialization.

Parameters
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 * 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: the default value for domainProperty is "domain" and for instanceProperty "pbx" if you replicate from an innovaphone PBX!
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.
Return value
Pointer to the replicator interface class

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();

Update

Function may be called to update domain and instance (see creatReplicator). The replication is restarted when this function is called

Parameters
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.
If you replicate from an innovaphone PBX, you typically use the App instance domain name for domain and a configurable value for instance, which must match the "PBX Name" of the PBX which is used for replication.
The configuration of the PBX name can be e.g. done inside a PBX Manager Plugin for your App.

AddColumn

After the replicator is created, the columns which should be replicated must be configured. This is done by calling AddColumn for each column.

Parameters
const char * remote The column name under which it is published
const char * local The local database column name
enum ReplicationType type
ReplicationString
string of arbitrary length
ReplicationULong64
64bit unsigned integer
ReplicationUnsigned
32bit unsigned integer
ReplicationBool
Boolean
ReplicationArray
Not used with the AddColumn function, but only used internally for the AddArray function
bool update The replicator user may update this column

AddArray

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.

Parameters
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.
Return value
A pointer to a IReplicatorArray class, which can be used to add columns

Initialize

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.

Parameters
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"

Added

Called when a row was added to the local table, so that the replicator can replicate the change to the publisher

Parameters
ulong64 id The id of the row added

Deleted

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

Parameters
ulong64 id The id of the row to be deleted

DeletedConfirm

Call to acknowlegde an incoming Deleted call. Only after the DeletedConfirm call the row is deleted from the table.

Parameters
ulong64 id The id of the row to be deleted

Updated

Called when a row was updated in the local table, so that the replicator can replicate the change to the publisher

Parameters
ulong64 id The id of the row updated

Start

Call to start the replicator after it was stopped. After initialization the replicator is started automatically, so there is no need to call Start.

Stop

Call to stop the replicator

UReplicator

class UReplicator {
public:
    virtual void ReplicatorInitialized() = 0;
    virtual void ReplicatorAdded(ulong64 id) = 0;
    virtual void ReplicatorDeleted(ulong64 id) = 0;
    virtual void ReplicatorDeletedConfirm(ulong64 id) = 0;
    virtual void ReplicatorDeletedConfirmComplete(ulong64 id) = 0;
    virtual void ReplicatorUpdated(ulong64 id, ulong64 mask) = 0;
    virtual void ReplicatorSessionInitialized() {}
    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) {};
};

ReplicatorInitialized

Called when replicator initialization is complete

ReplicatorAdded

Called when a row was added by the replicator

Parameters
ulong64 id The id of the row added

ReplicatorDeleted

Called when a row was deleted on the publisher. Locally the row is deleted only after DeletedConfirm is called

Parameters
ulong64 id The id of the row deleted

ReplicatorDeleted

Called when a row can be deleted locally after a Deleted was called

Parameters
ulong64 id The id of the row deleted

ReplicatorDeletedComplete

Called when a row was deleted locally after a DeletedConfirm call

Parameters
ulong64 id The id of the row deleted

ReplicatorUpdated

Called when a row was updated by the replicator

Parameters
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.

ReplicatorSessionInitialized

?

ReplicatorStopped

?

ReplicatorUpdate

?

ReplicatorStart

Callback to add custom arguments to the ReplicateStart message. The JSON properties, which may be added here depend on the publisher of the table.

IPublisher

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);
};

createPublisher

This functions is called to create a publisher as part of the initialization.

Parameters
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.
Return value
Pointer to the publisher interface class

AddColumn

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.

Parameters
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

Initialize

To be called after all columns have been added to initialize local datastructures and database tables

Parameters
const char * row SQL type to for a database column used to join to a row of the published table