Skip to content

reorg specific blocks#314

Merged
nischitpra merged 10 commits intomainfrom
np/reorg_hedera
Apr 10, 2026
Merged

reorg specific blocks#314
nischitpra merged 10 commits intomainfrom
np/reorg_hedera

Conversation

@nischitpra
Copy link
Copy Markdown
Collaborator

@nischitpra nischitpra commented Apr 10, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added reorg-api CLI command for manual reorg batch publishing
    • New HTTP endpoints: /health and /v1/reorg/publish for reorg operations
    • Bearer token authorization support
    • Block processing tracking with idempotency checks
  • Configuration

    • REORG_API_LISTEN_ADDR: Server listen address (default: :8080)
    • REORG_API_KEY: Optional API key for authorization
    • REORG_API_CLICKHOUSE_BATCH_SIZE: Batch processing size (default: 10)

@zeet-co
Copy link
Copy Markdown

zeet-co bot commented Apr 10, 2026

We're building your pull request over on Zeet.
Click me for more info about your build and deployment.
Once built, this branch can be tested at: https://insight-295-hedera-mainnet-reorg--761fa4.insight.zeet.app before merging 😉

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

Walkthrough

A new reorg-api CLI command and HTTP service is added to enable manual publishing of blockchain reorg data. The implementation includes ClickHouse query helpers, RPC batch fetching with retries, Kafka role-based producers, Redis idempotency tracking, and a REST API with authorization.

Changes

Cohort / File(s) Summary
CLI Command Registration
cmd/reorgapi.go, cmd/root.go
Added new reorg-api Cobra command that initializes RPC, ClickHouse, Kafka (with reorg-api role), and Redis, then starts the HTTP server. Registered as a subcommand in the root CLI.
Configuration
configs/config.go
Extended KafkaConfig with ProducerRole field and added three environment-backed settings to Config: ReorgAPIListenAddr (default :8080), ReorgAPIKey for Bearer authorization, and ReorgAPIClickhouseBatchSize (default 10).
ClickHouse Data Access
internal/libs/clickhouse.go
Added four new query functions (queryBlocksByBlockNumbers, queryTransactionsByBlockNumbers, queryLogsByBlockNumbers, queryTracesByBlockNumbers) and public GetBlockDataFromClickHouseForBlockNumbers() that deduplicates/sorts block numbers and concurrently fetches and indexes block data.
RPC Batch Fetching
internal/libs/libblockdata/getblockdata.go
Introduced FetchBlockDataFromRPC() for parallel RPC batch fetching with per-block retry logic (up to 3 attempts) and error handling instead of panic-based failures.
Infrastructure & Storage
internal/libs/kafka.go, internal/libs/redis.go, internal/storage/kafka_publisher.go
Added InitKafkaV2ForRole() to support role-based Kafka producers; added Redis helpers (GetReorgAPIMaxProcessedBlock, SetReorgAPIMaxProcessedBlock, ClearReorgAPIMaxProcessedBlock) for idempotency tracking; updated Kafka publisher to include role in client identifiers.
HTTP Server
internal/reorgapi/server.go
Implemented blocking Gin HTTP server with GET /health and POST /v1/reorg/publish endpoints. The publish handler validates payloads, enforces Bearer authorization, batches block processing with ClickHouse/RPC fetching, publishes to Kafka, and tracks progress via Redis idempotency cursor.

Sequence Diagram

