Дорабатываю добавление блоков.
Улучшил класс записыватель в БД.
This commit is contained in:
AidarKC 2025-12-24 17:01:10 +03:00
parent a309b6f3ef
commit 4759521176
2 changed files with 13 additions and 30 deletions

View File

@ -15,25 +15,19 @@ import java.sql.SQLException;
* Важно: * Важно:
* - Здесь обеспечивается атомарность записи: либо вставился блок и обновилось состояние, либо не вставилось ничего. * - Здесь обеспечивается атомарность записи: либо вставился блок и обновилось состояние, либо не вставилось ничего.
* - Соединение открывается/закрывается внутри (удобно для хэндлера). * - Соединение открывается/закрывается внутри (удобно для хэндлера).
* - При необходимости можно вызвать appendBlockAndState(Connection, ...) и управлять транзакцией снаружи.
*/ */
public final class BlockchainDbWriter { public final class BlockchainWriter {
private final SqliteDbController db; private final SqliteDbController db;
private final BlocksDAO blocksDAO; private final BlocksDAO blocksDAO;
private final BlockchainStateDAO stateDAO; private final BlockchainStateDAO stateDAO;
public BlockchainDbWriter(BlocksDAO blocksDAO, BlockchainStateDAO stateDAO) { public BlockchainWriter(BlocksDAO blocksDAO, BlockchainStateDAO stateDAO) {
this.db = SqliteDbController.getInstance(); this.db = SqliteDbController.getInstance();
this.blocksDAO = blocksDAO; this.blocksDAO = blocksDAO;
this.stateDAO = stateDAO; this.stateDAO = stateDAO;
} }
/**
* Публичный метод: сам открывает соединение, делает транзакцию и закрывает соединение.
*
* @return true если всё записалось успешно, иначе кидает SQLException (или IllegalStateException выше по коду).
*/
public void appendBlockAndState( public void appendBlockAndState(
String login, String login,
String blockchainName, String blockchainName,
@ -44,56 +38,45 @@ public final class BlockchainDbWriter {
String newHashHex String newHashHex
) throws SQLException { ) throws SQLException {
// 1) Открываем соединение (try-with-resources гарантирует закрытие)
try (Connection c = db.getConnection()) { try (Connection c = db.getConnection()) {
// 2) Включаем ручное управление транзакцией
boolean oldAutoCommit = c.getAutoCommit(); boolean oldAutoCommit = c.getAutoCommit();
c.setAutoCommit(false); c.setAutoCommit(false);
try { try {
// 3) Внутри одной транзакции: // 1) блок
// - вставляем строку блока insertBlockRow(c, login, blockchainName, globalNumber, prevGlobalHashHex, blockBytes);
// - обновляем/создаём blockchain_state
appendBlockAndState(c, login, blockchainName, globalNumber, prevGlobalHashHex, blockBytes, stOrNull, newHashHex);
// 4) Фиксируем транзакцию // 2) state
appendState(c, blockchainName, globalNumber, stOrNull, newHashHex);
// 3) commit
c.commit(); c.commit();
} catch (Exception e) { } catch (Exception e) {
// 5) Если что-то упало откатываем транзакцию, чтобы не было "полузаписей"
try { c.rollback(); } catch (SQLException ignore) {} try { c.rollback(); } catch (SQLException ignore) {}
// Пробрасываем как SQLException (чтобы вызывающий код мог отдать internal_error и т.п.)
if (e instanceof SQLException se) throw se; if (e instanceof SQLException se) throw se;
throw new SQLException("appendBlockAndState failed", e); throw new SQLException("appendBlockAndState failed", e);
} finally { } finally {
// 6) Возвращаем autoCommit как было
try { c.setAutoCommit(oldAutoCommit); } catch (SQLException ignore) {} try { c.setAutoCommit(oldAutoCommit); } catch (SQLException ignore) {}
} }
} }
} }
/** /**
* Внутренний/расширенный метод: запись в рамках УЖЕ открытого соединения. * Обновление состояния blockchain_state (создаём если отсутствует).
* Удобно если снаружи хотят объединить несколько действий в одну транзакцию. * Пока линии не используются: lineIndex=0 и lineHash = globalHash.
*/ */
public void appendBlockAndState( private void appendState(
Connection c, Connection c,
String login,
String blockchainName, String blockchainName,
int globalNumber, int globalNumber,
String prevGlobalHashHex,
byte[] blockBytes,
BlockchainStateEntry stOrNull, BlockchainStateEntry stOrNull,
String newHashHex String newHashHex
) throws SQLException { ) throws SQLException {
// A) Вставляем блок (строка в таблицу blocks)
insertBlockRow(c, login, blockchainName, globalNumber, prevGlobalHashHex, blockBytes);
// B) Обновляем состояние blockchain_state (создаём если отсутствует)
BlockchainStateEntry st = stOrNull; BlockchainStateEntry st = stOrNull;
if (st == null) { if (st == null) {
st = new BlockchainStateEntry(); st = new BlockchainStateEntry();
@ -104,7 +87,7 @@ public final class BlockchainDbWriter {
st.setLastGlobalNumber(globalNumber); st.setLastGlobalNumber(globalNumber);
st.setLastGlobalHash(newHashHex); st.setLastGlobalHash(newHashHex);
// Пока линии не используются: lineIndex=0 и lineHash = globalHash // Линии пока не используются: lineIndex=0 и lineHash=globalHash
st.setLastLineNumber(0, globalNumber); st.setLastLineNumber(0, globalNumber);
st.setLastLineHash(0, newHashHex); st.setLastLineHash(0, newHashHex);

View File

@ -40,7 +40,7 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
private final SolanaUsersDAO solanaUsersDAO = SolanaUsersDAO.getInstance(); private final SolanaUsersDAO solanaUsersDAO = SolanaUsersDAO.getInstance();
// Writer отвечает за транзакции/атомарность и консистентность БД // Writer отвечает за транзакции/атомарность и консистентность БД
private final BlockchainDbWriter dbWriter = new BlockchainDbWriter(blocksDAO, stateDAO); private final BlockchainWriter dbWriter = new BlockchainWriter(blocksDAO, stateDAO);
@Override @Override
public Net_Response handle(Net_Request baseReq, ConnectionContext ctx) { public Net_Response handle(Net_Request baseReq, ConnectionContext ctx) {