my example was not good tbh
parent
0db7008aac
commit
faa128400f
|
|
@ -0,0 +1 @@
|
||||||
|
https://topicpartition.io/blog/postgres-pubsub-queue-benchmarks
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"pg/src/with"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := with.Context(run); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(ctx context.Context) error {
|
||||||
|
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||||
|
c := fs.String("c", "postgresql://pulsegres:pulsegres@localhost:15432", "conn string")
|
||||||
|
if err := fs.Parse(os.Args[1:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return with.PSQL(ctx, *c, func(pg *sql.DB) error {
|
||||||
|
log.Println("creating tables...")
|
||||||
|
for _, sql := range []string{
|
||||||
|
`CREATE SCHEMA IF NOT EXISTS "pubsub"`,
|
||||||
|
|
||||||
|
`CREATE TABLE IF NOT EXISTS "pubsub"."topic_a" (
|
||||||
|
partition INT PRIMARY KEY,
|
||||||
|
partition_offset BIGINT NOT NULL DEFAULT 0
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE IF NOT EXISTS "pubsub"."topic_a_partition_0" (
|
||||||
|
id UUID NOT NULL DEFAULT GEN_RANDOM_UUID() PRIMARY KEY,
|
||||||
|
partition_offset BIGINT UNIQUE NOT NULL,
|
||||||
|
payload BYTEA NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE IF NOT EXISTS "pubsub"."topic_a_partition_1" (
|
||||||
|
id UUID NOT NULL DEFAULT GEN_RANDOM_UUID() PRIMARY KEY,
|
||||||
|
partition_offset BIGINT UNIQUE NOT NULL,
|
||||||
|
payload BYTEA NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
)`,
|
||||||
|
|
||||||
|
`INSERT INTO "pubsub"."topic_a" (partition, partition_offset) VALUES (0, 0) ON CONFLICT DO NOTHING`,
|
||||||
|
`INSERT INTO "pubsub"."topic_a" (partition, partition_offset) VALUES (1, 0) ON CONFLICT DO NOTHING`,
|
||||||
|
|
||||||
|
`CREATE TABLE IF NOT EXISTS "pubsub"."consumer_partition_offset" (
|
||||||
|
consumer_group TEXT NOT NULL,
|
||||||
|
partition INT REFERENCES "pubsub"."topic_a"("partition"),
|
||||||
|
partition_offset BIGINT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (consumer_group, partition)
|
||||||
|
)`,
|
||||||
|
} {
|
||||||
|
if _, err := pg.ExecContext(ctx, sql); err != nil {
|
||||||
|
return fmt.Errorf("failed setup sql %s: %w", sql, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub := func(a any) error {
|
||||||
|
b, _ := json.Marshal(a)
|
||||||
|
partition := rand.Int() % 2
|
||||||
|
partitionS := strconv.Itoa(partition)
|
||||||
|
_, err := pg.ExecContext(ctx, `
|
||||||
|
WITH reserve AS (
|
||||||
|
UPDATE "pubsub"."topic_a"
|
||||||
|
SET partition_offset=partition_offset+1
|
||||||
|
WHERE partition=`+partitionS+`
|
||||||
|
RETURNING (partition_offset-1) AS offset
|
||||||
|
)
|
||||||
|
INSERT INTO "pubsub"."topic_a_partition_`+partitionS+`" (partition_offset, payload)
|
||||||
|
SELECT reserve.offset, $1 FROM reserve
|
||||||
|
`, b)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sub := func(group string) (any, error) {
|
||||||
|
partition := rand.Int() % 2
|
||||||
|
partitionS := strconv.Itoa(partition)
|
||||||
|
|
||||||
|
if _, err := pg.ExecContext(ctx, `
|
||||||
|
INSERT INTO
|
||||||
|
"pubsub"."consumer_partition_offset"
|
||||||
|
(consumer_group, partition)
|
||||||
|
VALUES
|
||||||
|
($1, $2)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
`, group, partition); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
row := pg.QueryRowContext(ctx, `
|
||||||
|
WITH tip AS (
|
||||||
|
SELECT partition_offset-1
|
||||||
|
FROM "pubsub"."topic_a"
|
||||||
|
WHERE partition=`+partitionS+`
|
||||||
|
)
|
||||||
|
, to_claim AS (
|
||||||
|
SELECT partition_offset
|
||||||
|
FROM "pubsub"."consumer_partition_offset"
|
||||||
|
WHERE consumer_group=$1 AND partition=$2
|
||||||
|
FOR UPDATE SKIP LOCKED
|
||||||
|
)
|
||||||
|
, claimed AS (
|
||||||
|
UPDATE "pubsub"."consumer_partition_offset" consumer_partition_offset
|
||||||
|
SET consumer_partition_offset.partition_offset=to_claim.partition_offset+1
|
||||||
|
FROM to_claim
|
||||||
|
WHERE consumer_partition_offset.consumer_group=$1 AND consumer_partition_offset.partition=$2
|
||||||
|
RETURNING consumer_partition_offset.partition_offset
|
||||||
|
)
|
||||||
|
SELECT partition_offset FROM claimed
|
||||||
|
`, group, partition)
|
||||||
|
if err := row.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result any
|
||||||
|
if err := row.Scan(&result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, row.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
go with.Every(ctx, time.Second, func() {
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
if err := pub(1); err != nil {
|
||||||
|
log.Printf("failed pub: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("pubbed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
with.Every(ctx, time.Second, func() {
|
||||||
|
if err := func() error {
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
group := fmt.Sprintf("group_%d", i)
|
||||||
|
if v, err := sub(group); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
log.Printf("%s => %v", group, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
log.Printf("failed subs: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return ctx.Err()
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue