fix: 修复写队列 busy 恢复、关闭安全、备份与配置构建问题
This commit is contained in:
+38
-5
@@ -1,6 +1,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -10,7 +11,8 @@ import (
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
const dbFileName = "nixmsg.db"
|
||||
// DBFileName 是数据目录下的主库文件名。
|
||||
const DBFileName = "nixmsg.db"
|
||||
|
||||
// DB 持有读写连接与写入队列。
|
||||
type DB struct {
|
||||
@@ -25,7 +27,7 @@ func Open(dataDir, synchronous string) (*DB, error) {
|
||||
if err := os.MkdirAll(dataDir, 0o755); err != nil {
|
||||
return nil, fmt.Errorf("mkdir data_dir: %w", err)
|
||||
}
|
||||
dbPath := filepath.Join(dataDir, dbFileName)
|
||||
dbPath := filepath.Join(dataDir, DBFileName)
|
||||
existed, err := fileExists(dbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -69,10 +71,41 @@ func (d *DB) Close() error {
|
||||
return first
|
||||
}
|
||||
|
||||
// Checkpoint 在写 goroutine 上执行 wal_checkpoint(TRUNCATE)。
|
||||
func (d *DB) Checkpoint(ctx context.Context) error {
|
||||
if d == nil || d.Queue == nil {
|
||||
return fmt.Errorf("store: not open")
|
||||
}
|
||||
return d.Queue.Checkpoint(ctx)
|
||||
}
|
||||
|
||||
// OpenWriter 按 DEVELOPMENT 7.7 打开写连接(带 _txlock=immediate,MaxOpenConns=1)。
|
||||
func OpenWriter(dataDir, synchronous string) (*sql.DB, error) {
|
||||
if err := os.MkdirAll(dataDir, 0o755); err != nil {
|
||||
return nil, fmt.Errorf("mkdir data_dir: %w", err)
|
||||
return openWriter(dataDir, synchronous, true)
|
||||
}
|
||||
|
||||
// OpenExistingWriter 打开已有库的写连接,不创建数据目录;库文件不存在时返回错误。
|
||||
func OpenExistingWriter(dataDir, synchronous string) (*sql.DB, error) {
|
||||
dbPath := filepath.Join(dataDir, DBFileName)
|
||||
ok, err := fileExists(dbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
abs, absErr := filepath.Abs(dbPath)
|
||||
if absErr != nil {
|
||||
abs = dbPath
|
||||
}
|
||||
return nil, fmt.Errorf("database not found: %s", abs)
|
||||
}
|
||||
return openWriter(dataDir, synchronous, false)
|
||||
}
|
||||
|
||||
func openWriter(dataDir, synchronous string, mkdir bool) (*sql.DB, error) {
|
||||
if mkdir {
|
||||
if err := os.MkdirAll(dataDir, 0o755); err != nil {
|
||||
return nil, fmt.Errorf("mkdir data_dir: %w", err)
|
||||
}
|
||||
}
|
||||
dsn, err := buildDSN(dataDir, synchronous, true)
|
||||
if err != nil {
|
||||
@@ -116,7 +149,7 @@ func buildDSN(dataDir, synchronous string, writer bool) (string, error) {
|
||||
if sync != "FULL" && sync != "NORMAL" {
|
||||
return "", fmt.Errorf("invalid sqlite_synchronous: %s", synchronous)
|
||||
}
|
||||
dbPath := filepath.ToSlash(filepath.Join(dataDir, dbFileName))
|
||||
dbPath := filepath.ToSlash(filepath.Join(dataDir, DBFileName))
|
||||
dsn := fmt.Sprintf(
|
||||
"file:%s?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)&_pragma=synchronous(%s)&_pragma=foreign_keys(ON)&_pragma=secure_delete(ON)",
|
||||
dbPath,
|
||||
|
||||
Reference in New Issue
Block a user