add setup insert methods

This commit is contained in:
lbenedar
2026-04-16 18:30:00 +03:00
parent 69d3d38ab7
commit 1b7c7e9ae3
23 changed files with 818 additions and 144 deletions

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
"database/sql"
"flag" "flag"
"log" "log"
"log/slog" "log/slog"
@@ -14,6 +13,7 @@ import (
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
@@ -47,8 +47,8 @@ type application struct {
var version = "0.1.0" var version = "0.1.0"
func openDB(cfg config) (*sql.DB, error) { func openDB(cfg config) (*sqlx.DB, error) {
db, err := sql.Open("sqlite3", cfg.db.dsn) db, err := sqlx.Open("sqlite3", cfg.db.dsn)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -690,18 +690,18 @@ CREATE TABLE IF NOT EXISTS package_warnings_data (
); );
CREATE TABLE IF NOT EXISTS package_warnings_data_warning ( CREATE TABLE IF NOT EXISTS package_warnings_data_warning (
id TEXT PRIMARY KEY, id INTEGER PRIMARY KEY,
warning VARCHAR(128) NOT NULL, value VARCHAR(128) NOT NULL,
package_warnings_data_id TEXT, package_warnings_data_id TEXT,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS package_warnings_data_error ( CREATE TABLE IF NOT EXISTS package_warnings_data_error (
id TEXT PRIMARY KEY, id INTEGER PRIMARY KEY,
error VARCHAR(128) NOT NULL, value VARCHAR(128) NOT NULL,
package_warnings_data_id TEXT, package_warnings_data_id TEXT,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
@@ -1175,7 +1175,7 @@ CREATE TABLE IF NOT EXISTS files_storage (
); );
CREATE TABLE IF NOT EXISTS setup_language ( CREATE TABLE IF NOT EXISTS setup_language (
id TEXT PRIMARY KEY, id INTEGER PRIMARY KEY,
label VARCHAR(128) NOT NULL, label VARCHAR(128) NOT NULL,
@@ -1189,7 +1189,7 @@ CREATE TABLE IF NOT EXISTS setup_language_module (
label VARCHAR(128) NOT NULL, label VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL, path VARCHAR(128) NOT NULL,
setup_language_id TEXT, setup_language_id INTEGER,
FOREIGN KEY (setup_language_id) REFERENCES setup_language(id) ON DELETE CASCADE FOREIGN KEY (setup_language_id) REFERENCES setup_language(id) ON DELETE CASCADE
); );

1
go.mod
View File

@@ -54,6 +54,7 @@ require (
github.com/in-toto/in-toto-golang v0.9.0 // indirect github.com/in-toto/in-toto-golang v0.9.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/klauspost/compress v1.18.3 // indirect github.com/klauspost/compress v1.18.3 // indirect

6
go.sum
View File

@@ -1,5 +1,6 @@
cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
@@ -152,6 +153,7 @@ github.com/go-openapi/swag/yamlutils v0.25.3 h1:LKTJjCn/W1ZfMec0XDL4Vxh8kyAnv1or
github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao= github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao=
github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw= github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw=
github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc= github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
@@ -195,6 +197,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
@@ -207,10 +211,12 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.39 h1:sIwSjlJGOaRJjw44/HXaeTblZMjseqr6OOio1tz/+JI= github.com/mattn/go-sqlite3 v1.14.39 h1:sIwSjlJGOaRJjw44/HXaeTblZMjseqr6OOio1tz/+JI=
github.com/mattn/go-sqlite3 v1.14.39/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.39/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=

View File

@@ -5,6 +5,8 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"time" "time"
"github.com/jmoiron/sqlx"
) )
type StateType int type StateType int
@@ -44,7 +46,7 @@ type Options struct {
} }
type FoundryStateModel struct { type FoundryStateModel struct {
DB *sql.DB DB *sqlx.DB
} }
func (m FoundryStateModel) Insert(state *FoundryState) error { func (m FoundryStateModel) Insert(state *FoundryState) error {

View File

@@ -1,6 +1,6 @@
package db package db
import "database/sql" import "github.com/jmoiron/sqlx"
// var ( // var (
// ErrRecordNotFound = errors.New("record not found") // ErrRecordNotFound = errors.New("record not found")
@@ -21,7 +21,7 @@ type Models struct {
// } // }
// } // }
func NewModels(db *sql.DB) *Models { func NewModels(db *sqlx.DB) *Models {
return &Models{ return &Models{
FoundryState: FoundryStateModel{DB: db}, FoundryState: FoundryStateModel{DB: db},
} }

View File

@@ -1,7 +1,99 @@
package db package db
import (
"context"
"fmt"
"sync"
"github.com/jmoiron/sqlx"
)
type Files struct { type Files struct {
ID uint ID uint
Storages []string Storages []FilesStorage
}
func (f *Files) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO files (%s)
VALUES ($1)
RETURNING id`, data.fieldName)
args := []any{data.id}
err := tx.QueryRowx(query, args...).Scan(&f.ID)
if err != nil {
return err
}
syncDB := SyncDbOperations{
wg: sync.WaitGroup{},
errChan: make(chan error),
}
InsertSliceParallel[uint](&syncDB, tx, f.Storages, &InsertId[uint]{id: f.ID})
return syncDB.Wait()
}
func (f *Files) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO files (%s)
VALUES ($1)
RETURNING id`, data.fieldName)
args := []any{data.id}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&f.ID)
if err != nil {
return err
}
syncDB := SyncDbOperations{
wg: sync.WaitGroup{},
errChan: make(chan error),
}
InsertSliceParallel(&syncDB, tx, f.Storages, &InsertId[uint]{id: f.ID})
return syncDB.Wait()
}
type FilesStorage struct {
ID uint
Storage string
}
func (f FilesStorage) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
query := `
INSERT INTO files (files_id, storage)
VALUES ($1, $2)
RETURNING id`
args := []any{data.id, f.Storage}
err := tx.QueryRowx(query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
}
func (f FilesStorage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
const query = `
INSERT INTO featured_content (files_id, storage)
VALUES ($1, $2)
RETURNING id`
args := []any{data.id, f.Storage}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
} }

View File

@@ -1,6 +1,9 @@
package db package db
import "time" import (
"database/sql"
"time"
)
type FoundryDataType string type FoundryDataType string
@@ -17,3 +20,7 @@ type FoundryData struct {
Game *Game Game *Game
CreatedAt time.Time CreatedAt time.Time
} }
type FoundryDataModel struct {
DB *sql.DB
}

View File

@@ -11,13 +11,13 @@ type Game struct {
Files Files Files Files
Options GameOptions Options GameOptions
Release Release Release Release
World World World *World
System System System *System
CoreUpdate CoreUpdate CoreUpdate CoreUpdate
SystemUpdate SystemUpdate SystemUpdate SystemUpdate
ActiveUsers []string ActiveUsers []string
Modules []Module Modules []*Module
PackageWarnings []PackageWarning PackageWarnings []*PackageWarning
Packs []Pack Packs []Pack
Messages []Message Messages []Message
Combats []Combat Combats []Combat

View File

@@ -1,5 +1,11 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type Language struct { type Language struct {
ID uint ID uint
@@ -15,9 +21,77 @@ type SetupLanguage struct {
Modules []SetupLanguageModule Modules []SetupLanguageModule
} }
func (l SetupLanguage) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
const query = `
INSERT INTO setup_language (setup_id, label)
VALUES ($1, $2)
RETURNING id`
args := []any{data.id, l.Label}
err := tx.QueryRowx(query, args...).Scan(&l.ID)
if err != nil {
return err
}
InsertSlice(tx, l.Modules, &InsertId[string]{id: l.ID})
return nil
}
func (l SetupLanguage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
const query = `
INSERT INTO setup_language (setup_id, label)
VALUES ($1, $2)
RETURNING id`
args := []any{data.id, l.Label}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&l.ID)
if err != nil {
return err
}
InsertSlice(tx, l.Modules, &InsertId[string]{id: l.ID})
return nil
}
type SetupLanguageModule struct { type SetupLanguageModule struct {
ID string ID string
Label string Label string
Path string Path string
} }
func (l SetupLanguageModule) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
const query = `
INSERT INTO setup_language_module (setup_language_id, label, path)
VALUES ($1, $2, $3)
RETURNING id`
args := []any{data.id, l.Label, l.Path}
err := tx.QueryRowx(query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
func (l SetupLanguageModule) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
const query = `
INSERT INTO setup_language_module (setup_language_id, label, path)
VALUES ($1, $2, $3)
RETURNING id`
args := []any{data.id, l.Label, l.Path}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,11 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type GameOptions struct { type GameOptions struct {
ID uint ID uint
@@ -8,23 +14,95 @@ type GameOptions struct {
Port int Port int
} }
func (g *GameOptions) Insert(tx *sqlx.Tx, gameId *InsertId[uint]) error {
query := `
INSERT INTO featured_content (game_id, language, update_channel, port)
VALUES ($1, $2, $3, $4)
RETURNING id`
args := []any{gameId.id, g.Language, g.UpdateChannel, g.Port}
err := tx.QueryRowx(query, args...).Scan(&g.ID)
if err != nil {
return err
}
return nil
}
func (g *GameOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, gameId *InsertId[uint]) error {
query := `
INSERT INTO featured_content (game_id, language, update_channel, port)
VALUES ($1, $2, $3, $4)
RETURNING id`
args := []any{gameId.id, g.Language, g.UpdateChannel, g.Port}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&g.ID)
if err != nil {
return err
}
return nil
}
type SetupOptions struct { type SetupOptions struct {
ID uint ID uint
CompressSocket bool
CompressStatic bool
CSSTheme string CSSTheme string
DataPath string DataPath string
Fullscreen bool
Hostname string Hostname string
HotReload bool
Language string Language string
LocalHostname string LocalHostname string
UpdateChannel string
Port int Port int
CompressSocket bool
CompressStatic bool
Fullscreen bool
HotReload bool
ProxySSL bool ProxySSL bool
Telemetry bool Telemetry bool
UpdateChannel string
Upnp bool Upnp bool
DeleteNEDB bool DeleteNEDB bool
NoBackups bool NoBackups bool
} }
func (s *SetupOptions) Insert(tx *sqlx.Tx, setupId *InsertId[uint]) error {
query := `
INSERT INTO featured_content (setup_id, compress_socket, compress_static, css_theme, data_path,
fullscreen, hostname, hot_reload, language, local_hostname, port,
proxy_ssl, telemetry, update_channel, upnp, delete_nedb, no_backups)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
RETURNING id`
args := []any{setupId.id, s.CompressSocket, s.CompressStatic, s.CSSTheme, s.DataPath,
s.Fullscreen, s.Hostname, s.HotReload, s.Language, s.LocalHostname, s.Port,
s.ProxySSL, s.Telemetry, s.UpdateChannel, s.Upnp, s.DeleteNEDB, s.NoBackups}
err := tx.QueryRowx(query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}
func (s *SetupOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, setupId *InsertId[uint]) error {
query := `
INSERT INTO featured_content (setup_id, compress_socket, compress_static, css_theme, data_path,
fullscreen, hostname, hot_reload, language, local_hostname, port,
proxy_ssl, telemetry, update_channel, upnp, delete_nedb, no_backups)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
RETURNING id`
args := []any{setupId.id, s.CompressSocket, s.CompressStatic, s.CSSTheme, s.DataPath,
s.Fullscreen, s.Hostname, s.HotReload, s.Language, s.LocalHostname, s.Port,
s.ProxySSL, s.Telemetry, s.UpdateChannel, s.Upnp, s.DeleteNEDB, s.NoBackups}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type PackageWarningsData struct { type PackageWarningsData struct {
ID string ID string
@@ -10,9 +17,89 @@ type PackageWarningsData struct {
Manifest string Manifest string
} }
func (p *PackageWarningsData) InsertSliceType(tx *sqlx.Tx, data *InsertId[string], sliceType string) error {
query := fmt.Sprintf(`
INSERT INTO package_warnings_data (%s, id, type, reinstallable, manifest)
VALUES ($1, $2, $3, $4, $5)`, data.fieldName)
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.Exec(query, args...)
if err != nil {
return err
}
return nil
}
func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
query := fmt.Sprintf(`
INSERT INTO package_warnings_data (%s, id, type, reinstallable, manifest)
VALUES ($1, $2, $3, $4, $5)`, data.fieldName)
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.Exec(query, args...)
if err != nil {
return err
}
return nil
}
func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
query := fmt.Sprintf(`
INSERT INTO package_warnings_data (%s, id, type, reinstallable, manifest)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`, data.fieldName)
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.ExecContext(ctx, query, args...)
if err != nil {
return err
}
return nil
}
type PackageWarning struct { type PackageWarning struct {
ID string ID string
Key string Key string
Value PackageWarningsData Value PackageWarningsData
} }
func (p *PackageWarning) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO package_warnings (%s, id)
VALUES ($1, $2)`, data.fieldName)
args := []any{data.id, p.ID}
_, err := tx.Execx(query, args...)
if err != nil {
return err
}
InsertWithCtx(tx, &p.Value, &InsertId[string]{id: p.ID})
return nil
}
func (p *PackageWarning) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO package_warnings (%s, id)
VALUES ($1, $2)`, data.fieldName)
args := []any{data.id, p.ID}
_, err := tx.Exec(query, args...)
if err != nil {
return err
}
InsertWithCtx(tx, &p.Value, &InsertId[string]{id: p.ID})
return nil
}

View File

@@ -3,7 +3,10 @@ package db
type Relationships struct { type Relationships struct {
ID uint ID uint
Data []RelationshipsData Systems []RelationshipsData
Requires []RelationshipsData
Recommends []RelationshipsData
Conflicts []RelationshipsData
} }
type RelationshipsData struct { type RelationshipsData struct {

View File

@@ -1,14 +1,53 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Release struct { type Release struct {
ID uint ID uint
Generation int Generation int
Channel string
Suffix string
Build int Build int
NodeVersion int NodeVersion int
MaxGeneration int MaxGeneration int
MaxStableGeneration int MaxStableGeneration int
Time int64 Time int64
Channel string
Suffix string
}
func (r *Release) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO release_ (%s, generation, channel, suffix, build, node_version, max_generation, max_stable_generation, time)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id`, data.fieldName)
args := []any{data.id, r.Generation, r.Channel, r.Suffix, r.Build, r.NodeVersion, r.MaxGeneration, r.MaxStableGeneration, r.Time}
err := tx.QueryRowx(query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
}
func (r *Release) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO release_ (%s, generation, channel, suffix, build, node_version, max_generation, max_stable_generation, time)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id`, data.fieldName)
args := []any{data.id, r.Generation, r.Channel, r.Suffix, r.Build, r.NodeVersion, r.MaxGeneration, r.MaxStableGeneration, r.Time}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
} }

View File

@@ -1,21 +1,72 @@
package db package db
import (
"context"
"sync"
"time"
"github.com/jmoiron/sqlx"
)
type Setup struct { type Setup struct {
ID uint ID uint
CreatedAt time.Time
IsAdmin bool IsAdmin bool
IsSetup bool IsSetup bool
CoreUpdate CoreUpdate CoreUpdate CoreUpdate //+
FeaturedContent FeaturedContent FeaturedContent FeaturedContent //+
Files Files Files Files //+
Options SetupOptions Options *SetupOptions //+
Release Release Release Release //+
Languages []SetupLanguage Languages []SetupLanguage //+
Modules []Module Modules []*Module
News []News News []News //+
PackageWarnings []PackageWarning PackageWarnings []*PackageWarning
Systems []System Systems []*System
Worlds []World Worlds []*World
}
func (s *Setup) Insert(db *sqlx.DB) error {
tx := db.MustBegin()
defer tx.Rollback()
const query = `
INSERT INTO setup (is_admin, is_setup)
VALUES ($1, $2)
RETURNING id, created_at`
args := []any{s.IsAdmin, s.IsSetup}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err := tx.QueryRowContext(ctx, query, args...).Scan(&s.ID, &s.CreatedAt)
if err != nil {
return err
}
id := InsertId[uint]{id: s.ID, fieldName: "setup_id"}
dataSync := SyncDbOperations{
wg: sync.WaitGroup{},
errChan: make(chan error),
}
defer close(dataSync.errChan)
go InsertSliceParallel(&dataSync, tx, s.News, &id)
go InsertSliceParallel(&dataSync, tx, s.Languages, &id)
InsertWithCtx(tx, &s.FeaturedContent, &id)
InsertWithCtx(tx, &s.Files, &id)
InsertWithCtx(tx, &s.Release, &id)
InsertWithCtx(tx, &s.CoreUpdate, &id)
err = dataSync.Wait()
if err != nil {
return err
}
return tx.Commit()
} }
type FeaturedContent struct { type FeaturedContent struct {
@@ -27,6 +78,38 @@ type FeaturedContent struct {
Image string Image string
} }
func (f *FeaturedContent) Insert(tx *sqlx.Tx, setup *InsertId[uint]) error {
const query = `
INSERT INTO featured_content (setup_id, title, caption, url, image)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`
args := []any{setup.id, f.Title, f.Caption, f.URL, f.Image}
err := tx.QueryRowx(query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
}
func (f *FeaturedContent) InsertCtx(ctx context.Context, tx *sqlx.Tx, setup *InsertId[uint]) error {
const query = `
INSERT INTO featured_content (setup_id, title, caption, url, image)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`
args := []any{setup.id, f.Title, f.Caption, f.URL, f.Image}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
}
type News struct { type News struct {
ID uint ID uint
@@ -35,3 +118,35 @@ type News struct {
URL string URL string
Image string Image string
} }
func (n News) Insert(tx *sqlx.Tx, setup *InsertId[uint]) error {
const insertNews = `
INSERT INTO news (setup_id, title, caption, url, image)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`
args := []any{setup.id, n.Title, n.Caption, n.URL, n.Image}
err := tx.QueryRow(insertNews, args...).Scan(&n.ID)
if err != nil {
return err
}
return nil
}
func (n News) InsertCtx(ctx context.Context, tx *sqlx.Tx, setup *InsertId[uint]) error {
const insertNews = `
INSERT INTO news (setup_id, title, caption, url, image)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`
args := []any{setup.id, n.Title, n.Caption, n.URL, n.Image}
err := tx.QueryRowContext(ctx, insertNews, args...).Scan(&n.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type CoreUpdate struct { type CoreUpdate struct {
ID uint ID uint
@@ -12,6 +19,38 @@ type CoreUpdate struct {
WillDisableModules bool WillDisableModules bool
} }
func (c *CoreUpdate) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO core_update (%s, has_update, can_update, could_reach_website, slow_response, version, channel, will_disable_modules)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id`, data.fieldName)
args := []any{data.id, c.HasUpdate, c.CanUpdate, c.CouldReachWebsite, c.SlowResponse, c.Version, c.Channel, c.WillDisableModules}
err := tx.QueryRowx(query, args...).Scan(&c.ID)
if err != nil {
return err
}
return nil
}
func (c *CoreUpdate) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
query := fmt.Sprintf(`
INSERT INTO core_update (%s, has_update, can_update, could_reach_website, slow_response, version, channel, will_disable_modules)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id`, data.fieldName)
args := []any{data.id, c.HasUpdate, c.CanUpdate, c.CouldReachWebsite, c.SlowResponse, c.Version, c.Channel, c.WillDisableModules}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&c.ID)
if err != nil {
return err
}
return nil
}
type SystemUpdate struct { type SystemUpdate struct {
ID uint ID uint

View File

@@ -0,0 +1,116 @@
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
}

View File

@@ -12,7 +12,10 @@ func (f *Files) ToDB(dest *db.Files) bool {
return false return false
} }
copy(dest.Storages, f.Storages) dest.Storages = make([]db.FilesStorage, len(f.Storages))
for i := range f.Storages {
dest.Storages[i].Storage = f.Storages[i]
}
return true return true
} }

View File

@@ -44,50 +44,54 @@ type Module struct {
// ModulesFlags ModulesFlags `json:"flags,omitempty"` // ModulesFlags ModulesFlags `json:"flags,omitempty"`
} }
func (m *Module) ToDB(dest *db.Module) bool { func (m *Module) ToDB(dest **db.Module) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = m.ID module := &db.Module{
dest.Title = m.Title ID: m.ID,
dest.Description = m.Description Title: m.Title,
dest.URL = m.URL Description: m.Description,
dest.License = m.License URL: m.URL,
dest.Readme = m.Readme License: m.License,
dest.Bugs = m.Bugs Readme: m.Readme,
dest.Changelog = m.Changelog Bugs: m.Bugs,
dest.Version = m.Version Changelog: m.Changelog,
dest.Socket = m.Socket Version: m.Version,
dest.Manifest = m.Manifest Socket: m.Socket,
dest.Download = m.Download Manifest: m.Manifest,
dest.Protected = m.Protected Download: m.Download,
dest.Exclusive = m.Exclusive Protected: m.Protected,
dest.PersistentStorage = m.PersistentStorage Exclusive: m.Exclusive,
dest.CoreTranslation = m.CoreTranslation PersistentStorage: m.PersistentStorage,
dest.Library = m.Library CoreTranslation: m.CoreTranslation,
dest.Availability = m.Availability Library: m.Library,
dest.Locked = m.Locked Availability: m.Availability,
dest.Owned = m.Owned Locked: m.Locked,
dest.HasStorage = m.HasStorage Owned: m.Owned,
dest.Active = m.Active HasStorage: m.HasStorage,
Active: m.Active,
}
copy(dest.Scripts, m.Scripts) copy(module.Scripts, m.Scripts)
copy(dest.Esmodules, m.Esmodules) copy(module.Esmodules, m.Esmodules)
copy(dest.Tags, m.Tags) copy(module.Tags, m.Tags)
m.Compatibility.ToDB(&dest.Compatibility) m.Compatibility.ToDB(&module.Compatibility)
m.Relationships.ToDB(&dest.Relationships) m.Relationships.ToDB(&module.Relationships)
m.DocumentTypes.ToDB(&dest.DocumentTypes) m.DocumentTypes.ToDB(&module.DocumentTypes)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Authors, m.Authors) go CopySliceToDBParallel(&wg, &module.Authors, m.Authors)
go CopySliceToDBParallel(&wg, &dest.Media, m.Media) go CopySliceToDBParallel(&wg, &module.Media, m.Media)
go CopySliceToDBParallel(&wg, &dest.Styles, m.Styles) go CopySliceToDBParallel(&wg, &module.Styles, m.Styles)
go CopySliceToDBParallel(&wg, &dest.Languages, m.Languages) go CopySliceToDBParallel(&wg, &module.Languages, m.Languages)
go CopySliceToDBParallel(&wg, &dest.Packs, m.Packs) go CopySliceToDBParallel(&wg, &module.Packs, m.Packs)
go CopySliceToDBParallel(&wg, &dest.PackFolders, m.PackFolders) go CopySliceToDBParallel(&wg, &module.PackFolders, m.PackFolders)
wg.Wait() wg.Wait()
*dest = module
return true return true
} }

View File

@@ -43,49 +43,53 @@ type System struct {
// SystemFlags SystemFlags `json:"flags"` // SystemFlags SystemFlags `json:"flags"`
} }
func (s *System) ToDB(dest *db.System) bool { func (s *System) ToDB(dest **db.System) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = s.ID system := &db.System{
dest.Title = s.Title ID: s.ID,
dest.Description = s.Description Title: s.Title,
dest.URL = s.URL Description: s.Description,
dest.License = s.License URL: s.URL,
dest.Bugs = s.Bugs License: s.License,
dest.Changelog = s.Changelog Bugs: s.Bugs,
dest.Version = s.Version Changelog: s.Changelog,
dest.Socket = s.Socket Version: s.Version,
dest.Manifest = s.Manifest Socket: s.Socket,
dest.Download = s.Download Manifest: s.Manifest,
dest.Protected = s.Protected Download: s.Download,
dest.Exclusive = s.Exclusive Protected: s.Protected,
dest.PersistentStorage = s.PersistentStorage Exclusive: s.Exclusive,
dest.Background = s.Background PersistentStorage: s.PersistentStorage,
dest.PrimaryTokenAttribute = s.PrimaryTokenAttribute Background: s.Background,
dest.Availability = s.Availability PrimaryTokenAttribute: s.PrimaryTokenAttribute,
dest.Locked = s.Locked Availability: s.Availability,
dest.Owned = s.Owned Locked: s.Locked,
dest.HasStorage = s.HasStorage Owned: s.Owned,
HasStorage: s.HasStorage,
}
copy(dest.Scripts, s.Scripts) copy(system.Scripts, s.Scripts)
copy(dest.Esmodules, s.Esmodules) copy(system.Esmodules, s.Esmodules)
copy(dest.Tags, s.Tags) copy(system.Tags, s.Tags)
s.Compatibility.ToDB(&dest.Compatibility) s.Compatibility.ToDB(&system.Compatibility)
s.Relationships.ToDB(&dest.Relationships) s.Relationships.ToDB(&system.Relationships)
s.DocumentTypes.ToDB(&dest.DocumentTypes) s.DocumentTypes.ToDB(&system.DocumentTypes)
s.Grid.ToDB(&dest.Grid) s.Grid.ToDB(&system.Grid)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Authors, s.Authors) go CopySliceToDBParallel(&wg, &system.Authors, s.Authors)
go CopySliceToDBParallel(&wg, &dest.Media, s.Media) go CopySliceToDBParallel(&wg, &system.Media, s.Media)
go CopySliceToDBParallel(&wg, &dest.Styles, s.Styles) go CopySliceToDBParallel(&wg, &system.Styles, s.Styles)
go CopySliceToDBParallel(&wg, &dest.Languages, s.Languages) go CopySliceToDBParallel(&wg, &system.Languages, s.Languages)
go CopySliceToDBParallel(&wg, &dest.Packs, s.Packs) go CopySliceToDBParallel(&wg, &system.Packs, s.Packs)
go CopySliceToDBParallel(&wg, &dest.PackFolders, s.PackFolders) go CopySliceToDBParallel(&wg, &system.PackFolders, s.PackFolders)
wg.Wait() wg.Wait()
*dest = system
return true return true
} }

View File

@@ -28,8 +28,8 @@ func HotbarToDB(dest *[]db.UserHotbar, src map[int]string) {
} }
} }
func PackageWarningsToDB(dest *[]db.PackageWarning, src map[string]PackageWarningsData) { func PackageWarningsToDB(dest *[]*db.PackageWarning, src map[string]PackageWarningsData) {
*dest = make([]db.PackageWarning, len(src)) *dest = make([]*db.PackageWarning, len(src))
i := 0 i := 0
for k, v := range src { for k, v := range src {

View File

@@ -43,48 +43,52 @@ type World struct {
// Flags any `json:"flags"` // Flags any `json:"flags"`
} }
func (w *World) ToDB(dest *db.World) bool { func (w *World) ToDB(dest **db.World) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = w.ID world := &db.World{
dest.Title = w.Title ID: w.ID,
dest.Description = w.Description Title: w.Title,
dest.Version = w.Version Description: w.Description,
dest.Socket = w.Socket Version: w.Version,
dest.Protected = w.Protected Socket: w.Socket,
dest.Exclusive = w.Exclusive Protected: w.Protected,
dest.PersistentStorage = w.PersistentStorage Exclusive: w.Exclusive,
dest.System = w.System PersistentStorage: w.PersistentStorage,
dest.Background = w.Background System: w.System,
dest.JoinTheme = w.JoinTheme Background: w.Background,
dest.CoreVersion = w.CoreVersion JoinTheme: w.JoinTheme,
dest.SystemVersion = w.SystemVersion CoreVersion: w.CoreVersion,
dest.LastPlayed = w.LastPlayed SystemVersion: w.SystemVersion,
dest.Playtime = w.Playtime LastPlayed: w.LastPlayed,
dest.NextSession = w.NextSession Playtime: w.Playtime,
dest.Availability = w.Availability NextSession: w.NextSession,
dest.Locked = w.Locked Availability: w.Availability,
dest.Owned = w.Owned Locked: w.Locked,
dest.HasStorage = w.HasStorage Owned: w.Owned,
HasStorage: w.HasStorage,
}
copy(dest.Scripts, w.Scripts) copy(world.Scripts, w.Scripts)
copy(dest.Esmodules, w.Esmodules) copy(world.Esmodules, w.Esmodules)
copy(dest.Tags, w.Tags) copy(world.Tags, w.Tags)
w.Compatibility.ToDB(&dest.Compatibility) w.Compatibility.ToDB(&world.Compatibility)
w.Relationships.ToDB(&dest.Relationships) w.Relationships.ToDB(&world.Relationships)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Authors, w.Authors) go CopySliceToDBParallel(&wg, &world.Authors, w.Authors)
go CopySliceToDBParallel(&wg, &dest.Media, w.Media) go CopySliceToDBParallel(&wg, &world.Media, w.Media)
go CopySliceToDBParallel(&wg, &dest.Styles, w.Styles) go CopySliceToDBParallel(&wg, &world.Styles, w.Styles)
go CopySliceToDBParallel(&wg, &dest.Languages, w.Languages) go CopySliceToDBParallel(&wg, &world.Languages, w.Languages)
go CopySliceToDBParallel(&wg, &dest.Packs, w.Packs) go CopySliceToDBParallel(&wg, &world.Packs, w.Packs)
go CopySliceToDBParallel(&wg, &dest.PackFolders, w.PackFolders) go CopySliceToDBParallel(&wg, &world.PackFolders, w.PackFolders)
wg.Wait() wg.Wait()
*dest = world
return true return true
} }

View File

@@ -1,7 +1,6 @@
package transport package transport
import ( import (
"database/sql"
"log/slog" "log/slog"
"sync" "sync"
"time" "time"
@@ -10,6 +9,7 @@ import (
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/jmoiron/sqlx"
) )
type FoundryTransport struct { type FoundryTransport struct {
@@ -32,7 +32,7 @@ type FoundryTransport struct {
Logger *slog.Logger Logger *slog.Logger
} }
func NewFoundryTransport(dbConn *sql.DB, logger *slog.Logger, httpConfig *requests.FoundryHttpRequest) *FoundryTransport { func NewFoundryTransport(dbConn *sqlx.DB, logger *slog.Logger, httpConfig *requests.FoundryHttpRequest) *FoundryTransport {
return &FoundryTransport{ return &FoundryTransport{
CurrWsId: 0, CurrWsId: 0,
ExchangeChan: types.ExchangeChannels{ ExchangeChan: types.ExchangeChannels{