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)
| 502 | // beginReplication starts a new replication connection to the primary server and returns it. The LSN provided is the |
| 503 | // last one we have confirmed that we flushed to disk. |
| 504 | func (r *LogicalReplicator) beginReplication(slotName string, lastFlushLsn pglogrepl.LSN) (*pgconn.PgConn, error) { |
| 505 | r.logger.Debugf("Connecting to primary for replication: %s", r.ReplicationDns()) |
| 506 | conn, err := pgconn.Connect(context.Background(), r.ReplicationDns()) |
| 507 | if err != nil { |
| 508 | return nil, err |
| 509 | } |
| 510 | |
| 511 | // streaming of large transactions is available since PG 14 (protocol version 2) |
| 512 | // we also need to set 'streaming' to 'true' |
| 513 | pluginArguments := []string{ |
| 514 | "proto_version '2'", |
| 515 | fmt.Sprintf("publication_names '%s'", slotName), |
| 516 | "messages 'true'", |
| 517 | "streaming 'true'", |
| 518 | } |
| 519 | |
| 520 | // The LSN is the position in the WAL where we want to start replication, but it can only be used to skip entries, |
| 521 | // not rewind to previous entries that we've already confirmed to the primary that we flushed. We still pass an LSN |
| 522 | // for the edge case where we have flushed an entry to disk, but crashed before the primary received confirmation. |
| 523 | // In that edge case, we want to "skip" entries (from the primary's perspective) that we have already flushed to disk. |
| 524 | r.logger.Debugf("Starting logical replication on slot %s at WAL location %s", slotName, lastFlushLsn+1) |
| 525 | err = pglogrepl.StartReplication(context.Background(), conn, slotName, lastFlushLsn+1, pglogrepl.StartReplicationOptions{ |
| 526 | PluginArgs: pluginArguments, |
| 527 | }) |
| 528 | if err != nil { |
| 529 | return nil, err |
| 530 | } |
| 531 | r.logger.Infoln("Logical replication started on slot", slotName, "at WAL location", lastFlushLsn+1) |
| 532 | |
| 533 | return conn, nil |
| 534 | } |
| 535 | |
| 536 | // DropPublication drops the publication with the given name if it exists. Mostly useful for testing. |
| 537 | func DropPublication(primaryDns, slotName string) error { |
no test coverage detected