sequenceDiagram
    participant Client
    participant HTTPServer as HTTP Server<br/>(reorg-api)
    participant Redis
    participant ClickHouse
    participant RPC
    participant Kafka

    Client->>HTTPServer: POST /v1/reorg/publish<br/>(chain_id, block_numbers)
    HTTPServer->>HTTPServer: Validate & deduplicate blocks
    HTTPServer->>Redis: Get max processed block<br/>(idempotency cursor)
    Redis-->>HTTPServer: cursor value
    HTTPServer->>HTTPServer: Filter out processed blocks
    HTTPServer->>HTTPServer: Split into batches
    
    loop For each batch
        HTTPServer->>ClickHouse: Query existing block data<br/>by block numbers
        ClickHouse-->>HTTPServer: Block data with transactions/logs/traces
        HTTPServer->>RPC: Fetch canonical blocks<br/>(with retries)
        RPC-->>HTTPServer: Block data
        HTTPServer->>HTTPServer: Validate & match RPC ordering
        HTTPServer->>Kafka: Publish reorg payloads
        Kafka-->>HTTPServer: Ack
        HTTPServer->>Redis: Update max processed block
        Redis-->>HTTPServer: Success
    end
    
    HTTPServer-->>Client: JSON response<br/>(status, blocks processed)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'reorg specific blocks' is vague and does not clearly describe the primary change. The PR adds a new CLI command 'reorg-api' with HTTP server for manual reorg publishing, supporting Kafka producer role configuration and block data querying. Use a more descriptive title that reflects the main change, such as 'Add reorg-api HTTP server for manual block reorg publishing' or 'Implement reorg-api CLI command for batch reorg operations'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch np/reorg_hedera

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@configs/config.go`:
- Around line 98-99: After parsing environment into the config struct, validate
that ReorgAPIClickhouseBatchSize is > 0 (since it's a uint64 check for != 0) and
reject the config if it's zero by returning an error (or exiting) with a clear
message like "REORG_API_CLICKHOUSE_BATCH_SIZE must be a positive integer";
update the config-loading function that constructs the config (e.g., the
function that parses env into the struct) to perform this check and propagate
the error so startup fails fast instead of allowing downstream
divide-by-zero/infinite-loop behavior.
- Around line 94-97: The Reorg API is currently defaulting ReorgAPIListenAddr to
":8080" and allowing ReorgAPIKey to be empty which exposes an unauthenticated
mutating endpoint; update the configuration so either the default bind is
loopback (change ReorgAPIListenAddr envDefault to "127.0.0.1:8080") or add a
startup validation that returns an error and aborts if ReorgAPIKey is empty
while ReorgAPIListenAddr is not bound to localhost—implement this check in the
config initialization/validation path that constructs/validates the config
(reference ReorgAPIListenAddr and ReorgAPIKey) and fail fast with a clear error
message when the combination would allow unauthenticated external access.

In `@internal/libs/clickhouse.go`:
- Around line 337-355: Replace the un-cancelable errgroup usage (g :=
new(errgroup.Group)) with errgroup.WithContext so the group is tied to the
request context, and pass that derived ctx into the four concurrent callers (the
goroutines that call queryBlocksByBlockNumbers, queryTransactionsByBlockNumbers,
queryLogsByBlockNumbers, queryTracesByBlockNumbers) as well as into the
underlying query execution function (execQueryV2 / the query helpers) so that
any cancellation or error cancels the remaining ClickHouse scans; ensure each
helper accepts and uses the context for its FINAL scans.

In `@internal/libs/libblockdata/getblockdata.go`:
- Around line 342-355: The code assumes rpcResults preserve the order of
blockNumbers; instead ensure blocks are matched by their returned block number:
after building blockData from rpcResults (symbols: rpcResults, blockData,
common.BlockData), build a map from the block's number (e.g.,
block.Header.Number or whatever field holds the block number) to the
*common.BlockData, then iterate the original blockNumbers slice and for each
expected number pick the corresponding entry from the map (error if missing or
duplicate) before calling Validate; replace the current index-based trust and
return a clear error when an expected block number is absent or when there are
extra/unmatched RPC results.

In `@internal/libs/redis.go`:
- Around line 55-76: The current max-cursor approach in
GetReorgAPIMaxProcessedBlock/SetReorgAPIMaxProcessedBlock/ClearReorgAPIMaxProcessedBlock
is unsafe for non-contiguous or out-of-order block lists; replace the single max
value with per-block idempotency tracking in Redis (e.g., a Redis SET or bitmap
keyed by RedisReorgAPIMaxProcessedBlock:<chainID>) so you can check membership
for an individual block rather than comparing to a max. Update the API
functions: add functions like IsBlockProcessed(chainID, blockNumber) that use
SIsMember or GETBIT, MarkBlockProcessed(chainID, blockNumber) that uses SAdd or
SETBIT, and optionally UnmarkBlock/ResetChain that uses SRem/DEL; keep
RedisClient and the existing RedisReorgAPIMaxProcessedBlock base key name for
locating the keys and migrate or retire the old max-based functions accordingly.

In `@internal/reorgapi/server.go`:
- Around line 123-128: The current filtering that builds work by comparing each
bn in sorted against lastPublishedMaxBlock breaks idempotency for sparse/manual
ranges (e.g., submitting [100,200] then 150 gets dropped); update the logic in
server.go around the work construction (the loop using sorted and
lastPublishedMaxBlock) to either validate incoming ranges are contiguous before
accepting (reject non-contiguous requests in the request handler) or replace the
single lastPublishedMaxBlock cursor with explicit tracking (e.g., a
processedBlocks set or persisted batch IDs) and change the membership check to
consult that set instead of comparing to lastPublishedMaxBlock so
previously-unpublished blocks are not erroneously skipped. Ensure any
persistence/lookup uses the existing functions that read/write publication state
so behavior remains durable.
- Around line 168-172: The ClickHouse query failure handled after calling
libs.GetBlockDataFromClickHouseForBlockNumbers should return a 500 (internal
server error) instead of 400 and must not expose err.Error() to the client;
update the error handling where chunkOld is fetched (the block that logs via
log.Error().Err(err).Msg("manual reorg: clickhouse") and currently calls
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})) to log the detailed
err internally but respond with c.JSON(http.StatusInternalServerError,
gin.H{"error": "internal server error"}) or a short generic message like "failed
to query clickhouse".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a29d6c23-ecee-432b-9ccd-875b7c8969fb

📥 Commits

Reviewing files that changed from the base of the PR and between 1230c51 and 7b32a4b.

📒 Files selected for processing (9)
  • cmd/reorgapi.go
  • cmd/root.go
  • configs/config.go
  • internal/libs/clickhouse.go
  • internal/libs/kafka.go
  • internal/libs/libblockdata/getblockdata.go
  • internal/libs/redis.go
  • internal/reorgapi/server.go
  • internal/storage/kafka_publisher.go

Comment thread configs/config.go
Comment thread configs/config.go
Comment thread internal/libs/clickhouse.go
Comment thread internal/libs/libblockdata/getblockdata.go
Comment thread internal/libs/redis.go
Comment thread internal/reorgapi/server.go
Comment thread internal/reorgapi/server.go
Comment thread internal/reorgapi/server.go
@nischitpra nischitpra merged commit 21672cd into main Apr 10, 2026
5 of 6 checks passed
@nischitpra nischitpra deleted the np/reorg_hedera branch April 10, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant