# 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:

- Exchange of information, which columns of the table are requested by the client and which of these can provided by the server
- Support of change sequence number, so that after the websocket connection is established only updates from after the latest known sequence number have to be replicated.
- Dynamic updates of the client when the connection is up
- Updates from client sent to the server

## File information

File | common/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, 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.

### 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 * 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.

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, instance, guid and usn (see creatReplicator). The replication is restarted when this function is called

Parameters
  domain, instance, guid and usn as defined for createReplicator

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

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

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

### ReplicatorDeleted

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.

Parameters

  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

### ReplicatorDeletedConfirm

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.

Parameters

  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.

### ReplicatorDeletedConfirmComplete

Called when a row was deleted locally after a DeletedConfirm call

Parameters

  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.

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

### ReplicatorSessionInitializing

Indicates that the replicator is waiting for a matching AppWebsocket connection

### ReplicatorSessionStarted

Indicates the a ReplicateStartResult was received and the initial replication started.

### ReplicatorSessionInitialized

Indicates that the initial replication is complete

### ReplicatorSessionClosed

Indicates that the replication AppWebsocket connection was closed and the replicator is waiting for a matching AppWebsocket connection

### ReplicatorStopped

Called when stopping of the replicator is complete after call to Stop().

### 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