Hi Hou-san. Here are some review comments for your patch v1-0001.
======
doc/src/sgml/logical-replication.sgml
nit - added a comma.
======
doc/src/sgml/monitoring.sgml
nit - use <literal> for 'apply_error_count'.
nit - added a period when there are multiple sentences.
nit - adjusted field descriptions using Chat-GPT clarification suggestions
======
src/include/pgstat.h
nit - change the param to 'type' -- ie. same as the implementation calls it
======
src/include/replication/conflict.h
nit - defined 'NUM_CONFLICT_TYPES' inside the enum (I think this way
is often used in other PG source enums)
======
src/test/subscription/t/026_stats.pl
1.
+ # Delete data from the test table on the publisher. This delete operation
+ # should be skipped on the subscriber since the table is already empty.
+ $node_publisher->safe_psql($db, qq(DELETE FROM $table_name;));
+
+ # Wait for the subscriber to report tuple missing conflict.
+ $node_subscriber->poll_query_until(
+ $db,
+ qq[
+ SELECT update_missing_count > 0 AND delete_missing_count > 0
+ FROM pg_stat_subscription_stats
+ WHERE subname = '$sub_name'
+ ])
+ or die
+ qq(Timed out while waiting for tuple missing conflict for
subscription '$sub_name');
Can you write a comment to explain why the replicated DELETE is
expected to increment both the 'update_missing_count' and the
'delete_missing_count'?
~
nit - update several "Apply and Sync errors..." comments that did not
mention conflicts
nit - tweak comments wording for update_differ and delete_differ
nit - /both > 0/> 0/
nit - /both 0/0/
======
Kind Regards,
Peter Smith.
Fujitsu Australia
diff --git a/doc/src/sgml/logical-replication.sgml
b/doc/src/sgml/logical-replication.sgml
index f3e3641..f682369 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1585,7 +1585,7 @@ test_sub=# SELECT * FROM t1 ORDER BY id;
</para>
<para>
- Additional logging is triggered and the conflict statistics are collected
(displayed in the
+ Additional logging is triggered, and the conflict statistics are collected
(displayed in the
<link
linkend="monitoring-pg-stat-subscription-stats"><structname>pg_stat_subscription_stats</structname></link>
view)
in the following <firstterm>conflict</firstterm> cases:
<variablelist>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index ea36d46..ac3c773 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -2159,7 +2159,7 @@ description | Waiting for a newly initialized WAL file to
reach durable storage
<para>
Number of times an error occurred while applying changes. Note that any
conflict resulting in an apply error will be counted in both
- apply_error_count and the corresponding conflict count.
+ <literal>apply_error_count</literal> and the corresponding conflict
count.
</para></entry>
</row>
@@ -2179,8 +2179,8 @@ description | Waiting for a newly initialized WAL file to
reach durable storage
</para>
<para>
Number of times a row insertion violated a
- <literal>NOT DEFERRABLE</literal> unique constraint while applying
- changes
+ <literal>NOT DEFERRABLE</literal> unique constraint during the
+ application of changes
</para></entry>
</row>
@@ -2189,11 +2189,11 @@ description | Waiting for a newly initialized WAL file
to reach durable storage
<structfield>update_differ_count</structfield> <type>bigint</type>
</para>
<para>
- Number of times an update was performed on a row that was previously
- modified by another source while applying changes. This conflict is
+ Number of times an update was applied to a row that had been previously
+ modified by another source during the application of changes. This
conflict is
counted only when the
<link
linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link>
- option is enabled on the subscriber
+ option is enabled on the subscriber.
</para></entry>
</row>
@@ -2202,9 +2202,9 @@ description | Waiting for a newly initialized WAL file to
reach durable storage
<structfield>update_exists_count</structfield> <type>bigint</type>
</para>
<para>
- Number of times that the updated value of a row violated a
- <literal>NOT DEFERRABLE</literal> unique constraint while applying
- changes
+ Number of times that an updated row value violated a
+ <literal>NOT DEFERRABLE</literal> unique constraint during the
+ application of changes
</para></entry>
</row>
@@ -2213,8 +2213,8 @@ description | Waiting for a newly initialized WAL file to
reach durable storage
<structfield>update_missing_count</structfield> <type>bigint</type>
</para>
<para>
- Number of times that the tuple to be updated was not found while
applying
- changes
+ Number of times the tuple to be updated was not found during the
+ application of changes
</para></entry>
</row>
@@ -2223,11 +2223,11 @@ description | Waiting for a newly initialized WAL file
to reach durable storage
<structfield>delete_differ_count</structfield> <type>bigint</type>
</para>
<para>
- Number of times a delete was performed on a row that was previously
- modified by another source while applying changes. This conflict is
- counted only when the
+ Number of times a delete operation was applied to row that had been
+ previously modified by another source during the application of changes.
+ This conflict is counted only when the
<link
linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link>
- option is enabled on the subscriber
+ option is enabled on the subscriber.
</para></entry>
</row>
@@ -2236,8 +2236,8 @@ description | Waiting for a newly initialized WAL file to
reach durable storage
<structfield>delete_missing_count</structfield> <type>bigint</type>
</para>
<para>
- Number of times that the tuple to be deleted was not found while
applying
- changes
+ Number of times the tuple to be deleted was not found during the
application
+ of changes
</para></entry>
</row>
diff --git a/src/backend/utils/activity/pgstat_subscription.c
b/src/backend/utils/activity/pgstat_subscription.c
index e06c927..ebb0135 100644
--- a/src/backend/utils/activity/pgstat_subscription.c
+++ b/src/backend/utils/activity/pgstat_subscription.c
@@ -116,7 +116,7 @@ pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref,
bool nowait)
#define SUB_ACC(fld) shsubent->stats.fld += localent->fld
SUB_ACC(apply_error_count);
SUB_ACC(sync_error_count);
- for (int i = 0; i < CONFLICT_NUM_TYPES; i++)
+ for (int i = 0; i < NUM_CONFLICT_TYPES; i++)
SUB_ACC(conflict_count[i]);
#undef SUB_ACC
diff --git a/src/backend/utils/adt/pgstatfuncs.c
b/src/backend/utils/adt/pgstatfuncs.c
index 870aee8..7dd4b1e 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2019,7 +2019,7 @@ pg_stat_get_subscription_stats(PG_FUNCTION_ARGS)
values[i++] = Int64GetDatum(subentry->sync_error_count);
/* conflict count */
- for (int nconflict = 0; nconflict < CONFLICT_NUM_TYPES; nconflict++)
+ for (int nconflict = 0; nconflict < NUM_CONFLICT_TYPES; nconflict++)
values[i++] =
Int64GetDatum(subentry->conflict_count[nconflict]);
/* stats_reset */
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index adb91f5..91b54aa 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -166,7 +166,7 @@ typedef struct PgStat_BackendSubEntry
{
PgStat_Counter apply_error_count;
PgStat_Counter sync_error_count;
- PgStat_Counter conflict_count[CONFLICT_NUM_TYPES];
+ PgStat_Counter conflict_count[NUM_CONFLICT_TYPES];
} PgStat_BackendSubEntry;
/* ----------
@@ -425,7 +425,7 @@ typedef struct PgStat_StatSubEntry
{
PgStat_Counter apply_error_count;
PgStat_Counter sync_error_count;
- PgStat_Counter conflict_count[CONFLICT_NUM_TYPES];
+ PgStat_Counter conflict_count[NUM_CONFLICT_TYPES];
TimestampTz stat_reset_timestamp;
} PgStat_StatSubEntry;
@@ -728,7 +728,7 @@ extern PgStat_SLRUStats *pgstat_fetch_slru(void);
*/
extern void pgstat_report_subscription_error(Oid subid, bool is_apply_error);
-extern void pgstat_report_subscription_conflict(Oid subid, ConflictType
conflict);
+extern void pgstat_report_subscription_conflict(Oid subid, ConflictType type);
extern void pgstat_create_subscription(Oid subid);
extern void pgstat_drop_subscription(Oid subid);
extern PgStat_StatSubEntry *pgstat_fetch_stat_subscription(Oid subid);
diff --git a/src/include/replication/conflict.h
b/src/include/replication/conflict.h
index 7232c88..37c9100 100644
--- a/src/include/replication/conflict.h
+++ b/src/include/replication/conflict.h
@@ -45,9 +45,9 @@ typedef enum
* complex rules than simple equality checks. These conflicts are left
for
* future improvements.
*/
-} ConflictType;
-#define CONFLICT_NUM_TYPES (CT_DELETE_MISSING + 1)
+ NUM_CONFLICT_TYPES /* must be last */
+} ConflictType;
extern bool GetTupleTransactionInfo(TupleTableSlot *localslot,
TransactionId *xmin,
diff --git a/src/test/subscription/t/026_stats.pl
b/src/test/subscription/t/026_stats.pl
index 4773528..e22b0b1 100644
--- a/src/test/subscription/t/026_stats.pl
+++ b/src/test/subscription/t/026_stats.pl
@@ -162,7 +162,7 @@ sub create_sub_pub_w_errors
));
# Update the data in the test table on the publisher. This should
generate
- # a conflict because it attempts to update a row on the subscriber that
has
+ # a conflict because it causes subscriber to attempt to update a row
that has
# been modified by a different origin.
$node_publisher->safe_psql($db, qq(UPDATE $table_name SET a = 2;));
@@ -184,7 +184,7 @@ sub create_sub_pub_w_errors
));
# Delete data from the test table on the publisher. This should
generate a
- # conflict because it attempts to delete a row on the subscriber that
has
+ # conflict because it causes subscriber to attempt to delete a row that
has
# been modified by a different origin.
$node_publisher->safe_psql($db, qq(DELETE FROM $table_name;));
@@ -216,7 +216,7 @@ my ($pub1_name, $sub1_name) =
create_sub_pub_w_errors($node_publisher, $node_subscriber, $db,
$table1_name);
-# Apply and Sync errors are > 0 and reset timestamp is NULL
+# Apply errors, sync errors, and conflicts are > 0 and reset timestamp is NULL
is( $node_subscriber->safe_psql(
$db,
qq(SELECT apply_error_count > 0,
@@ -232,7 +232,7 @@ is( $node_subscriber->safe_psql(
WHERE subname = '$sub1_name')
),
qq(t|t|t|t|t|t|t|t|t),
- qq(Check that apply errors, sync errors, and conflicts are both > 0 and
stats_reset is NULL for subscription '$sub1_name'.)
+ qq(Check that apply errors, sync errors, and conflicts are > 0 and
stats_reset is NULL for subscription '$sub1_name'.)
);
# Reset a single subscription
@@ -240,7 +240,7 @@ $node_subscriber->safe_psql($db,
qq(SELECT pg_stat_reset_subscription_stats((SELECT subid FROM
pg_stat_subscription_stats WHERE subname = '$sub1_name')))
);
-# Apply and Sync errors are 0 and stats reset is not NULL
+# Apply errors, sync errors, and conflicts are 0 and stats reset is not NULL
is( $node_subscriber->safe_psql(
$db,
qq(SELECT apply_error_count = 0,
@@ -256,7 +256,7 @@ is( $node_subscriber->safe_psql(
WHERE subname = '$sub1_name')
),
qq(t|t|t|t|t|t|t|t|t),
- qq(Confirm that apply errors, sync errors, and conflicts are both 0 and
stats_reset is not NULL after reset for subscription '$sub1_name'.)
+ qq(Confirm that apply errors, sync errors, and conflicts are 0 and
stats_reset is not NULL after reset for subscription '$sub1_name'.)
);
# Get reset timestamp
@@ -286,7 +286,7 @@ my ($pub2_name, $sub2_name) =
create_sub_pub_w_errors($node_publisher, $node_subscriber, $db,
$table2_name);
-# Apply and Sync errors are > 0 and reset timestamp is NULL
+# Apply errors, sync errors, and conflicts are > 0 and reset timestamp is NULL
is( $node_subscriber->safe_psql(
$db,
qq(SELECT apply_error_count > 0,
@@ -302,14 +302,14 @@ is( $node_subscriber->safe_psql(
WHERE subname = '$sub2_name')
),
qq(t|t|t|t|t|t|t|t|t),
- qq(Confirm that apply errors, sync errors, and conflicts are both > 0
and stats_reset is NULL for sub '$sub2_name'.)
+ qq(Confirm that apply errors, sync errors, and conflicts are > 0 and
stats_reset is NULL for sub '$sub2_name'.)
);
# Reset all subscriptions
$node_subscriber->safe_psql($db,
qq(SELECT pg_stat_reset_subscription_stats(NULL)));
-# Apply and Sync errors are 0 and stats reset is not NULL
+# Apply errors, sync errors, and conflicts are 0 and stats reset is not NULL
is( $node_subscriber->safe_psql(
$db,
qq(SELECT apply_error_count = 0,
@@ -325,7 +325,7 @@ is( $node_subscriber->safe_psql(
WHERE subname = '$sub1_name')
),
qq(t|t|t|t|t|t|t|t|t),
- qq(Confirm that apply errors, sync errors, and conflicts are both 0 and
stats_reset is not NULL for sub '$sub1_name' after reset.)
+ qq(Confirm that apply errors, sync errors, and conflicts are 0 and
stats_reset is not NULL for sub '$sub1_name' after reset.)
);
is( $node_subscriber->safe_psql(
@@ -343,7 +343,7 @@ is( $node_subscriber->safe_psql(
WHERE subname = '$sub2_name')
),
qq(t|t|t|t|t|t|t|t|t),
- qq(Confirm that apply errors, sync errors, and conflicts are both 0 and
stats_reset is not NULL for sub '$sub2_name' after reset.)
+ qq(Confirm that apply errors, sync errors, and conflicts are 0 and
stats_reset is not NULL for sub '$sub2_name' after reset.)
);
$reset_time1 = $node_subscriber->safe_psql($db,