Skip to content

Commit 6468b04

Browse files
committed
ロールバックバグ修正
1 parent da30a3a commit 6468b04

File tree

4 files changed

+155
-58
lines changed

4 files changed

+155
-58
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package dev.felnull.DataIO;
2+
3+
import org.bukkit.Bukkit;
4+
5+
import java.sql.Connection;
6+
import java.sql.PreparedStatement;
7+
import java.sql.SQLException;
8+
import java.util.UUID;
9+
import java.util.concurrent.BlockingQueue;
10+
import java.util.concurrent.LinkedBlockingQueue;
11+
12+
public final class AsyncItemLogger {
13+
private static final BlockingQueue<ItemLogEvent> QUEUE = new LinkedBlockingQueue<>(5000);
14+
private static volatile boolean running = false;
15+
16+
public static void start(DatabaseManager db) {
17+
if (running) return;
18+
running = true;
19+
Thread t = new Thread(() -> loop(db), "BS-ItemLog-Worker");
20+
t.setDaemon(true);
21+
t.start();
22+
}
23+
public static void stop() { running = false; }
24+
public static void enqueue(ItemLogEvent ev) { QUEUE.offer(ev); }
25+
26+
private static void loop(DatabaseManager db) {
27+
while (running) {
28+
try (Connection conn = db.getConnection();
29+
PreparedStatement ps = conn.prepareStatement(
30+
"INSERT INTO inventory_item_log " +
31+
"(group_uuid, plugin_name, page_id, slot, operation_type, itemstack, display_name, display_name_plain, material, amount, player_uuid, timestamp) " +
32+
"VALUES (?,?,?,?,?,?,?,?,?,?,?,NOW())")) {
33+
conn.setAutoCommit(false);
34+
35+
// 1件待ってからまとめて吸う(50ms or 200件)
36+
ItemLogEvent first = QUEUE.poll(1, java.util.concurrent.TimeUnit.SECONDS);
37+
if (first == null) continue;
38+
39+
int batch = 0;
40+
long start = System.currentTimeMillis();
41+
add(ps, first); batch++;
42+
43+
while (batch < 200 && System.currentTimeMillis() - start < 50) {
44+
ItemLogEvent ev = QUEUE.poll();
45+
if (ev == null) break;
46+
add(ps, ev); batch++;
47+
}
48+
49+
ps.executeBatch();
50+
conn.commit();
51+
} catch (Exception e) {
52+
// 少し待って再開(接続枯渇・一時障害に強く)
53+
try { Thread.sleep(50); } catch (InterruptedException ignored) {}
54+
Bukkit.getLogger().warning("[BetterStorage] 非同期ログワーカーエラー: " + e.getMessage());
55+
}
56+
}
57+
}
58+
59+
private static void add(PreparedStatement ps, ItemLogEvent e) throws SQLException {
60+
ps.setString(1, e.groupUUID.toString());
61+
ps.setString(2, e.pluginName);
62+
ps.setString(3, e.pageId);
63+
ps.setInt(4, e.slot);
64+
ps.setString(5, e.operation);
65+
ps.setString(6, e.itemstack);
66+
ps.setString(7, e.displayName);
67+
ps.setString(8, e.displayNamePlain);
68+
ps.setString(9, e.material);
69+
ps.setInt(10, e.amount);
70+
ps.setString(11, e.playerUUID != null ? e.playerUUID.toString() : null);
71+
ps.addBatch();
72+
}
73+
74+
public static final class ItemLogEvent {
75+
final UUID groupUUID; final String pluginName; final String pageId; final int slot;
76+
final String operation; final String itemstack; final String displayName; final String displayNamePlain;
77+
final String material; final int amount; final UUID playerUUID;
78+
public ItemLogEvent(UUID g, String p, String page, int s, String op, String it, String d, String dp, String m, int a, UUID u) {
79+
groupUUID=g; pluginName=p; pageId=page; slot=s; operation=op; itemstack=it; displayName=d; displayNamePlain=dp; material=m; amount=a; playerUUID=u;
80+
}
81+
}
82+
}

