satellite/satellitedb: use delete returning to query pending_serial_queue
this way we don't have to do 2 steps, and by using the ctid, postgres is going to do two very efficient prefix scans. Change-Id: Ia9d0546cdf0a1af67ceec9cd508d336a5fdcbdb9
This commit is contained in:
parent
b82d04e618
commit
2b3545c0c3
@ -17,6 +17,7 @@ import (
|
|||||||
"storj.io/common/uuid"
|
"storj.io/common/uuid"
|
||||||
"storj.io/storj/private/dbutil"
|
"storj.io/storj/private/dbutil"
|
||||||
"storj.io/storj/private/dbutil/pgutil"
|
"storj.io/storj/private/dbutil/pgutil"
|
||||||
|
"storj.io/storj/private/tagsql"
|
||||||
"storj.io/storj/satellite/orders"
|
"storj.io/storj/satellite/orders"
|
||||||
"storj.io/storj/satellite/satellitedb/dbx"
|
"storj.io/storj/satellite/satellitedb/dbx"
|
||||||
)
|
)
|
||||||
@ -609,71 +610,74 @@ type rawPendingSerial struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ordersDBQueue struct {
|
type ordersDBQueue struct {
|
||||||
db *satelliteDB
|
impl dbutil.Implementation
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
produced []rawPendingSerial
|
tx tagsql.Tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *ordersDB) WithQueue(ctx context.Context, cb func(ctx context.Context, queue orders.Queue) error) (err error) {
|
func (db *ordersDB) WithQueue(ctx context.Context, cb func(ctx context.Context, queue orders.Queue) error) (err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
queue := &ordersDBQueue{
|
return Error.Wrap(db.db.WithTx(ctx, func(ctx context.Context, tx *dbx.Tx) error {
|
||||||
db: db.db,
|
return cb(ctx, &ordersDBQueue{
|
||||||
|
impl: db.db.implementation,
|
||||||
log: db.db.log,
|
log: db.db.log,
|
||||||
}
|
tx: tx.Tx,
|
||||||
|
})
|
||||||
err = cb(ctx, queue)
|
}))
|
||||||
if err != nil {
|
|
||||||
return errs.Wrap(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodeIDs, bucketIDs, serialNumbers [][]byte
|
|
||||||
for _, pending := range queue.produced {
|
|
||||||
nodeIDs = append(nodeIDs, pending.nodeID)
|
|
||||||
bucketIDs = append(bucketIDs, pending.bucketID)
|
|
||||||
serialNumbers = append(serialNumbers, pending.serialNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.db.ExecContext(ctx, `
|
|
||||||
DELETE FROM pending_serial_queue WHERE (
|
|
||||||
storage_node_id, bucket_id, serial_number
|
|
||||||
) IN (
|
|
||||||
SELECT
|
|
||||||
unnest($1::bytea[]),
|
|
||||||
unnest($2::bytea[]),
|
|
||||||
unnest($3::bytea[])
|
|
||||||
)
|
|
||||||
`,
|
|
||||||
pq.ByteaArray(nodeIDs),
|
|
||||||
pq.ByteaArray(bucketIDs),
|
|
||||||
pq.ByteaArray(serialNumbers))
|
|
||||||
if err != nil {
|
|
||||||
return Error.Wrap(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (queue *ordersDBQueue) GetPendingSerialsBatch(ctx context.Context, size int) (pendingSerials []orders.PendingSerial, done bool, err error) {
|
func (queue *ordersDBQueue) GetPendingSerialsBatch(ctx context.Context, size int) (pendingSerials []orders.PendingSerial, done bool, err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
// TODO: this might end up being WORSE on cockroach because it does a hash-join after a
|
// TODO: no idea of this query makes sense on cockroach. it may do a terrible job with it.
|
||||||
// full scan of the consumed_serials table, but it's massively better on postgres because
|
// but it's blazing fast on postgres and that's where we have the problem! :D :D :D
|
||||||
// it does an indexed anti-join. hopefully we can get rid of the entire serials system
|
|
||||||
// before it matters.
|
|
||||||
|
|
||||||
rows, err := queue.db.Query(ctx, `
|
var rows *sql.Rows
|
||||||
SELECT storage_node_id, bucket_id, serial_number, action, settled, expires_at,
|
switch queue.impl {
|
||||||
|
case dbutil.Postgres:
|
||||||
|
rows, err = queue.tx.Query(ctx, `
|
||||||
|
DELETE
|
||||||
|
FROM pending_serial_queue
|
||||||
|
WHERE
|
||||||
|
ctid = any (array(
|
||||||
|
SELECT
|
||||||
|
ctid
|
||||||
|
FROM pending_serial_queue
|
||||||
|
LIMIT $1
|
||||||
|
))
|
||||||
|
RETURNING storage_node_id, bucket_id, serial_number, action, settled, expires_at, (
|
||||||
coalesce((
|
coalesce((
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM consumed_serials
|
FROM consumed_serials
|
||||||
WHERE
|
WHERE
|
||||||
consumed_serials.storage_node_id = pending_serial_queue.storage_node_id
|
consumed_serials.storage_node_id = pending_serial_queue.storage_node_id
|
||||||
AND consumed_serials.serial_number = pending_serial_queue.serial_number
|
AND consumed_serials.serial_number = pending_serial_queue.serial_number
|
||||||
), 0) as consumed
|
), 0))
|
||||||
|
`, size)
|
||||||
|
case dbutil.Cockroach:
|
||||||
|
rows, err = queue.tx.Query(ctx, `
|
||||||
|
DELETE
|
||||||
|
FROM pending_serial_queue
|
||||||
|
WHERE
|
||||||
|
(storage_node_id, bucket_id, serial_number) = any (array(
|
||||||
|
SELECT
|
||||||
|
(storage_node_id, bucket_id, serial_number)
|
||||||
FROM pending_serial_queue
|
FROM pending_serial_queue
|
||||||
LIMIT $1
|
LIMIT $1
|
||||||
|
))
|
||||||
|
RETURNING storage_node_id, bucket_id, serial_number, action, settled, expires_at, (
|
||||||
|
coalesce((
|
||||||
|
SELECT 1
|
||||||
|
FROM consumed_serials
|
||||||
|
WHERE
|
||||||
|
consumed_serials.storage_node_id = pending_serial_queue.storage_node_id
|
||||||
|
AND consumed_serials.serial_number = pending_serial_queue.serial_number
|
||||||
|
), 0))
|
||||||
`, size)
|
`, size)
|
||||||
|
default:
|
||||||
|
return nil, false, Error.New("unhandled implementation")
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, Error.Wrap(err)
|
return nil, false, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
@ -697,7 +701,6 @@ func (queue *ordersDBQueue) GetPendingSerialsBatch(ctx context.Context, size int
|
|||||||
return nil, false, Error.Wrap(err)
|
return nil, false, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.produced = append(queue.produced, rawPending)
|
|
||||||
size--
|
size--
|
||||||
|
|
||||||
if consumed != 0 {
|
if consumed != 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user