Skip to content

Commit 827401b

Browse files
committed
fix: Slot not being deleted when created with dynamicConfig
Closes #2992
1 parent cf673a1 commit 827401b

2 files changed

Lines changed: 68 additions & 33 deletions

File tree

stackgres-k8s/src/common/src/main/java/io/stackgres/common/JsonUtil.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.stackgres.common;
77

88
import java.io.IOException;
9+
import java.util.ArrayList;
910
import java.util.List;
1011
import java.util.function.Predicate;
1112

@@ -45,20 +46,26 @@ public static ObjectNode mergeJsonObjectsFilteringByModel(
4546
ObjectNode otherValueFilteredByModel = JSON_MAPPER.valueToTree(
4647
JSON_MAPPER.readValue(otherValue.toString(), modelClass));
4748
List<Tuple2<ObjectNode, ObjectNode>> nodesToFilterOut =
48-
List.of(Tuple.tuple(otherValueFilteredByModel, otherValue));
49-
while (!nodesToFilterOut.isEmpty()) {
50-
nodesToFilterOut
51-
.forEach(nodeTuple -> Seq.seq(nodeTuple.v1.fieldNames())
52-
.filter(Predicate.not(field -> nodeTuple.v2.get(field) instanceof ObjectNode objectNode
53-
&& !objectNode.isEmpty()))
54-
.forEach(nodeTuple.v2::remove));
55-
nodesToFilterOut = Seq.seq(nodesToFilterOut)
49+
new ArrayList<>(List.of(Tuple.tuple(otherValueFilteredByModel, otherValue)));
50+
List<Tuple2<ObjectNode, ObjectNode>> nextNodesToFilterOut = nodesToFilterOut;
51+
while (true) {
52+
nextNodesToFilterOut =
53+
Seq.seq(nextNodesToFilterOut)
5654
.flatMap(nodeTuple -> Seq.seq(nodeTuple.v1.fieldNames())
5755
.map(field -> Tuple.tuple(nodeTuple.v1.get(field), nodeTuple.v2.get(field))))
58-
.filter(nodeTuple -> ObjectNode.class.isInstance(nodeTuple.v1))
56+
.filter(nodeTuple -> ObjectNode.class.isInstance(nodeTuple.v1) && nodeTuple.v2 != null)
5957
.map(nodeTuple -> nodeTuple.map1(ObjectNode.class::cast).map2(ObjectNode.class::cast))
6058
.toList();
59+
if (nextNodesToFilterOut.isEmpty()) {
60+
break;
61+
}
62+
nodesToFilterOut.addAll(0, nextNodesToFilterOut);
6163
}
64+
nodesToFilterOut
65+
.forEach(nodeTuple -> Seq.seq(nodeTuple.v1.fieldNames())
66+
.filter(Predicate.not(field -> nodeTuple.v2.get(field) instanceof ObjectNode objectNode
67+
&& !objectNode.isEmpty()))
68+
.forEach(nodeTuple.v2::remove));
6269
JsonNode updatedValue = JSON_MAPPER.readerForUpdating(otherValue)
6370
.readTree(JSON_MAPPER.writeValueAsString(value));
6471
return (ObjectNode) updatedValue;

stackgres-k8s/src/common/src/test/java/io/stackgres/common/JsonUtilTest.java

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,6 @@ void testMergeJsonObjectsFilteringByModelBase() throws Exception {
230230
value, otherValue, Model.class);
231231
assertEquals("""
232232
---
233-
ve:
234-
ka: 1
235-
kb: 2
236233
vf:
237234
vm: "m"
238235
vi: "a"
@@ -254,6 +251,9 @@ void testMergeJsonObjectsFilteringByModelBase() throws Exception {
254251
- 1
255252
- 2
256253
- 3
254+
ve:
255+
ka: 1
256+
kb: 2
257257
vg:
258258
- vi: "d"
259259
vj: "e"
@@ -291,6 +291,8 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig1() throws Exception {
291291
void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
292292
ObjectNode value = (ObjectNode) io.stackgres.testutil.JsonUtil.yamlMapper()
293293
.readTree("""
294+
check_timeline: true
295+
loop_wait: 10
294296
postgresql:
295297
parameters:
296298
archive_command: /bin/true
@@ -340,9 +342,6 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
340342
random_page_cost: '1.5'
341343
shared_buffers: 32MB
342344
shared_preload_libraries: pg_stat_statements, auto_explain
343-
ssl: 'on'
344-
ssl_cert_file: /etc/ssl/tls.crt
345-
ssl_key_file: /etc/ssl/tls.key
346345
superuser_reserved_connections: '8'
347346
track_activity_query_size: 4kB
348347
track_commit_timestamp: 'on'
@@ -353,17 +352,30 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
353352
wal_level: logical
354353
wal_log_hints: 'on'
355354
work_mem: 10MB
356-
use_slots: true
355+
pg_hba:
356+
- local all all trust
357+
- host all all 127.0.0.1/32 md5
358+
- host all all ::1/128 md5
359+
- local replication all trust
360+
- host all all 0.0.0.0/0 md5
361+
- host replication replicator 0.0.0.0/0 md5
357362
use_pg_rewind: true
358-
ttl: 30
359-
loop_wait: 10
363+
use_slots: true
360364
retry_timeout: 10
365+
standby_cluster:
366+
create_replica_methods:
367+
- basebackup
368+
host: primary-standby-from-cluster
369+
port: '5433'
370+
restore_command: exec-with-env replicate -- wal-g wal-fetch %f %p
361371
synchronous_mode: false
362372
synchronous_mode_strict: false
363-
check_timeline: true
373+
ttl: 30
364374
""");
365375
ObjectNode otherValue = (ObjectNode) io.stackgres.testutil.JsonUtil.yamlMapper()
366376
.readTree("""
377+
check_timeline: true
378+
loop_wait: 10
367379
postgresql:
368380
parameters:
369381
archive_command: /bin/true
@@ -413,9 +425,6 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
413425
random_page_cost: '1.5'
414426
shared_buffers: 32MB
415427
shared_preload_libraries: pg_stat_statements, auto_explain
416-
ssl: 'on'
417-
ssl_cert_file: /etc/ssl/tls.crt
418-
ssl_key_file: /etc/ssl/tls.key
419428
superuser_reserved_connections: '8'
420429
track_activity_query_size: 4kB
421430
track_commit_timestamp: 'on'
@@ -426,19 +435,30 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
426435
wal_level: logical
427436
wal_log_hints: 'on'
428437
work_mem: 10MB
429-
use_slots: true
438+
pg_hba:
439+
- local all all trust
440+
- host all all 127.0.0.1/32 md5
441+
- host all all ::1/128 md5
442+
- local replication all trust
443+
- host all all 0.0.0.0/0 md5
444+
- host replication replicator 0.0.0.0/0 md5
430445
use_pg_rewind: true
431-
ttl: 30
432-
loop_wait: 10
446+
use_slots: true
433447
retry_timeout: 10
448+
slots: {}
449+
standby_cluster: {}
434450
synchronous_mode: false
435451
synchronous_mode_strict: false
436-
check_timeline: true
452+
ttl: 30
453+
pause: true
437454
""");
438455
var result = JsonUtil.mergeJsonObjectsFilteringByModel(
439456
value, otherValue, PatroniConfig.class);
440457
assertEquals("""
441458
---
459+
pause: true
460+
check_timeline: true
461+
loop_wait: 10
442462
postgresql:
443463
parameters:
444464
archive_command: "/bin/true"
@@ -488,9 +508,6 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
488508
random_page_cost: "1.5"
489509
shared_buffers: "32MB"
490510
shared_preload_libraries: "pg_stat_statements, auto_explain"
491-
ssl: "on"
492-
ssl_cert_file: "/etc/ssl/tls.crt"
493-
ssl_key_file: "/etc/ssl/tls.key"
494511
superuser_reserved_connections: "8"
495512
track_activity_query_size: "4kB"
496513
track_commit_timestamp: "on"
@@ -501,14 +518,25 @@ void testMergeJsonObjectsFilteringByModelPatroniConfig2() throws Exception {
501518
wal_level: "logical"
502519
wal_log_hints: "on"
503520
work_mem: "10MB"
504-
use_slots: true
521+
pg_hba:
522+
- "local all all trust"
523+
- "host all all 127.0.0.1/32 md5"
524+
- "host all all ::1/128 md5"
525+
- "local replication all trust"
526+
- "host all all 0.0.0.0/0 md5"
527+
- "host replication replicator 0.0.0.0/0 md5"
505528
use_pg_rewind: true
506-
ttl: 30
507-
loop_wait: 10
529+
use_slots: true
508530
retry_timeout: 10
531+
standby_cluster:
532+
create_replica_methods:
533+
- "basebackup"
534+
host: "primary-standby-from-cluster"
535+
port: "5433"
536+
restore_command: "exec-with-env replicate -- wal-g wal-fetch %f %p"
509537
synchronous_mode: false
510538
synchronous_mode_strict: false
511-
check_timeline: true
539+
ttl: 30
512540
""",
513541
io.stackgres.testutil.JsonUtil.yamlMapper().writeValueAsString(result));
514542
}

0 commit comments

Comments
 (0)