beginReplication starts a new replication connection to the primary server and returns it. The LSN provided is the last one we have confirmed that we flushed to disk.
(slotName string, lastFlushLsn pglogrepl.LSN)
| 424 | // beginReplication starts a new replication connection to the primary server and returns it. The LSN provided is the |
| 425 | // last one we have confirmed that we flushed to disk. |
| 426 | func (r *LogicalReplicator) beginReplication(slotName string, lastFlushLsn pglogrepl.LSN) (*pgconn.PgConn, error) { |
| 427 | conn, err := pgconn.Connect(context.Background(), r.ReplicationDns()) |
| 428 | if err != nil { |
| 429 | return nil, err |
| 430 | } |
| 431 | |
| 432 | // streaming of large transactions is available since PG 14 (protocol version 2) |
| 433 | // we also need to set 'streaming' to 'true' |
| 434 | pluginArguments := []string{ |
| 435 | "proto_version '2'", |
| 436 | fmt.Sprintf("publication_names '%s'", slotName), |
| 437 | "messages 'true'", |
| 438 | "streaming 'true'", |
| 439 | } |
| 440 | |
| 441 | // The LSN is the position in the WAL where we want to start replication, but it can only be used to skip entries, |
| 442 | // not rewind to previous entries that we've already confirmed to the primary that we flushed. We still pass an LSN |
| 443 | // for the edge case where we have flushed an entry to disk, but crashed before the primary received confirmation. |
| 444 | // In that edge case, we want to "skip" entries (from the primary's perspective) that we have already flushed to disk. |
| 445 | log.Printf("Starting logical replication on slot %s at WAL location %s", slotName, lastFlushLsn+1) |
| 446 | err = pglogrepl.StartReplication(context.Background(), conn, slotName, lastFlushLsn+1, pglogrepl.StartReplicationOptions{ |
| 447 | PluginArgs: pluginArguments, |
| 448 | }) |
| 449 | if err != nil { |
| 450 | return nil, err |
| 451 | } |
| 452 | log.Println("Logical replication started on slot", slotName) |
| 453 | |
| 454 | return conn, nil |
| 455 | } |
| 456 | |
| 457 | // DropPublication drops the publication with the given name if it exists. Mostly useful for testing. |
| 458 | func DropPublication(primaryDns, slotName string) error { |
no test coverage detected