Commit scopes
=============

Commit scopes give applications granular control about durability and
consistency of EDB Postgres Distributed.

A commit scope is a set of rules that describes the behavior of the
system as transactions are committed. The actual behavior depends on
which a kind of commit scope a commit scope’s rule uses :ref:`Synchronous Commit <Synchronous Commit>`  ,
:ref:`How Quorum Commit works <How Quorum Commit works>`  , :ref:`Commit At Most Once <Commit At Most Once>`  , :ref:`Lag Control <Lag Control>`  , or a combination of
these.

While most commit scope kinds control the processing of the transaction,
Lag Control is the exception as it dynamically regulates the performance
of the system in response to replication operations being slow or queued
up. It is typically used, though, in combination with other commit scope
kinds

Commit scope structure
----------------------

Every commit scope has a name (a ``commit_scope_name`` ).

Each commit scope has one or more rules.

Each rule within the commit scope has an ``origin_node_group`` which
together uniquely identify the commit scope rule.

The ``origin_node_group`` is a PGD group and it defines the nodes which
will apply this rule when they are the originators of a transaction.

Finally there is the rule which defines what kind of commit scope or
combination of commit scope kinds should be applied to those
transactions.

So if a commit scope has a rule that reads:

origin_node_group := ‘example_bdr_group’, rule := ‘MAJORITY ORIGIN GROUP
SYNCHRONOUS COMMIT’,

Then, the rule is applied when any node in the ``example_bdr_group``
issues a transaction.

The rule itself specifies how many nodes of a specified group will need
to confirm the change. ``MAJORITY ORIGIN GROUP`` is the commit scope
group, and ``SYNCHRONOUS COMMIT`` is the commit scope kind. This
translates to requiring that a majority of nodes in the origin node’s
group must confirm the change before the change can be considered as
committed.

How a commit scope is selected
------------------------------

When any change takes place, PGD looks up which commit scope should be
used for the transaction or node.

If a transaction specifies a commit scope, that scope will be used.

If not specified, the system will search for a default commit scope.
Default commit scopes are a group level setting. The system consults the
group tree. Starting at the bottom of the group tree with the node’s
group and working up, it searches for any group which has a
default_commit_scope setting defined. This commit scope will then be
used.

If no default_commit_scope is found then the node’s GUC,
bdr.commit_scope is used. And if that isn’t set or is set to ``local``
then no commit scope applies and PGD’s async replication is used.

A commit scope rule applies to a transaction when the originating node’s
group is the rule’s ``origin_node_group`` or one of its subgroups. PGD
determines the match by ascending the group tree from the node’s own
group, most-specific first, so a rule defined on a parent or top-level
group also applies to transactions originating in its subgroups. If no
rule matches and the scope isn’t ``local`` , the transaction uses PGD’s
default async replication.

Creating a Commit Scope
-----------------------

Use ``bdr.create_commit_scope`` to add our example rule to a commit
scope. For example:

.. code:: sql

   SELECT bdr.create_commit_scope(
       commit_scope_name := example_scope,
       origin_node_group := example_bdr_group,
       rule := MAJORITY ORIGIN GROUP SYNCHRONOUS COMMIT,
       wait_for_ready := true
   );

This will add the rule ``MAJORITY ORIGIN GROUP SYNCHRONOUS COMMIT`` for
any transaction originating from the ``example_bdr_group`` to a scope
called ``example_scope`` .

If no rules previously existed in ``example_scope`` , then adding this
rule would make the scope exist.

When a rule is added, the origin_node_group must already exist. If it
does not, the whole add operation will be discarded with an error.

The rule will then be evaluated. If the rule mentions groups that don’t
exist or the settings on the group are incompatible with other
configuration setting on the group’s nodes, a warning will be emitted,
but the rule will be added.

Once the rule is added, the commit scope will be available for use.

The ``wait_for_ready`` controls whether the
``bdr.create_commit_scope()`` call blocks until the rule has been added
to the relevant nodes. The setting defaults to true and can be omitted.

Using a commit scope
--------------------

To use our example scope, we can set ``bdr.commit_scope`` within a
transaction

.. code:: sql

   BEGIN;
   SET LOCAL bdr.commit_scope = example_scope;
   ...
   COMMIT;

You must set the commit scope before the transaction writes any data.

You can set a commit scope as a default for a group or subgroup using
``bdr.alter_node_group_option`` :

.. code:: sql

   SELECT bdr.alter_node_group_option(
     node_group_name := example_bdr_group,
     config_key := default_commit_scope,
     config_value := example_scope
   );

To completely clear the default for a group or subgroup, set the
``default_commit_scope`` value to ``local`` :

.. code:: sql

   SELECT bdr.alter_node_group_option(
     node_group_name := example_bdr_group,
     config_key := default_commit_scope,
     config_value := local
   );

You can also make this change using PGD CLI:

::

   pgd group example-bdr-group set-option default_commit_scope "example_scope"

And you can clear the default using PGD CLI by setting the value to
``local`` :

::

   pgd group example-bdr-group set-option default_commit_scope "local"

Finally, you can set the default commit_scope for a node using:

.. code:: sql

   SET bdr.commit_scope = example_scope;

Set ``bdr.commit_scope`` to ``local`` to use the PGD default async
replication.
