24 12 25
Дорабатываю добавление блоков. Улучшил класс записыватель в БД.
This commit is contained in:
parent
a309b6f3ef
commit
4759521176
@ -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);
|
||||||
|
|
||||||
@ -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) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user