Skip to content
Bram Gruneir edited this page May 15, 2024 · 4 revisions

Three-Way Merge

Replicator supports merge operations when a compare-and-set behavior is defined for a table. This can enable automated, per-row reconciliation in bi-directional replication use cases.

The merge operation will take advantage of changefeeds created with the diff option. Having before, after, and target allows Replicator to provide a built-in api.standardMerge() operator. This implements a basic three-way merge that can delegate to a user-defined function or to a dead-letter-queue when irreconcilable conflicts occur.

Refer to replicator@v1.d.ts for further details on the userscript API.

api.configureTable('my_table', {
    // One or more columns must be present to enable merge behavior.
    cas: [ 'version' ],
    // This shows how a counter-like column can be merged by applying a
    // delta computed from the incoming payload.
    merge: api.standardMerge(op: api.MergeOp => {
        console.log("merge", JSON.stringify(op));
        op.unmerged.forEach(colName => {
            switch (colName) {
                case "val":
                    // Leading unary + coerces to numeric.
                    op.target.val = +op.target.val + +op.proposed.val - +op.before.val;
                    break;
                default:
                    // This could also arrange to return a DLQ result.
                    throw new Error("unexpected column name: " + colName)
            }
        })
        op.target.version++;
        return {apply: op.target};
    }),
});

Dead-letter queues

The target schema may define one or more DLQ tables. Replicator, as a general rule, does not perform schema changes within an application schema. The structure of the tables, with example DDL, is given in dlq_schema.go.

// This will attempt a three-way merge and then write conflicts to a DLQ.
api.configureTable('my_table', {
    cas: [ 'version' ],
    merge: api.standardMerge(() => ({dlq: "for_later"}))
});
Clone this wiki locally