-
Notifications
You must be signed in to change notification settings - Fork 8
Add TTL expiration for completed transactions in EOA executor #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TTL expiration for completed transactions in EOA executor #94
Conversation
WalkthroughThe changes add TTL (Time To Live) configuration for completed transactions throughout the EOA executor system. A new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
scripts/simple-redis-cleanup.ts (1)
3-3: UseBun.redisinstead ofioredis.Based on coding guidelines and learnings, scripts under
scripts/**/*.{ts,tsx,js,jsx}should useBun.redisfor Redis connections rather than theioredislibrary.Apply this pattern to migrate to Bun's native Redis client:
-import Redis from "ioredis"; +// Bun.redis provides native Redis supportThen update the constructor and usage accordingly:
constructor() { this.redis = Bun.redis(CONFIG.redisUrl); }Note: Verify the Bun.redis API for any differences in method signatures (scan, pipeline, etc.) compared to ioredis.
scripts/redis-cleanup/index.tsx (1)
3-3: Migrate fromioredistoBun.redis(requires substantial refactoring).File matches the
scripts/**/*.tsxpattern and must useBun.redisper coding guidelines. However, this migration is not a simple import swap—Bun.redis does not provide an explicitpipeline()API, requiring refactoring of batch operations at lines 111, 272, and 315.Required changes:
- Line 3: Replace
import Redis from "ioredis"withimport { redis } from "bun"- Line 59: Replace
this.redis = new Redis(CONFIG.redisUrl)withthis.redis = redis(CONFIG.redisUrl)- Lines 111–120 (hmget batch): Replace explicit pipeline with
Promise.all()for concurrenthmget()calls- Lines 272–283 (del batch): Replace explicit pipeline with
Promise.all()for concurrentdel()calls- Lines 315–354 (batch delete): Replace explicit pipeline with
Promise.all()for concurrentdel()calls across all transactionsBun.redis automatically pipelines concurrent commands, so restructuring to use
Promise.all()achieves the same batching behavior without explicit pipeline management.
🧹 Nitpick comments (2)
executors/src/eoa/store/mod.rs (1)
100-104: TTL field added to EoaExecutorStore is consistent with designAdding
pub completed_transaction_ttl_seconds: u64onEoaExecutorStoregives downstream modules a single source for TTL configuration. This aligns with how other store metadata is exposed.If this field is only ever used internally by the store modules, you could drop
puband/or add a short doc comment clarifying that the unit is seconds to prevent future misuse.server/src/http/routes/admin/eoa_diagnostics.rs (1)
126-132: Diagnostics now honor the same TTL configuration as the workerEach admin handler now builds
EoaExecutorStorewitheoa_queue.handler.completed_transaction_ttl_seconds, so diagnostics and manual reset logic see a store configured identically to the live executor. This is the right place to source TTL from and keeps behavior consistent across read and write paths.Given the repeated pattern of:
- grabbing
redis_conn,namespace, andcompleted_transaction_ttl_secondsfromeoa_queue.handler, and- constructing
EoaExecutorStore::new(...)consider extracting a small helper (e.g.,
fn make_eoa_store(state: &EngineServerState, eoa: Address, chain_id: u64) -> EoaExecutorStore) to reduce duplication and keep future TTL/config changes in one place.Also applies to: 215-217, 269-272, 333-336, 379-382, 422-425
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (12)
executors/src/eoa/store/atomic.rs(4 hunks)executors/src/eoa/store/borrowed.rs(2 hunks)executors/src/eoa/store/mod.rs(3 hunks)executors/src/eoa/store/submitted.rs(2 hunks)executors/src/eoa/worker/mod.rs(2 hunks)scripts/redis-cleanup/index.tsx(3 hunks)scripts/simple-redis-cleanup.ts(1 hunks)server/configuration/server_base.yaml(1 hunks)server/src/config.rs(2 hunks)server/src/execution_router/mod.rs(1 hunks)server/src/http/routes/admin/eoa_diagnostics.rs(6 hunks)server/src/queue/manager.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
scripts/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (scripts/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
scripts/**/*.{ts,tsx,js,jsx}: Usebun <file>instead ofnode <file>orts-node <file>to run JS/TS files
Do not usedotenv; Bun automatically loads .env files
UseBun.serve()for HTTP/WebSocket servers; do not useexpress
Usebun:sqlitefor SQLite; do not usebetter-sqlite3
UseBun.redisfor Redis; do not useioredis
UseBun.sqlfor Postgres; do not usepgorpostgres.js
Use built-inWebSocket; do not usews
PreferBun.fileovernode:fsreadFile/writeFile for file IO
UseBun.$(shell) instead ofexeca
Files:
scripts/redis-cleanup/index.tsxscripts/simple-redis-cleanup.ts
scripts/**/*.{html,ts,tsx,css}
📄 CodeRabbit inference engine (scripts/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
Use
bun build <file.html|file.ts|file.css>instead ofwebpackoresbuild
Files:
scripts/redis-cleanup/index.tsxscripts/simple-redis-cleanup.ts
🧠 Learnings (5)
📚 Learning: 2025-09-20T06:58:40.230Z
Learnt from: d4mr
Repo: thirdweb-dev/engine-core PR: 48
File: executors/src/eoa/store/submitted.rs:229-230
Timestamp: 2025-09-20T06:58:40.230Z
Learning: The diff in executors/src/eoa/store/submitted.rs shows correct brace structure - the first closing brace closes the remove_transaction_from_redis_submitted_zset method and the second closing brace closes the impl CleanSubmittedTransactions block. The change only adds whitespace formatting.
Applied to files:
executors/src/eoa/store/borrowed.rsexecutors/src/eoa/store/submitted.rsserver/src/execution_router/mod.rsexecutors/src/eoa/worker/mod.rsexecutors/src/eoa/store/atomic.rsexecutors/src/eoa/store/mod.rsserver/src/http/routes/admin/eoa_diagnostics.rsserver/src/queue/manager.rs
📚 Learning: 2025-09-20T05:30:35.171Z
Learnt from: joaquim-verges
Repo: thirdweb-dev/engine-core PR: 48
File: executors/src/eoa/worker/send.rs:20-21
Timestamp: 2025-09-20T05:30:35.171Z
Learning: In executors/src/eoa/worker/send.rs, there is a critical bug where HEALTH_CHECK_INTERVAL is defined as 300 seconds but compared against millisecond timestamps, causing balance checks to occur every 300ms instead of every 5 minutes (1000x more frequent than intended).
Applied to files:
executors/src/eoa/worker/mod.rsserver/src/http/routes/admin/eoa_diagnostics.rsserver/src/queue/manager.rs
📚 Learning: 2025-09-20T07:40:58.898Z
Learnt from: CR
Repo: thirdweb-dev/engine-core PR: 0
File: scripts/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-09-20T07:40:58.898Z
Learning: Applies to scripts/**/*.{ts,tsx,js,jsx} : Use `Bun.redis` for Redis; do not use `ioredis`
Applied to files:
scripts/redis-cleanup/index.tsxscripts/simple-redis-cleanup.ts
📚 Learning: 2025-07-06T15:44:13.701Z
Learnt from: d4mr
Repo: thirdweb-dev/engine-core PR: 5
File: executors/src/eoa/worker.rs:173-176
Timestamp: 2025-07-06T15:44:13.701Z
Learning: The EOA executor store uses comprehensive WATCH-based coordination where every Redis state mutation watches the lock key and validates ownership before proceeding. If the lock is lost during any operation, the transaction fails with LockLost error. This makes aggressive lock acquisition safe because only the actual lock holder can successfully perform state mutations, regardless of who claims the lock.
Applied to files:
executors/src/eoa/store/mod.rsserver/src/http/routes/admin/eoa_diagnostics.rs
📚 Learning: 2025-07-06T15:44:13.701Z
Learnt from: d4mr
Repo: thirdweb-dev/engine-core PR: 5
File: executors/src/eoa/worker.rs:173-176
Timestamp: 2025-07-06T15:44:13.701Z
Learning: In the EOA executor system, aggressive lock acquisition is safe because every Redis state mutation uses WATCH operations on the lock key. If the lock is lost during a transaction, the WATCH causes the transaction to fail and the worker exits gracefully. This provides coordination between workers even when using forceful lock takeover.
Applied to files:
executors/src/eoa/store/mod.rsserver/src/http/routes/admin/eoa_diagnostics.rs
🧬 Code graph analysis (1)
server/src/http/routes/admin/eoa_diagnostics.rs (2)
executors/src/eoa/store/mod.rs (2)
new(113-119)new(297-313)executors/src/eoa/store/atomic.rs (1)
chain_id(89-91)
🔇 Additional comments (20)
scripts/simple-redis-cleanup.ts (1)
13-13: Good safety improvement.Changing the default to
dryRun: trueis a conservative and safe choice that prevents accidental data deletion. Users must now explicitly opt-in to actual deletion operations.server/configuration/server_base.yaml (1)
27-43: TTL config default looks correct
completed_transaction_ttl_seconds: 86400is a sensible 1‑day default and consistent with the field name and comment. No issues from the config side.server/src/execution_router/mod.rs (1)
451-459: EOA store TTL wiring is consistent with worker configurationPassing
self.eoa_executor_queue.handler.completed_transaction_ttl_secondsintoEoaExecutorStore::newensures the router uses the same TTL as the EOA worker, keeping behavior consistent for completed transactions.executors/src/eoa/worker/mod.rs (2)
162-168: Scoped store now correctly receives TTLPassing
self.completed_transaction_ttl_secondsintoEoaExecutorStore::newensures the worker’s scoped store uses the configured TTL for completed transactions. This keeps TTL behavior centralized on the handler.
129-132: All handler construction sites properly initializecompleted_transaction_ttl_secondsfrom queue config; no action needed.The verification confirms that the single handler construction site in
server/src/queue/manager.rs:264correctly setscompleted_transaction_ttl_seconds: queue_config.completed_transaction_ttl_seconds, which is populated from configuration with a default of 86400 seconds (1 day). The field is never uninitialized or defaulted to zero.executors/src/eoa/store/mod.rs (1)
297-303: Constructor update cleanly threads in completed_transaction_ttl_secondsExtending
EoaExecutorStore::newto takecompleted_transaction_ttl_secondsand store it on the struct is straightforward and keeps existing call‑sites explicit about TTL configuration.Also applies to: 311-312
server/src/config.rs (2)
54-55: LGTM!The new TTL configuration field is properly structured with a serde default and follows the existing configuration patterns in the file.
76-78: LGTM!The default TTL value of 86400 seconds (1 day) is reasonable for completed transaction cleanup, providing a balance between data retention and storage efficiency.
executors/src/eoa/store/borrowed.rs (2)
44-44: LGTM!The field addition properly threads the TTL configuration through the borrowed transaction processing flow.
230-236: LGTM!The TTL expiration is correctly applied to failed transactions. The Success path appropriately omits TTL here since those transactions transition to submitted state and are handled by the cleanup logic in
submitted.rs. The Nack path correctly omits TTL as transactions return to pending state.executors/src/eoa/store/submitted.rs (2)
203-203: LGTM!The field addition properly enables TTL configuration for submitted transaction cleanup operations.
364-367: LGTM!The TTL expiration is correctly applied to confirmed transactions, ensuring automatic cleanup after the configured duration. The logic appropriately applies TTL only to completed transactions (SCENARIO 1), while replaced transactions (SCENARIO 2) correctly omit TTL as they transition back to pending state.
server/src/queue/manager.rs (1)
264-264: LGTM!The TTL configuration is correctly propagated from
QueueConfigtoEoaExecutorJobHandler, completing the configuration chain from config files to the executor system.executors/src/eoa/store/atomic.rs (4)
592-598: LGTM!The TTL expiration is correctly applied to failed pending transactions, ensuring both the transaction data and attempts list are automatically cleaned up after the configured duration.
668-675: LGTM!The batch failure operation correctly applies the same TTL logic as the single-transaction case, ensuring consistency across both code paths.
734-734: LGTM!The TTL is correctly threaded from the store into the
CleanSubmittedTransactionsoperation.
752-752: LGTM!The TTL is correctly threaded from the store into the
ProcessBorrowedTransactionsoperation, maintaining consistency with theCleanSubmittedTransactionspattern.scripts/redis-cleanup/index.tsx (3)
15-17: LGTM: More conservative defaults improve safety.The updated defaults are appropriate:
dryRun: trueprevents accidental deletions- Larger
batchSizeimproves efficiency- Higher
progressIntervalreduces log noise
222-229: Question: Does 1-month minimum align with the 1-day TTL?The safety window was increased from 1 minute to 1 month, but the PR introduces a 1-day TTL (86400 seconds) for completed transactions. This means:
- TTL should auto-expire transactions after 1 day
- This cleanup script won't touch anything under 30 days old
- Gap: Transactions that survive TTL expiration would accumulate for 29 days before cleanup
Is this 30-day buffer intentional, or should it be closer to the TTL duration (e.g., 2-3 days) to catch TTL failures sooner?
307-309: LGTM: Aggregated logging reduces noise.Replacing per-transaction dry-run logs with a single summary improves readability and performance while still providing the necessary information.

Summary by CodeRabbit
Release Notes
New Features
Configuration
✏️ Tip: You can customize this high-level summary in your review settings.