bgentry/que-go

Is `que-go` + `github.com/lib/pq` really that bad

keegancsmith opened this issue · 1 comments

Hey, I really want to use que-go, but in an app I work on we already use pq a few times (for notify/checking errors/etc). Instead of rolling my own queue or introducing pgx (I have some reservations), I wondered if I could modify que-go to use transaction level advisory locks (pg_try_advisory_xact_lock). That way we could continue using the usual database/sql and github.com/lib/pq API.

After some hacking it seems to work, but had to change the API a bit (no more Done() or Conn()). Is this a really bad idea, or is this feasible? My fork is at https://github.com/keegancsmith/que-go

Hi @keegancsmith,

My goal with this library is to maintain 100% compatibility with the que implementation. Using transaction-level advisory locks instead of session-level locks has two main conflicts with this goal:

  1. que itself uses session-level advisory locks, which use different postgres functions than transaction-level locks and are not interchangeable
  2. Using transaction-level advisory locks would require some code changes and would result in some different behaviors than session-level locks. One case I'm thinking of is if there's an error during i.e. an INSERT, which would cause the transaction to be rolled back. Que normally saves info about an error after it occurs (including an error message and retry timestamp), but it would be unable to safely do so with transaction-level locks. The lock would get released as soon as an error occurs, and there would be no guarantee of writing error info before another worker picks up the job.

Regarding pq vs pgx, it's not that one is "bad" and the other isn't. It's just that database/sql has no ability to check out a connection from the pool for as long as que-go would need to hold it. Pgx does have this functionality. All benchmarks I've seen point to it also being significantly faster than pq.

The main tradeoffs I'm aware of with pgx are a (potentially) smaller base of users and stricter type requirements that require your Go code to use types that can be directly encoded to and decoded from the underlying Postgres type.