improve upsert perfomance

This commit is contained in:
2024-08-13 23:39:44 +03:00
parent 30e5968e03
commit 25762cbae8
8 changed files with 127 additions and 83 deletions

View File

@ -20,15 +20,14 @@ func NewHandlersBuilder() *handlersBuilder {
// MountStatsHandlers mounts stats related handlers.
func (h *handlersBuilder) MountStatsHandlers(sr store.Stats, log *slog.Logger) {
log = log.With(slog.String("api", "http"))
// log = log.With(slog.String("api", "http"))
// mws := multipleMiddlewares(
// middlewarePanicRecovery(log),
// middlewareLogger(log),
// )
mws := multipleMiddlewares(
middlewarePanicRecovery(log),
middlewareLogger(log),
)
h.mux.Handle("/api/v1/stats/", mws(listStatsHandler(sr)))
h.mux.Handle("/api/v1/stats/{id}", mws(postStatsHandler(sr)))
h.mux.Handle("/api/v1/stats/", listStatsHandler(sr))
h.mux.Handle("/api/v1/stats/{id}", postStatsHandler(sr))
}
func (s *handlersBuilder) MountProfileHandlers() {

View File

@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"sync"
"time"
"git.loyso.art/frx/devsim/internal/entities"
@ -30,11 +31,16 @@ func Dial(ctx context.Context, uri string) (*repository, error) {
return nil, fmt.Errorf("pinging mongo database: %w", err)
}
return &repository{client: client}, nil
updateOptions := options.Update().SetUpsert(true)
return &repository{
client: client,
updateOptions: updateOptions,
}, nil
}
type repository struct {
client *mongo.Client
client *mongo.Client
updateOptions *options.UpdateOptions
}
func (r *repository) Close() error {
@ -46,22 +52,24 @@ func (r *repository) Close() error {
func (r *repository) StatsRepository() statsRepository {
return statsRepository{
collection: r.client.Database("bench").Collection("device_stats"),
collection: r.client.Database("bench").Collection("device_stats"),
updateOptions: r.updateOptions,
}
}
type statsRepository struct {
collection *mongo.Collection
collection *mongo.Collection
updateOptions *options.UpdateOptions
}
type deviceStatsDB struct {
UpdatedAt time.Time `bson:"updated_at"`
DeviceID string `bson:"_id"`
IncomingTraffic int `bson:"inc_traffic"`
OutgoinfTraffic int `bson:"out_traffic"`
IncomingRPS int `bson:"inc_rps"`
ReadRPS int `bson:"read_rps"`
WriteRPS int `bson:"write_rps"`
UpdatedAt time.Time `bson:"updated_at"`
}
func (s deviceStatsDB) asDomain() entities.DeviceStatistics {
@ -76,15 +84,26 @@ func (s deviceStatsDB) asDomain() entities.DeviceStatistics {
}
}
func (r statsRepository) Upsert(ctx context.Context, stats entities.DeviceStatistics) error {
opts := options.Update().SetUpsert(true)
var bsonSyncPool = sync.Pool{
New: func() any {
m := make(bson.M, 1)
return &m
},
}
filter := bson.D{
{
Key: "_id",
Value: stats.ID,
},
}
func getPoolD() *bson.M {
return bsonSyncPool.Get().(*bson.M)
}
func putPoolD(m *bson.M) {
bsonSyncPool.Put(m)
}
type filterByID struct {
ID entities.DeviceID `bson:"_id"`
}
func (r statsRepository) Upsert(ctx context.Context, stats entities.DeviceStatistics) error {
document := deviceStatsDB{
DeviceID: string(stats.ID),
IncomingTraffic: stats.IncomingTrafficBytes,
@ -95,9 +114,13 @@ func (r statsRepository) Upsert(ctx context.Context, stats entities.DeviceStatis
UpdatedAt: time.Now(),
}
// updatePtr := getPoolD()
// update := *updatePtr
// defer putPoolD(updatePtr)
update := bson.M{"$set": document}
_, err := r.collection.UpdateOne(ctx, filter, update, opts)
_, err := r.collection.UpdateOne(ctx, filterByID{ID: stats.ID}, update, r.updateOptions)
if err != nil {
return fmt.Errorf("inserting: %w", err)
}

View File

@ -31,7 +31,7 @@ type repository struct {
func (r *repository) StatsRepository() statsRepository {
return statsRepository{
db: r.db,
q: queries.New(r.db),
}
}
@ -41,7 +41,7 @@ func (r *repository) Close() error {
}
type statsRepository struct {
db *pgxpool.Pool
q *queries.Queries
}
type deviceStatsDB struct {
@ -67,7 +67,7 @@ func (s deviceStatsDB) asDomain() entities.DeviceStatistics {
}
func (r statsRepository) Upsert(ctx context.Context, stats entities.DeviceStatistics) error {
err := queries.New(r.db).UpsertDeviceMetrics(ctx, queries.UpsertDeviceMetricsParams{
err := r.q.UpsertDeviceMetrics(ctx, queries.UpsertDeviceMetricsParams{
DeviceID: string(stats.ID),
IncTraffic: int32(stats.IncomingTrafficBytes),
OutTraffic: int32(stats.OutgoingTrafficBytes),
@ -83,7 +83,7 @@ func (r statsRepository) Upsert(ctx context.Context, stats entities.DeviceStatis
}
func (r statsRepository) List(ctx context.Context) (out []entities.DeviceStatistics, err error) {
stats, err := queries.New(r.db).ListDeviceStats(ctx)
stats, err := r.q.ListDeviceStats(ctx)
if err != nil {
return nil, fmt.Errorf("listing device stats: %w", err)
}