src/main/java/dev/felnull/DataIO/DataIO.java

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -953,34 +953,14 @@ public static void logInventoryItemChangeAsync(DatabaseManager db, UUID groupUUI
953953

954954
String serializedItem = ItemSerializer.serializeToBase64(item);
955955
String displayName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : "";
956-
String material = item.getType().name();
957-
int amount = item.getAmount();
958956
String plainName = ChatColor.stripColor(displayName);
959957

960-
Bukkit.getScheduler().runTaskAsynchronously(BetterStorage.BSPlugin, () -> {
961-
try (Connection conn = db.getConnection()) {
962-
String sql = "INSERT INTO inventory_item_log " +
963-
"(group_uuid, plugin_name, page_id, slot, operation_type, itemstack, display_name, display_name_plain, material, amount, player_uuid, timestamp) " +
964-
"VALUES (?,?,?,?,?,?,?,?,?,?,?,NOW())";
965-
966-
try (PreparedStatement ps = conn.prepareStatement(sql)) {
967-
ps.setString(1, groupUUID.toString());
968-
ps.setString(2, pluginName);
969-
ps.setString(3, pageId);
970-
ps.setInt(4, slot);
971-
ps.setString(5, op.toDbString());
972-
ps.setString(6, serializedItem);
973-
ps.setString(7, displayName);
974-
ps.setString(8, plainName);
975-
ps.setString(9, material);
976-
ps.setInt(10, amount);
977-
ps.setString(11, playerUUID != null ? playerUUID.toString() : null); // null安全
978-
ps.executeUpdate();
979-
}
980-
} catch (SQLException e) {
981-
Bukkit.getLogger().warning("[BetterStorage] 非同期ログ保存失敗: " + e.getMessage());
982-
}
983-
});
958+
AsyncItemLogger.ItemLogEvent ev = new AsyncItemLogger.ItemLogEvent(
959+
groupUUID, pluginName, pageId, slot,
960+
op.toDbString(), serializedItem, displayName, plainName,
961+
item.getType().name(), item.getAmount(), playerUUID
962+
);
963+
AsyncItemLogger.enqueue(ev); // ← ここだけ
984964
}
985965

986966

src/main/java/dev/felnull/DataIO/DatabaseManager.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.bukkit.plugin.java.JavaPlugin;
77
import org.bukkit.scheduler.BukkitRunnable;
88
import org.bukkit.scheduler.BukkitTask;
9+
import org.jetbrains.annotations.NotNull;
910

1011
import java.sql.Connection;
1112
import java.sql.SQLException;
@@ -68,17 +69,7 @@ private void connect() throws Exception {
6869
this.username = plugin.getConfig().getString("database.username");
6970
this.password = plugin.getConfig().getString("database.password");
7071
Bukkit.getLogger().info("[BetterStorage] 接続先 → " + ip + ":" + port + "/" + dbName);
71-
String jdbcUrl = "jdbc:mariadb://" + ip + ":" + port + "/" + dbName
72-
+ "?useUnicode=true&characterEncoding=utf8mb4";
73-
HikariConfig config = new HikariConfig();
74-
config.setJdbcUrl(jdbcUrl);
75-
config.setUsername(username);
76-
config.setPassword(password);
77-
config.setMaximumPoolSize(10);
78-
config.setMinimumIdle(2);
79-
config.setConnectionTimeout(30000);
80-
config.setIdleTimeout(600000);
81-
config.setMaxLifetime(1800000);
72+
HikariConfig config = getHikariConfig();
8273

8374
if (dataSource != null && !dataSource.isClosed()) {
8475
dataSource.close();
@@ -91,6 +82,23 @@ private void connect() throws Exception {
9182
// 成功
9283
}
9384
}
85+
86+
private @NotNull HikariConfig getHikariConfig() {
87+
String jdbcUrl = "jdbc:mariadb://" + ip + ":" + port + "/" + dbName
88+
+ "?useUnicode=true&characterEncoding=utf8mb4";
89+
HikariConfig config = new HikariConfig();
90+
config.setJdbcUrl(jdbcUrl);
91+
config.setUsername(username);
92+
config.setPassword(password);
93+
config.setMaximumPoolSize(30);
94+
config.setMinimumIdle(2);
95+
config.setConnectionTimeout(30000);
96+
config.setIdleTimeout(600000);
97+
config.setMaxLifetime(1800000);
98+
config.setConnectionInitSql("SET time_zone = 'Asia/Tokyo'");
99+
return config;
100+
}
101+
94102
// DB利用可否判定
95103
public boolean isConnected() {
96104
return isDbConnected;

src/main/java/dev/felnull/DataIO/UnifiedLogManager.java

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,34 @@ public static boolean restoreGroupToTimestamp(UUID groupUUID, LocalDateTime targ
191191
if (group == null) {
192192
group = backup.toGroupData(); // 完全復元
193193
} else {
194+
saveBackupSnapshot(group);
194195
// storageData だけ置き換える
195196
StorageData restored = backup.storageData.toStorageData();
196197
restored.attach(group);
197198
group.storageData = restored;
198199
}
199200

201+
// 2_2旧データ削除
202+
// 旧データ削除(このグループ+このプラグインのページ・アイテム・タグ [+ storage])
203+
final String gid = groupUUID.toString();
204+
final String plugin = group.ownerPlugin;
205+
206+
try (PreparedStatement delItems = conn.prepareStatement(
207+
"DELETE FROM inventory_item_table WHERE group_uuid=? AND plugin_name=?");
208+
PreparedStatement delTags = conn.prepareStatement(
209+
"DELETE FROM tag_table WHERE group_uuid=? AND plugin_name=?");
210+
PreparedStatement delPages = conn.prepareStatement(
211+
"DELETE FROM inventory_table WHERE group_uuid=? AND plugin_name=?");
212+
PreparedStatement delStorage = conn.prepareStatement( // ← storage も入れ替える場合のみ
213+
"DELETE FROM storage_table WHERE group_uuid=? AND plugin_name=?")) {
214+
215+
// 子 → 親(items → tags → pages → storage)の順で削除
216+
delItems.setString(1, gid); delItems.setString(2, plugin); delItems.executeUpdate();
217+
delTags.setString(1, gid); delTags.setString(2, plugin); delTags.executeUpdate();
218+
delPages.setString(1, gid); delPages.setString(2, plugin); delPages.executeUpdate();
219+
delStorage.setString(1, gid); delStorage.setString(2, plugin); delStorage.executeUpdate(); // 不要なら削除
220+
}
221+
200222
// 3. 差分ログを snapshot → targetTime に適用
201223
boolean success = applyForwardDiffs(group, snapshotTime, targetTime);
202224

@@ -209,6 +231,7 @@ public static boolean restoreGroupToTimestamp(UUID groupUUID, LocalDateTime targ
209231

210232
} catch (Exception e) {
211233
Bukkit.getLogger().warning("[BetterStorage] 巻き戻しに失敗: " + e.getMessage());
234+
Bukkit.getLogger().info("復元中...");
212235
return false;
213236
}
214237
}
@@ -269,21 +292,23 @@ public static boolean applyForwardDiffs(GroupData groupData, LocalDateTime from,
269292
ps.setString(2, groupData.ownerPlugin);
270293
ps.setString(3, from.format(FORMATTER));
271294
ps.setString(4, to.format(FORMATTER));
272-
295+
Bukkit.getLogger().info("aiauwdh");
273296
try (ResultSet rs = ps.executeQuery()) {
297+
Bukkit.getLogger().info("ha?!");
274298
while (rs.next()) {
275299
String pageId = rs.getString("page_id");
276300
String op = rs.getString("operation_type");
277301
String metaJson = null;
278302
try { metaJson = rs.getString("meta_json"); } catch (SQLException ignore) {}
279-
303+
Bukkit.getLogger().info("ayag!");
280304
switch (op) {
281305
case "PAGE_CREATE": {
282306
ensurePagePresentOrCreate(groupData, pageId);
283307
break;
284308
}
285309
case "PAGE_DELETE": {
286310
groupData.storageData.storageInventory.remove(pageId);
311+
Bukkit.getLogger().info("削除!");
287312
break;
288313
}
289314
case "PAGE_META": { // 任意:rows は final なら再生成 or 後でDBから拾う
@@ -336,26 +361,28 @@ public static boolean applyForwardDiffs(GroupData groupData, LocalDateTime from,
336361
while (rs.next()) {
337362
String pageId = rs.getString("page_id");
338363
int slot = rs.getInt("slot");
339-
String base64 = rs.getString("itemstack");
340-
String timestampStr = rs.getString("timestamp");
341-
342-
ItemStack item = ItemSerializer.deserializeFromBase64(base64);
343-
344-
InventoryData inv = groupData.storageData.storageInventory.get(pageId);
345-
if (inv != null && inv.itemStackSlot != null) {
346-
if (item == null || item.getType() == Material.AIR) {
347-
inv.itemStackSlot.remove(slot);
348-
} else {
349-
inv.itemStackSlot.put(slot, item);
364+
if(slot != -1){
365+
String base64 = rs.getString("itemstack");
366+
String timestampStr = rs.getString("timestamp");
367+
368+
ItemStack item = ItemSerializer.deserializeFromBase64(base64);
369+
370+
InventoryData inv = groupData.storageData.storageInventory.get(pageId);
371+
if (inv != null && inv.itemStackSlot != null) {
372+
if (item == null || item.getType() == Material.AIR) {
373+
inv.itemStackSlot.remove(slot);
374+
} else {
375+
inv.itemStackSlot.put(slot, item);
376+
}
350377
}
351-
}
352378

353-
// 差分適用された timestamp を記録
354-
try {
355-
LocalDateTime appliedTime = LocalDateTime.parse(timestampStr, FORMATTER);
356-
appliedTimestamps.add(appliedTime);
357-
} catch (Exception e) {
358-
Bukkit.getLogger().warning("timestampのパースに失敗: " + timestampStr);
379+
// 差分適用された timestamp を記録
380+
try {
381+
LocalDateTime appliedTime = LocalDateTime.parse(timestampStr, FORMATTER);
382+
appliedTimestamps.add(appliedTime);
383+
} catch (Exception e) {
384+
Bukkit.getLogger().warning("timestampのパースに失敗: " + timestampStr);
385+
}
359386
}
360387
}
361388
}
@@ -597,7 +624,7 @@ private static Map<Integer, ItemStack> loadLatestLoggedItems(Connection conn, St
597624
int slot = rs.getInt("slot");
598625
String operationType = rs.getString("operation_type");
599626

600-
if (seenSlots.contains(slot)) {
627+
if (seenSlots.contains(slot)||slot == -1) {
601628
continue;
602629
}
603630
seenSlots.add(slot);

0 commit comments

Comments
 (0)