Skip to content

Commit 10a6f31

Browse files
committed
Fix/upgrade SQLite storage option
1 parent 6b887f9 commit 10a6f31

3 files changed

Lines changed: 74 additions & 19 deletions

File tree

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@
152152
<artifactId>HikariCP</artifactId>
153153
<version>6.2.1</version>
154154
</dependency>
155+
<dependency>
156+
<groupId>org.xerial</groupId>
157+
<artifactId>sqlite-jdbc</artifactId>
158+
<version>3.47.1.0</version>
159+
</dependency>
155160
<dependency>
156161
<groupId>com.squareup.okhttp</groupId>
157162
<artifactId>okhttp</artifactId>

src/main/java/dev/noah/perplayerkit/storage/StorageSelector.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
public class StorageSelector {
2929

30-
3130
private StorageManager storageManager;
3231
private Plugin plugin;
3332

@@ -39,7 +38,8 @@ public StorageSelector(Plugin plugin, String storageType) {
3938

4039
case "yml":
4140
case "yaml":
42-
storageManager = new YAMLStorage(plugin,plugin.getDataFolder() + File.separator + "please-use-a-real-database.yml");
41+
storageManager = new YAMLStorage(plugin,
42+
plugin.getDataFolder() + File.separator + "please-use-a-real-database.yml");
4343
break;
4444
case "redis":
4545
storageManager = new RedisStorage(plugin);
@@ -50,8 +50,8 @@ public StorageSelector(Plugin plugin, String storageType) {
5050
break;
5151
case "sqlite":
5252
default:
53-
//default to sqlite
54-
db = new SQLite(plugin.getDataFolder() + File.separator + "database.db");
53+
// default to sqlite
54+
db = new SQLite(plugin);
5555
storageManager = new SQLStorage(db);
5656
break;
5757
}
@@ -62,5 +62,4 @@ public StorageManager getDbManager() {
6262
return storageManager;
6363
}
6464

65-
6665
}

src/main/java/dev/noah/perplayerkit/storage/sql/SQLite.java

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,88 @@
1818
*/
1919
package dev.noah.perplayerkit.storage.sql;
2020

21+
import com.zaxxer.hikari.HikariConfig;
22+
import com.zaxxer.hikari.HikariDataSource;
23+
import org.bukkit.plugin.Plugin;
24+
25+
import java.io.File;
2126
import java.sql.Connection;
22-
import java.sql.DriverManager;
2327
import java.sql.SQLException;
2428

2529
public class SQLite implements SQLDatabase {
2630

31+
private final Plugin plugin;
2732
private final String databasePath;
28-
private Connection connection;
33+
private HikariDataSource dataSource;
2934

30-
public SQLite(String databasePath) {
31-
this.databasePath = databasePath;
35+
public SQLite(Plugin plugin) {
36+
this.plugin = plugin;
37+
this.databasePath = plugin.getDataFolder() + File.separator + "database.db";
3238
}
3339

3440
public boolean isConnected() {
35-
try {
36-
return connection != null && !connection.isClosed() && connection.isValid(1);
37-
} catch (SQLException e) {
38-
return false;
39-
}
41+
return (dataSource != null && !dataSource.isClosed());
4042
}
4143

4244
public void connect() throws ClassNotFoundException, SQLException {
4345
if (!isConnected()) {
44-
Class.forName("org.sqlite.JDBC");
45-
connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath);
46+
// Ensure plugin data folder exists
47+
plugin.getDataFolder().mkdirs();
48+
49+
HikariConfig config = new HikariConfig();
50+
51+
// Modern SQLite JDBC URL with optimized parameters (2025 best practices)
52+
config.setJdbcUrl("jdbc:sqlite:" + databasePath +
53+
"?journal_mode=WAL" + // WAL mode for better concurrency
54+
"&synchronous=NORMAL" + // Balance between safety and performance
55+
"&cache_size=10000" + // 10MB cache (negative = KB, positive = pages)
56+
"&temp_store=MEMORY" + // Use memory for temp tables
57+
"&mmap_size=268435456" + // 256MB memory-mapped I/O
58+
"&optimize" + // Run PRAGMA optimize on connection
59+
"&foreign_keys=ON" + // Enable foreign key constraints
60+
"&busy_timeout=30000"); // 30 second busy timeout
61+
62+
config.setDriverClassName("org.sqlite.JDBC");
63+
config.setPoolName("SQLite-Pool");
64+
65+
// SQLite-specific pool configuration (optimized for single-writer architecture)
66+
config.setMaximumPoolSize(1); // SQLite is single-writer, use 1 connection
67+
config.setMinimumIdle(1); // Keep one connection alive
68+
config.setConnectionTimeout(30000); // 30 seconds connection timeout
69+
config.setIdleTimeout(300000); // 5 minutes idle timeout (reduced from 10)
70+
config.setMaxLifetime(1800000); // 30 minutes max connection lifetime
71+
config.setLeakDetectionThreshold(60000); // 60 seconds leak detection
72+
config.setKeepaliveTime(30000); // 30 seconds keepalive (HikariCP 4.0+)
73+
74+
// Modern HikariCP settings for better performance
75+
config.setInitializationFailTimeout(10000); // 10 seconds initialization timeout
76+
config.setValidationTimeout(5000); // 5 seconds validation timeout
77+
config.setConnectionTestQuery("SELECT 1"); // Lightweight connection test
78+
config.setAutoCommit(true); // SQLite default
79+
config.setReadOnly(false); // Allow writes
80+
config.setIsolateInternalQueries(false); // Don't isolate internal queries
81+
config.setRegisterMbeans(false); // Disable JMX for performance
82+
config.setAllowPoolSuspension(true); // Allow pool suspension for maintenance
83+
84+
// SQLite-specific connection properties (optimized for modern usage)
85+
config.addDataSourceProperty("cachePrepStmts", "true");
86+
config.addDataSourceProperty("prepStmtCacheSize", "500"); // Increased from 250
87+
config.addDataSourceProperty("prepStmtCacheSqlLimit", "4096"); // Increased from 2048
88+
config.addDataSourceProperty("useServerPrepStmts", "false"); // SQLite doesn't support server-side prepared
89+
// statements
90+
config.addDataSourceProperty("rewriteBatchedStatements", "true"); // Optimize batch operations
91+
config.addDataSourceProperty("cacheResultSetMetadata", "true"); // Cache metadata for performance
92+
config.addDataSourceProperty("cacheServerConfiguration", "true"); // Cache server config
93+
config.addDataSourceProperty("elideSetAutoCommits", "true"); // Optimize auto-commit calls
94+
config.addDataSourceProperty("maintainTimeStats", "false"); // Disable time stats for performance
95+
96+
dataSource = new HikariDataSource(config);
4697
}
4798
}
4899

49100
public void disconnect() throws SQLException {
50-
if (connection != null && !connection.isClosed()) {
51-
connection.close();
101+
if (isConnected()) {
102+
dataSource.close();
52103
}
53104
}
54105

@@ -60,6 +111,6 @@ public Connection getConnection() throws SQLException {
60111
throw new SQLException("Failed to load SQLite driver", e);
61112
}
62113
}
63-
return connection;
114+
return dataSource.getConnection();
64115
}
65116
}

0 commit comments

Comments
 (0)