Files
Foundry-Scrapping-API/internal/foundry/temp_models/db/utils.go
2026-04-16 18:30:00 +03:00

117 lines
2.3 KiB
Go

package db
import (
"context"
"fmt"
"sync"
"time"
"github.com/jmoiron/sqlx"
)
type AllowedIds interface {
~uint | ~string
}
type InsertId[T AllowedIds] struct {
id T
fieldName string
tableName string
}
type SyncDbOperations struct {
errChan chan error
wg sync.WaitGroup
}
func (s *SyncDbOperations) Wait() error {
return WaitSync(&s.wg, s.errChan)
}
func WaitSync(wg *sync.WaitGroup, errChan chan error) error {
wgDone := make(chan struct{})
go func() {
wg.Wait()
close(wgDone)
}()
select {
case <-wgDone:
return nil
case err := <-errChan:
close(wgDone)
return err
}
}
type Insertable[T AllowedIds] interface {
Insert(tx *sqlx.Tx, relId *InsertId[T]) error
InsertCtx(ctx context.Context, tx *sqlx.Tx, relId *InsertId[T]) error
}
func InsertWithCtx[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data I, relId *InsertId[T]) error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
return data.InsertCtx(ctx, tx, relId)
}
func InsertSlice[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId *InsertId[T]) error {
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
for i := range data {
err := data[i].InsertCtx(ctx, tx, relId)
if err != nil {
return err
}
}
return nil
}
func InsertSliceParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDbOperations, tx *sqlx.Tx, data []I, relId *InsertId[T]) {
syncDb.wg.Add(1)
wg := sync.WaitGroup{}
errChan := make(chan error)
defer close(errChan)
for i := range data {
go func() {
wg.Add(1)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
errChan <- data[i].InsertCtx(ctx, tx, relId)
wg.Done()
}()
}
err := WaitSync(&wg, errChan)
if err != nil {
syncDb.errChan <- err
}
syncDb.wg.Done()
}
func InsertSimpleSliceToTable[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId *InsertId[T]) error {
query := fmt.Sprintf(`
INSERT INTO %s (%s, value)
VALUES (:id, :value)`, relId.tableName, relId.fieldName)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
for i := range data {
_, err := tx.ExecContext(ctx, query, relId.id, data[i])
if err != nil {
return err
}
}
return nil
}