feat: allow resetting RocksDB cache

This commit is contained in:
erhant 2026-07-02 14:31:34 +03:00
parent 6cadac2dc3
commit e645875ebd
5 changed files with 77 additions and 5 deletions

8
flake.lock generated
View File

@ -154,11 +154,11 @@
"logos-module-builder": "logos-module-builder_4"
},
"locked": {
"lastModified": 1782982957,
"narHash": "sha256-L1W94vlMtKK5w6S9np2qFEY8tJ5M5g6Aryfrb3Bf4lo=",
"lastModified": 1782991756,
"narHash": "sha256-MhRCtwOctGTZ2+CMF93AAPV6nIO/X2uO4qcTxzLsgbw=",
"ref": "erhant/bump-lez-and-fix-logging",
"rev": "69dbf45a57f94345d46ceca3c9bc563ce5fab0ae",
"revCount": 59,
"rev": "b2fde3c000d00c04da374b2c31719e29a237b2a4",
"revCount": 62,
"type": "git",
"url": "https://github.com/logos-blockchain/lez-indexer-module"
},

View File

@ -33,6 +33,11 @@ class LezExplorerUi
// refresh the feed. The backend writes the JSON to a file itself — the UI
// never deals with paths. Returns true on success.
SLOT(bool applyConfigJson(QString json))
// Delete the indexer's RocksDB cache and restart from the saved config: the
// recovery path when the local store is stale against a different/reset chain
// (otherwise the indexer can sit at "caught up" on a mismatched store).
// Returns true on success.
SLOT(bool resetIndexerCache())
// Reload the latest page into recentBlocks and re-baseline the poller.
SLOT(void refreshBlocks())
// Append the next older page of blocks to recentBlocks.

View File

@ -399,6 +399,24 @@ bool LezExplorerUiBackend::applyConfigJson(QString json) {
return ok;
}
bool LezExplorerUiBackend::resetIndexerCache() {
// reset_storage stops the indexer and deletes its RocksDB store; then we
// restart from the saved config so it re-indexes the current chain from
// scratch. The recovery path for a store left stale against a reset chain.
const qlonglong code = modules().lez_indexer_module.reset_storage(configFilePath());
if (code != 0) {
emit error(QStringLiteral("Failed to delete the indexer cache (code %1).").arg(code));
return false;
}
// Store is empty now; re-baseline the poller and restart ingestion.
m_lastPolledTip = 0;
m_polledOnce = false;
const bool ok = startIndexerFromFile();
refreshBlocks();
return ok;
}
void LezExplorerUiBackend::refreshBlocks() {
const QString json = modules().lez_indexer_module.getBlocks(QString(), QStringLiteral("10"));
m_recentBlocks = parseBlockArrayJson(json);

View File

@ -40,6 +40,7 @@ public:
// .rep SLOTs.
bool applyConfigJson(QString json) override;
bool resetIndexerCache() override;
void refreshBlocks() override;
void loadMoreBlocks() override;
QVariantMap getBlockById(QString id) override;

View File

@ -11,6 +11,8 @@ Item {
property var explorer
readonly property var backend: explorer ? explorer.backend : null
property bool statusIsError: false
// Armed by the first "Delete Cache" tap; a second tap actually wipes.
property bool confirmingReset: false
Component.onCompleted: {
// Seed the editor with the saved config, falling back to the template.
@ -83,6 +85,25 @@ Item {
font.pixelSize: Theme.typography.secondaryText
}
// Delete the indexer's RocksDB cache and re-sync (two-tap confirm).
Rectangle {
Layout.preferredHeight: 38
Layout.preferredWidth: 150
radius: Theme.spacing.radiusMedium
color: resetCacheHover.hovered ? Qt.lighter(Theme.palette.error, 1.1) : Theme.palette.error
HoverHandler { id: resetCacheHover }
TapHandler { onTapped: page.resetCache() }
LogosText {
anchors.centerIn: parent
text: page.confirmingReset ? "Confirm delete" : "Delete Cache"
color: Theme.palette.background
font.pixelSize: Theme.typography.secondaryText
font.weight: Theme.typography.weightBold
}
}
// Reset to the built-in template.
Rectangle {
Layout.preferredHeight: 38
@ -93,7 +114,7 @@ Item {
border.color: Theme.palette.borderSecondary
HoverHandler { id: resetHover }
TapHandler { onTapped: if (page.backend) { editor.text = page.backend.defaultConfig; page.setStatus("", false); } }
TapHandler { onTapped: if (page.backend) { page.confirmingReset = false; editor.text = page.backend.defaultConfig; page.setStatus("", false); } }
LogosText {
anchors.centerIn: parent
@ -129,9 +150,36 @@ Item {
statusLabel.text = message;
}
// Delete the indexer's RocksDB cache and re-sync. First tap arms; a second
// tap confirms (it's destructive wipes the local index).
function resetCache() {
if (!page.backend)
return;
if (!page.confirmingReset) {
page.confirmingReset = true;
page.setStatus("Click “Confirm delete” to wipe the local index and re-sync from scratch.", true);
return;
}
page.confirmingReset = false;
page.setStatus("Deleting cache…", false);
logos.watch(page.backend.resetIndexerCache(),
function (ok) {
if (ok) {
page.setStatus("Cache deleted. Indexer restarting…", false);
page.explorer.goHome();
}
// On failure the backend emits error() (shown by onError above).
},
function (err) {
page.setStatus("Error: " + err, true);
});
}
function save() {
if (!page.backend)
return;
// A save cancels a pending cache-delete confirmation.
page.confirmingReset = false;
// Validate locally first for an immediate, precise error.
try {
JSON.parse(editor.text);