embedded-postgres

repository·master·Indexed 22 days ago

https://github.com/fergusstrange/embedded-postgres

A Go library that allows developers to run a real Postgres database locally on Linux, OSX, or Windows as part of an application or test suite. It supports multiple Postgres versions (V9 through V18), custom configuration for credentials and paths, and provides mechanisms for data persistence and custom binary fetching strategies via CacheLocator and RemoteFetchStrategy.

Tokens
3K
Snippets
9
Records
19
Agent score
76%

What's inside embedded-postgres

  1. Manage data persistence and runtime paths

    master

    Understanding the relationship between RuntimePath and DataPath is critical for data persistence:

    • RuntimePath: This directory is erased and recreated at every Start(). It is not suitable for persistent data.
    • DataPath: To ensure data persists between runs, set DataPath to a directory located outside of the RuntimePath.
    • Binary Management: Postgres binaries are downloaded to BinariesPath. If the directory already exists, the library uses whatever version is present without performing a version check. To run multiple Postgres versions in different tests, ensure BinariesPath is a subdirectory of RuntimePath.
  2. Default CacheLocator behavior

    master

    The library uses a default cache location if no specific directory is provided.

    1. If cacheDirectory is empty, it defaults to .embedded-postgres-go in the user's home directory.
    2. It constructs the filename using the pattern: embedded-postgres-binaries-{operatingSystem}-{architecture}-{version}.txz.
    3. It uses a VersionStrategy to resolve the operating system, architecture, and version string.

    While defaultCacheLocator is an internal implementation detail, you can achieve similar behavior by providing a CacheLocator that follows this path construction logic.

  3. Configure the embedded Postgres instance using Config

    master

    The Config struct manages the runtime configuration for the Postgres process. You should initialize a configuration using DefaultConfig() and then use its builder methods to customize settings.

    Key configuration areas include:

    • Connection details: Port, Database, Username, and Password.
    • Filesystem paths: RuntimePath (extracted runtime), CachePath (binary archives, defaults to ~/.go-embedded-postgres), DataPath (Postgres data directory), and BinariesPath (pre-downloaded binaries).
    • Postgres settings: Version, Locale, Encoding, and StartParameters (passed via -c to override postgres.conf).
    • Lifecycle: StartTimeout (max time to wait for startup) and Logger (output destination).

    You can retrieve a connection string for your application using GetConnectionURL().

  4. Run embedded-postgres with default configuration

    master

    To start a single Postgres instance using default settings, use embeddedpostgres.NewDatabase() and call Start(). Remember to call Stop() to release the child Postgres process and prevent blocking.

    postgres := embeddedpostgres.NewDatabase()
    err := postgres.Start()
    
    // Do test logic
    
    err := postgres.Stop()
  5. Configure embedded-postgres with custom settings

    master

    You can customize the Postgres instance by using NewDatabase with a configuration object generated from DefaultConfig(). This allows you to override credentials, version, paths, and connection parameters.

    logger := &bytes.Buffer{}
    postgres := NewDatabase(DefaultConfig().
    Username("beer").
    Password("wine").
    Database("gin").
    Version(V12).
    RuntimePath("/tmp").
    BinaryRepositoryURL("https://repo.local/central.proxy").
    Port(9876).
    StartTimeout(45 * time.Second).
    StartParameters(map[string]string{"max_connections": "200"}).
    Logger(logger))
    err := postgres.Start()
    
    // Do test logic
    
    err := postgres.Stop()
  6. Reference embedded-postgres configuration options

    master

    The library uses a configuration object with the following default values. Use these keys to customize your instance.

    | Configuration       | Default Value                                   |
    |---------------------|-------------------------------------------------|
    | Username            | postgres                                        |
    | Password            | postgres                                        |
    | Database            | postgres                                        |
    | Version             | 18.3.0                                          |
    | Encoding            | UTF8                                            |
    | Locale              | C                                               |
    | CachePath           | $USER_HOME/.embedded-postgres-go/               |
    | RuntimePath         | $USER_HOME/.embedded-postgres-go/extracted     |
    | DataPath            | $USER_HOME/.embedded-postgres-go/extracted/data |
    | BinariesPath        | $USER_HOME/.embedded-postgres-go/extracted     |
    | BinaryRepositoryURL | https://repo1.maven.org/maven2                  |
    | Port                | 5432                                            |
    | StartTimeout        | 15 Seconds                                      |
    | StartParameters     | map[string]string{"max_connections": "101"}     |
  7. Implement a custom RemoteFetchStrategy

    master

    The RemoteFetchStrategy is a function type used to define how Postgres binaries are retrieved and made available for use. By implementing this type, you can control the source of the binaries (e.g., a local mirror, a specific S3 bucket, or a custom URL structure) instead of relying on the default behavior.

    To use it, define a function that matches the signature func() error and provide it to the configuration that requires a fetching strategy.

  8. Start the Postgres process with Start

    master

    The Start() method attempts to download/extract the required Postgres binaries, initialize the data directory, and launch the Postgres process.

    If an error occurs during startup, Start() will attempt to call Stop() to ensure no orphaned sub-processes are left running. It also performs a health check to ensure the database is ready for connections.

    Errors returned:

    • ErrServerAlreadyStarted: If the server is already running.
    • Various errors related to port availability, binary downloading, or database initialization.
  9. Override Postgres runtime parameters

    master

    Use the StartParameters(parameters map[string]string) method to pass custom configuration settings to the Postgres process at startup. These parameters are passed via the -c flag. This allows you to override default values in postgres.conf.

    Example: To set max_connections to 100:

    config.StartParameters(map[string]string{
        "max_connections": "100",
    })