By dropping down to common database/sql constructs, River can share connections and transactions with Bun, a well known ORM (Object Relational Mapper) in the Go ecosystem.
Sharing a database handle
The same *sql.DB handle can be configured on Bun and a River client:
import ( _ "github.com/jackc/pgx/v5/stdlib" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdriver/riverdatabasesql")sqlDB, err := sql.Open("pgx", "postgres://localhost/river")if err != nil { return nil, err}
bunDB := bun.NewDB(sqlDB, pgdialect.New())
riverClient, err := river.NewClient(riverdatabasesql.New(sqlDB), &river.Config{ Workers: workers,})if err != nil { return nil, err}Database/sql does not support listen
The database/sql package doesn't support Postgres LISTEN, so if a client using riverdatabasesql is started for work, it does so in "poll only mode", meaning that jobs are fetched by polling periodically rather than being notified through a Postgres listen/notify channel.
For maximum throughput performance, use of riverdatabasesql should be restricted to compatibility with packages like GORM, and that a separate client with a Pgx pool and using the more standard riverpgxv5 driver is used for working jobs.
Sharing a transaction
Transactions are shareable by starting them from Bun, then accessing bun.Tx's embedded *sql.Tx and using it with a River client's InsertTx:
tx, err := bunDB.BeginTx(ctx, &sql.TxOptions{})if err != nil { return nil, err}
_, err = riverClient.InsertTx(ctx, tx.Tx, SortArgs{ // tx.Tx is *sql.Tx Strings: []string{ "whale", "tiger", "bear", },}, nil)if err != nil { return nil, err}
if err := tx.Commit(); err != nil { return nil, err}