add setup insert methods
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
1
go.mod
@@ -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
6
go.sum
@@ -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=
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
116
internal/foundry/temp_models/db/utils.go
Normal file
116
internal/foundry/temp_models/db/utils.go
Normal 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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
Reference in New Issue
Block a user