]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Change unit of idle_replication_slot_timeout to seconds.
authorFujii Masao <fujii@postgresql.org>
Thu, 10 Jul 2025 23:39:24 +0000 (08:39 +0900)
committerFujii Masao <fujii@postgresql.org>
Thu, 10 Jul 2025 23:42:16 +0000 (08:42 +0900)
Previously, the idle_replication_slot_timeout parameter used minutes
as its unit, based on the assumption that values would typically exceed
one minute in production environments. However, this caused unexpected
behavior: specifying a value below 30 seconds would round down to 0,
effectively disabling the timeout. This could be surprising to users.

To allow finer-grained control and avoid such confusion, this commit changes
the unit of idle_replication_slot_timeout to seconds. Larger values can
still be specified easily using standard time suffixes, for example,
'24h' for 24 hours.

Back-patch to v18 where idle_replication_slot_timeout was added.

Reported-by: Gunnar Morling <gunnar.morling@googlemail.com>
Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Laurenz Albe <laurenz.albe@cybertec.at>
Reviewed-by: David G. Johnston <david.g.johnston@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CADGJaX_0+FTguWpNSpgVWYQP_7MhoO0D8=cp4XozSQgaZ40Odw@mail.gmail.com
Backpatch-through: 18

doc/src/sgml/config.sgml
src/backend/replication/slot.c
src/backend/utils/misc/guc_tables.c
src/backend/utils/misc/postgresql.conf.sample
src/include/replication/slot.h

index 59a0874528a3accaa4b68463933e21fc7c8e9478..bd12225cbe4f019c1a06ba4d83ce12d926a89a6a 100644 (file)
@@ -4620,7 +4620,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
        <para>
         Invalidate replication slots that have remained idle longer than this
         duration. If this value is specified without units, it is taken as
-        minutes. A value of zero (the default) disables the idle timeout
+        seconds. A value of zero (the default) disables the idle timeout
         invalidation mechanism. This parameter can only be set in the
         <filename>postgresql.conf</filename> file or on the server command
         line.
index f9fec50ae883ff4bf6792e5cc3831ca0c736ecad..27530dade2b2f32262f7513074d098913528363b 100644 (file)
@@ -154,7 +154,7 @@ int                 max_replication_slots = 10; /* the maximum number of replication
  * Invalidate replication slots that have remained idle longer than this
  * duration; '0' disables it.
  */
-int                    idle_replication_slot_timeout_mins = 0;
+int                    idle_replication_slot_timeout_secs = 0;
 
 /*
  * This GUC lists streaming replication standby server slot names that
@@ -1612,13 +1612,10 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause,
 
                case RS_INVAL_IDLE_TIMEOUT:
                        {
-                               int                     minutes = slot_idle_seconds / SECS_PER_MINUTE;
-                               int                     secs = slot_idle_seconds % SECS_PER_MINUTE;
-
                                /* translator: %s is a GUC variable name */
-                               appendStringInfo(&err_detail, _("The slot's idle time of %dmin %02ds exceeds the configured \"%s\" duration of %dmin."),
-                                                                minutes, secs, "idle_replication_slot_timeout",
-                                                                idle_replication_slot_timeout_mins);
+                               appendStringInfo(&err_detail, _("The slot's idle time of %lds exceeds the configured \"%s\" duration of %ds."),
+                                                                slot_idle_seconds, "idle_replication_slot_timeout",
+                                                                idle_replication_slot_timeout_secs);
                                /* translator: %s is a GUC variable name */
                                appendStringInfo(&err_hint, _("You might need to increase \"%s\"."),
                                                                 "idle_replication_slot_timeout");
@@ -1656,7 +1653,7 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause,
 static inline bool
 CanInvalidateIdleSlot(ReplicationSlot *s)
 {
-       return (idle_replication_slot_timeout_mins != 0 &&
+       return (idle_replication_slot_timeout_secs != 0 &&
                        !XLogRecPtrIsInvalid(s->data.restart_lsn) &&
                        s->inactive_since > 0 &&
                        !(RecoveryInProgress() && s->data.synced));
@@ -1717,9 +1714,9 @@ DetermineSlotInvalidationCause(uint32 possible_causes, ReplicationSlot *s,
                if (CanInvalidateIdleSlot(s))
                {
                        /*
-                        * We simulate the invalidation due to idle_timeout as the minimum
-                        * time idle time is one minute which makes tests take a long
-                        * time.
+                        * Simulate the invalidation due to idle_timeout to test the
+                        * timeout behavior promptly, without waiting for it to trigger
+                        * naturally.
                         */
 #ifdef USE_INJECTION_POINTS
                        if (IS_INJECTION_POINT_ATTACHED("slot-timeout-inval"))
@@ -1734,7 +1731,7 @@ DetermineSlotInvalidationCause(uint32 possible_causes, ReplicationSlot *s,
                         * idle_replication_slot_timeout GUC.
                         */
                        if (TimestampDifferenceExceedsSeconds(s->inactive_since, now,
-                                                                                                 idle_replication_slot_timeout_mins * SECS_PER_MINUTE))
+                                                                                                 idle_replication_slot_timeout_secs))
                        {
                                *inactive_since = s->inactive_since;
                                return RS_INVAL_IDLE_TIMEOUT;
index 511dc32d519216448a90c6e2798db98c17c40100..a925be869448c1807fcc5391ee460e7959ffd2a6 100644 (file)
@@ -3100,10 +3100,10 @@ struct config_int ConfigureNamesInt[] =
                        gettext_noop("Sets the duration a replication slot can remain idle before "
                                                 "it is invalidated."),
                        NULL,
-                       GUC_UNIT_MIN
+                       GUC_UNIT_S
                },
-               &idle_replication_slot_timeout_mins,
-               0, 0, INT_MAX / SECS_PER_MINUTE,
+               &idle_replication_slot_timeout_secs,
+               0, 0, INT_MAX,
                check_idle_replication_slot_timeout, NULL, NULL
        },
 
index 341f88adc87b270234c00d387b2ddc85b5688df4..a9d8293474af5ec61cedeaaaf096ded6892a4523 100644 (file)
                                # (change requires restart)
 #wal_keep_size = 0             # in megabytes; 0 disables
 #max_slot_wal_keep_size = -1   # in megabytes; -1 disables
-#idle_replication_slot_timeout = 0     # in minutes; 0 disables
+#idle_replication_slot_timeout = 0     # in seconds; 0 disables
 #wal_sender_timeout = 60s      # in milliseconds; 0 disables
 #track_commit_timestamp = off  # collect timestamp of transaction commit
                                # (change requires restart)
index ffacba9d2ae52301100b62ca49046c516e67c9b7..76aeeb92242e9ba1680d6ea8fd7c673211603a0f 100644 (file)
@@ -266,7 +266,7 @@ extern PGDLLIMPORT ReplicationSlot *MyReplicationSlot;
 /* GUCs */
 extern PGDLLIMPORT int max_replication_slots;
 extern PGDLLIMPORT char *synchronized_standby_slots;
-extern PGDLLIMPORT int idle_replication_slot_timeout_mins;
+extern PGDLLIMPORT int idle_replication_slot_timeout_secs;
 
 /* shmem initialization functions */
 extern Size ReplicationSlotsShmemSize(void);