hotfix: move save data to DB (#2)

* start reading save data from DB

* finish migration code

* remove leftover dir creation

* fix import cycle

* remove more dir creation

* update gitignore

* fix pk

* better table creation

* use REPLACE INTO

* fix typo
This commit is contained in:
Up authored and GitHub committed 2024-05-07 17:10:33 -04:00
1 parent 723fe48969
commit 1f95f7c042
10 files changed
+253 -134

No files matched your search

+77 -1
View File
@@ -19,9 +19,11 @@ package db
import (
"database/sql"
"encoding/hex"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"os"
)
var handle *sql.DB
@@ -36,5 +38,79 @@ func Init(username, password, protocol, address, database string) error {
handle.SetMaxOpenConns(1000)
tx, err := handle.Begin()
if err != nil {
panic(err)
}
tx.Exec("CREATE TABLE IF NOT EXISTS systemSaveData (uuid BINARY(16) PRIMARY KEY, data BLOB, timestamp TIMESTAMP)")
tx.Exec("CREATE TABLE IF NOT EXISTS sessionSaveData (uuid BINARY(16), slot TINYINT, data BLOB, timestamp TIMESTAMP, PRIMARY KEY (uuid, slot))")
err = tx.Commit()
if err != nil {
panic(err)
}
// TODO temp code
entries, err := os.ReadDir("userdata")
if err != nil {
log.Fatalln(err)
return nil
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
uuidString := entry.Name()
uuid, err := hex.DecodeString(uuidString)
if err != nil {
log.Printf("failed to decode uuid: %s", err)
continue
}
// store new system data
systemData, err := LegacyReadSystemSaveData(uuid)
if err != nil {
log.Printf("failed to read system save data for %v: %s", uuidString, err)
continue
}
err = StoreSystemSaveData(uuid, systemData)
if err != nil {
log.Fatalf("failed to store system save data for %v: %s\n", uuidString, err)
continue
}
// delete old system data
err = os.Remove("userdata/" + uuidString + "/system.pzs")
if err != nil {
log.Fatalf("failed to remove legacy system save data for %v: %s", uuidString, err)
}
for i := 0; i < 5; i++ {
sessionData, err := LegacyReadSessionSaveData(uuid, i)
if err != nil {
log.Printf("failed to read session save data %v for %v: %s", i, uuidString, err)
continue
}
// store new session data
err = StoreSessionSaveData(uuid, sessionData, i)
if err != nil {
log.Fatalf("failed to store session save data for %v: %s\n", uuidString, err)
}
// delete old session data
filename := "session"
if i != 0 {
filename += fmt.Sprintf("%d", i)
}
err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", uuidString, filename))
if err != nil {
log.Fatalf("failed to remove legacy session save data %v for %v: %s", i, uuidString, err)
}
}
}
return nil
}
+84
View File
@@ -0,0 +1,84 @@
/*
Copyright (C) 2024 Pagefault Games
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package db
import (
"encoding/gob"
"encoding/hex"
"fmt"
"os"
"strconv"
"github.com/klauspost/compress/zstd"
"github.com/pagefaultgames/rogueserver/defs"
)
func LegacyReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var system defs.SystemSaveData
file, err := os.Open("userdata/" + hex.EncodeToString(uuid) + "/system.pzs")
if err != nil {
return system, fmt.Errorf("failed to open save file for reading: %s", err)
}
defer file.Close()
zstdDecoder, err := zstd.NewReader(file)
if err != nil {
return system, fmt.Errorf("failed to create zstd decoder: %s", err)
}
defer zstdDecoder.Close()
err = gob.NewDecoder(zstdDecoder).Decode(&system)
if err != nil {
return system, fmt.Errorf("failed to deserialize save: %s", err)
}
return system, nil
}
func LegacyReadSessionSaveData(uuid []byte, slotID int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData
fileName := "session"
if slotID != 0 {
fileName += strconv.Itoa(slotID)
}
file, err := os.Open(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName))
if err != nil {
return session, fmt.Errorf("failed to open save file for reading: %s", err)
}
defer file.Close()
zstdDecoder, err := zstd.NewReader(file)
if err != nil {
return session, fmt.Errorf("failed to create zstd decoder: %s", err)
}
defer zstdDecoder.Close()
err = gob.NewDecoder(zstdDecoder).Decode(&session)
if err != nil {
return session, fmt.Errorf("failed to deserialize save: %s", err)
}
return session, nil
}
+63
View File
@@ -17,6 +17,12 @@
package db
import (
"bytes"
"encoding/gob"
"github.com/pagefaultgames/rogueserver/defs"
)
func TryAddDailyRunCompletion(uuid []byte, seed string, mode int) (bool, error) {
var count int
err := handle.QueryRow("SELECT COUNT(*) FROM dailyRunCompletions WHERE uuid = ? AND seed = ?", uuid, seed).Scan(&count)
@@ -33,3 +39,60 @@ func TryAddDailyRunCompletion(uuid []byte, seed string, mode int) (bool, error)
return true, nil
}
func ReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var data []byte
err := handle.QueryRow("SELECT data FROM systemSaveData WHERE uuid = ?", uuid).Scan(&data)
reader := bytes.NewReader(data)
system := defs.SystemSaveData{}
err = gob.NewDecoder(reader).Decode(&system)
return system, err
}
func StoreSystemSaveData(uuid []byte, data defs.SystemSaveData) error {
var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(data)
if err != nil {
return err
}
_, err = handle.Exec("INSERT INTO systemSaveData (uuid, data, timestamp) VALUES (?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE data = VALUES(data), timestamp = VALUES(timestamp)", uuid, buf.Bytes())
return err
}
func DeleteSystemSaveData(uuid []byte) error {
_, err := handle.Exec("DELETE FROM systemSaveData WHERE uuid = ?", uuid)
return err
}
func ReadSessionSaveData(uuid []byte, slot int) (defs.SessionSaveData, error) {
var data []byte
err := handle.QueryRow("SELECT data FROM sessionSaveData WHERE uuid = ? AND slot = ?", uuid, slot).Scan(&data)
reader := bytes.NewReader(data)
save := defs.SessionSaveData{}
err = gob.NewDecoder(reader).Decode(&save)
return save, err
}
func StoreSessionSaveData(uuid []byte, data defs.SessionSaveData, slot int) error {
var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(data)
if err != nil {
return err
}
_, err = handle.Exec("REPLACE INTO sessionSaveData (uuid, slot, data, timestamp) VALUES (?, ?, ?, UTC_TIMESTAMP())", uuid, slot, buf.Bytes())
return err
}
func DeleteSessionSaveData(uuid []byte, slot int) error {
_, err := handle.Exec("DELETE FROM sessionSaveData WHERE uuid = ? AND slot = ?", uuid, slot)
return err
}