Enha: db use same connection to avoid db locking
This commit is contained in:
		| @@ -28,6 +28,7 @@ func (cm *CronManager) Start() { | ||||
| 			cm.CleanupRooms() | ||||
| 			cm.CleanupActions() | ||||
| 			cm.CleanupPlayersRoom() | ||||
| 			ticker.Reset(30 * time.Second) | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|   | ||||
| @@ -24,16 +24,11 @@ func init() { | ||||
| 		Level:     slog.LevelDebug, | ||||
| 		AddSource: true, | ||||
| 	})) | ||||
| 	// memcache = cache.MemCache | ||||
| 	cfg = config.LoadConfigOrDefault("") | ||||
| 	Notifier = broker.Notifier | ||||
| 	// cache.MemCache.StartBackupRoutine(15 * time.Second) // Reduced backup interval | ||||
| 	// bot loader | ||||
| 	// check the rooms if it has bot_{digits} in them, create bots if have | ||||
| 	repo = repos.NewRepoProvider("sqlite3://../gralias.db") | ||||
| 	// repo = repos.NewRepoProvider("sqlite3://../gralias.db") | ||||
| 	repo = repos.RP | ||||
| 	recoverBots() | ||||
| 	// if player has a roomID, but no team and role, try to recover | ||||
| 	// recoverPlayers() | ||||
| } | ||||
|  | ||||
| func HandlePing(w http.ResponseWriter, r *http.Request) { | ||||
|   | ||||
							
								
								
									
										3
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								main.go
									
									
									
									
									
								
							| @@ -62,7 +62,8 @@ func main() { | ||||
| 	// Setup graceful shutdown | ||||
| 	stop := make(chan os.Signal, 1) | ||||
| 	signal.Notify(stop, os.Interrupt, syscall.SIGTERM) | ||||
| 	repo := repos.NewRepoProvider(cfg.DBPath) | ||||
| 	// repo := repos.NewRepoProvider(cfg.DBPath) | ||||
| 	repo := repos.RP | ||||
| 	defer repo.Close() | ||||
| 	cm := crons.NewCronManager(repo, slog.Default()) | ||||
| 	cm.Start() | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package repos | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"gralias/config" | ||||
| 	"log/slog" | ||||
| 	"os" | ||||
| 	"sync" | ||||
| @@ -20,6 +21,7 @@ type AllRepos interface { | ||||
| 	SettingsRepo | ||||
| 	CardMarksRepo | ||||
| 	InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) | ||||
| 	Close() | ||||
| } | ||||
|  | ||||
| type RepoProvider struct { | ||||
| @@ -28,26 +30,39 @@ type RepoProvider struct { | ||||
| 	pathToDB string | ||||
| } | ||||
|  | ||||
| var RP AllRepos | ||||
|  | ||||
| func init() { | ||||
| 	cfg := config.LoadConfigOrDefault("") | ||||
| 	// sqlite3 has lock on write, so we need to have only one connection per whole app | ||||
| 	// https://github.com/mattn/go-sqlite3/issues/274#issuecomment-232942571 | ||||
| 	RP = NewRepoProvider(cfg.DBPath) | ||||
| } | ||||
|  | ||||
| func NewRepoProvider(pathToDB string) *RepoProvider { | ||||
| 	db, err := sqlx.Connect("sqlite3", pathToDB) | ||||
| 	if err != nil { | ||||
| 		slog.Error("Unable to connect to database", "error", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||
| 	stmts := []string{ | ||||
| 		"PRAGMA foreign_keys = ON;", | ||||
| 		"PRAGMA busy_timeout=200;", | ||||
| 	} | ||||
| 	for _, stmt := range stmts { | ||||
| 		_, err = db.Exec(stmt) | ||||
| 		if err != nil { | ||||
| 			slog.Error("Unable to enable foreign keys", "error", err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
| 	slog.Info("Successfully connected to database") | ||||
| 	// db.SetMaxOpenConns(2) | ||||
| 	rp := &RepoProvider{ | ||||
| 		DB:       db, | ||||
| 		pathToDB: pathToDB, | ||||
| 	} | ||||
|  | ||||
| 	go rp.pingLoop() | ||||
|  | ||||
| 	return rp | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -98,7 +98,7 @@ func TestPlayersRepo_DeletePlayer(t *testing.T) { | ||||
| 	_, err := db.Exec(`INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)`, player.RoomID, player.Username, player.Team, player.Role, player.IsBot) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
| 	err = repo.PlayerDelete(context.Background(), *player.RoomID, player.Username) | ||||
| 	err = repo.PlayerDelete(context.Background(), player.Username) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
| 	var count int | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder