Skip to content

Prune entity history sequentially per entity + improve metrics - #691

Merged
DZakh merged 2 commits into
mainfrom
dz/throttle-rollback-pruning-more
Aug 18, 2025
Merged

Prune entity history sequentially per entity + improve metrics#691
DZakh merged 2 commits into
mainfrom
dz/throttle-rollback-pruning-more

Conversation

@DZakh

@DZakh DZakh commented Aug 18, 2025

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added per-entity rollback history prune metrics for time (ms) and count.
    • Exposed total rollback success metrics: time (ms) and count.
  • Refactor

    • Replaced rollback duration histogram with explicit counters and a manual timer, improving clarity and consistency of timing units.
    • Updated metric names: previous rollback duration metric removed; new rollback time/count and per-entity prune time/count metrics introduced.
  • Chores

    • Monitoring and dashboards may require updates to reflect the new metric names and structure.

@coderabbitai

coderabbitai Bot commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Replaces rollback duration histogram with counters and adds per-entity prune metrics in Prometheus.res. Updates GlobalState rollback path to use Hrtime-based timing and increment new RollbackSuccess counters. Removes previous startTimer/endTimer usage and introduces RollbackHistoryPrune with labeled counters.

Changes

Cohort / File(s) Summary
Prometheus metrics restructuring
codegenerator/cli/npm/envio/src/Prometheus.res
Removed RollbackDuration histogram and startTimer; added RollbackSuccess counters (envio_rollback_time ms, envio_rollback_count) with increment(timeMillis); added RollbackHistoryPrune labeled counters (envio_rollback_history_prune_time ms, envio_rollback_history_prune_count) with increment(timeMillis, entityName).
GlobalState rollback instrumentation
codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res
Replaced Prometheus.RollbackDuration timer with Hrtime.makeTimer; on completion, computes elapsed ms and calls Prometheus.RollbackSuccess.increment.

Sequence Diagram(s)

sequenceDiagram
  participant GS as GlobalState
  participant HR as Hrtime
  participant PM as Prometheus.RollbackSuccess

  GS->>HR: makeTimer()
  activate HR
  HR-->>GS: startTime
  deactivate HR

  GS->>GS: perform rollback/reorg work

  GS->>HR: timeSince(startTime)
  HR-->>GS: elapsedMillis

  GS->>PM: increment(timeMillis=elapsedMillis)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • JonoPrest

Poem

I hopped through code where rollbacks dwell,
Tick-tock milliseconds tell.
Histograms fade, counters bloom—
Prune the past, make tidy room.
With stopwatch paws and metric cheer,
I time the leap, then nibble near.
(_/)>⏱️

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dz/throttle-rollback-pruning-more

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Comment on lines -497 to -505
module RollbackDuration = {
let histogram = PromClient.Histogram.make({
"name": "envio_rollback_duration",
"help": "Rollback on reorg duration in seconds",
"buckets": [0.5, 1., 5., 10.],
module RollbackSuccess = {
let timeCounter = PromClient.Counter.makeCounter({
"name": "envio_rollback_time",
"help": "Rollback on reorg total time in milliseconds",
})

let counter = PromClient.Counter.makeCounter({
"name": "envio_rollback_count",
"help": "Number of successful rollbacks on reorg",
})

let startTimer = () => {
histogram->PromClient.Histogram.startTimer

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Found time + count combo much more informative than histogram for these kind of cases. It also takes less space in the metrics response, which is already quite big 😅

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res (1)

875-914: Pruning is still concurrent; switch to sequential per-entity and emit per-entity metrics

This path still executes pruning concurrently across entities via Promise.all, which contradicts the stated objective “Prune entity history sequentially per entity + improve metrics” and prevents per-entity timing metrics from being emitted. Running sequentially also reduces DB contention.

Refactor to:

  • Run prune sequentially per entity.
  • Time each entity prune and increment Prometheus.RollbackHistoryPrune with the entity label.
  • Optionally, update benchmark summary per-entity.

Apply this diff:

-        let timeRef = Hrtime.makeTimer()
-        let _ = await Promise.all(
-          Entities.allEntities->Belt.Array.map(entityConfig => {
-            Db.sql->DbFunctions.EntityHistory.pruneStaleEntityHistory(
-              ~entityName=entityConfig.name,
-              ~safeChainIdAndBlockNumberArray,
-              ~shouldDeepClean,
-            )
-          }),
-        )
-
-        if Env.Benchmark.shouldSaveData {
-          let elapsedTimeMillis = Hrtime.timeSince(timeRef)->Hrtime.toMillis->Hrtime.floatFromMillis
-
-          Benchmark.addSummaryData(
-            ~group="Other",
-            ~label="Prune Stale History Time (ms)",
-            ~value=elapsedTimeMillis,
-          )
-        }
+        let entities = Entities.allEntities
+        for idx in 0 to entities->Array.length - 1 {
+          let entityConfig = entities->Array.getUnsafe(idx)
+          let tRef = Hrtime.makeTimer()
+          await Db.sql->DbFunctions.EntityHistory.pruneStaleEntityHistory(
+            ~entityName=entityConfig.name,
+            ~safeChainIdAndBlockNumberArray,
+            ~shouldDeepClean,
+          )
+          let elapsed = Hrtime.timeSince(tRef)->Hrtime.toMillis
+          Prometheus.RollbackHistoryPrune.increment(
+            ~timeMillis=elapsed,
+            ~entityName=entityConfig.name,
+          )
+
+          if Env.Benchmark.shouldSaveData {
+            Benchmark.addSummaryData(
+              ~group="Other",
+              ~label=`Prune Stale History (${entityConfig.name}) (ms)`,
+              ~value=elapsed->Hrtime.floatFromMillis,
+            )
+          }
+        }
🧹 Nitpick comments (1)
codegenerator/cli/npm/envio/src/Prometheus.res (1)

497-512: RollbackSuccess metrics: approach is sound

Replacing histogram with total-time and count counters is consistent with computing averages downstream. No labels keeps cardinality low. Consider adding "labelNames": [] for consistency with other counters, but not required.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cef9a67 and 2acd74d.

📒 Files selected for processing (2)
  • codegenerator/cli/npm/envio/src/Prometheus.res (1 hunks)
  • codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{res,resi}

📄 CodeRabbit Inference Engine (.cursor/rules/rescript.mdc)

**/*.{res,resi}: Never use [| item |] to create an array. Use [ item ] instead.
Must always use = for setting value to a field. Use := only for ref values created using ref function.
ReScript has record types which require a type definition before hand. You can access record fields by dot like foo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.

Files:

  • codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res
  • codegenerator/cli/npm/envio/src/Prometheus.res
codegenerator/cli/templates/{dynamic/**/*.hbs,static/**}

📄 CodeRabbit Inference Engine (.cursor/rules/navigation.mdc)

Templates live under codegenerator/cli/templates: dynamic/ for Handlebars (.hbs), static/ for raw Rescript files copied verbatim.

Files:

  • codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res
{**/generated/src/**/*.res,codegenerator/cli/templates/static/codegen/src/**/*.res,codegenerator/cli/templates/dynamic/codegen/src/**/*.res}

📄 CodeRabbit Inference Engine (.cursor/rules/navigation.mdc)

Runtime code lives in each project’s generated/src, but template versions (good for editing) are under codegenerator/cli/templates/static/codegen/src or codegenerator/cli/templates/dynamic/codegen/src.

Files:

  • codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res
codegenerator/cli/npm/envio/**

📄 CodeRabbit Inference Engine (.cursor/rules/navigation.mdc)

Library-fied runtime shared across indexers lives in codegenerator/cli/npm/envio.

Files:

  • codegenerator/cli/npm/envio/src/Prometheus.res
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_and_test
🔇 Additional comments (2)
codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res (2)

1042-1042: Good switch to Hrtime-based timing

Capturing the rollback start time with Hrtime is appropriate and aligns with the new Prometheus API.


1156-1157: Correct Prometheus usage for rollback success

Passing Hrtime.milliseconds directly to Prometheus.RollbackSuccess.increment is type-correct and avoids unnecessary conversions. Looks good.

Comment thread codegenerator/cli/npm/envio/src/Prometheus.res
@DZakh
DZakh enabled auto-merge (squash) August 18, 2025 14:54
@DZakh
DZakh merged commit 5860866 into main Aug 18, 2025
2 checks passed
@DZakh
DZakh deleted the dz/throttle-rollback-pruning-more branch August 18, 2025 15:02
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.

2 participants