Nats Data Stream#1966
Conversation
5e001ec to
ff6bce2
Compare
IvanBelyakoff
left a comment
There was a problem hiding this comment.
I did my best to look through the files. Amazing job!
Given the amount of tests, I believe it is much better tested than what we had!
ff6bce2 to
5fac91c
Compare
5fac91c to
c34a6b4
Compare
c34a6b4 to
b22334e
Compare
* Initial plan * Update zkevm-data-streamer to v0.2.11 and Go to 1.25 Co-authored-by: tamingchaos <6331188+tamingchaos@users.noreply.github.com> * Remove accidentally committed binary Co-authored-by: tamingchaos <6331188+tamingchaos@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tamingchaos <6331188+tamingchaos@users.noreply.github.com>
This commit introduces a suite of tests for NATS JetStream, covering various functionalities including: - Basic server operations and message publishing - Server-client communication setup - Bidirectional message exchange - Cluster replication and fault tolerance - Message ordering verification - Persistence of messages across server restarts These tests ensure the reliability and performance of NATS as an embedded service within the Erigon datastreaming infrastructure.
…d JetStream replication
…treaming - Implement NATS client with full DatastreamClient interface compatibility - Add state machines for reliable L2 block processing and message ordering - Support bookmark-based stream positioning via NATS KV store - Include comprehensive test suite with e2e, behavior, and interface tests - Add configuration for NATS connection (host, port, TLS support) - Document state machines and architecture with Mermaid diagrams - Integrate NATS client into stage_batches with factory pattern
… metadata management
59a1355 to
48d4aa8
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR introduces NATS JetStream as an alternative datastreaming infrastructure for Erigon's zkEVM implementation, moving away from the file-based datastreamer approach. The changes include:
- Implementation of a NATS-based datastream client and server that wraps the existing file-based implementation
- Comprehensive test suite for NATS functionality including cluster configurations, persistence, and various topologies
- Integration of NATS metadata management using JetStream KV store for tracking stream state
- Factory pattern for creating NATS-enabled stream servers
Reviewed Changes
Copilot reviewed 64 out of 65 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| zk/stages/test_utils.go | Adds ExecutePerFile stub method to TestDatastreamClient interface |
| zk/stages/stage_batches_test.go | Updates type reference from local DatastreamClient to types.DatastreamClient |
| zk/stages/stage_batches_datastream.go | Moves isReading check earlier in StartRead and updates type references |
| zk/stages/stage_batches.go | Extracts DatastreamClient interface to types package and updates imports |
| zk/datastream/types/client.go | Defines DatastreamClient interface with ExecutePerFile method |
| zk/datastream/test/nats/*.go | Comprehensive test suite for NATS functionality |
| zk/datastream/natsstream/*.go | NATS implementation files including client, server, metadata management |
| zk/datastream/server/*.go | Updates factory interface signature and adds version parameter comment |
| zk/datastream/test/data_stream_compare/test_datastream_compare.go | Renames NewClient to NewStreamClient |
| turbo/cli/default_flags.go | Adds new command-line flags for NATS configuration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if r.isReading.Load() { | ||
| return fmt.Errorf("tried starting datastream client runner thread while another is running") | ||
| } | ||
|
|
||
| if diffBlock > client.DefaultEntryChannelSize { |
There was a problem hiding this comment.
The reordering of the isReading check is good, but there's a race condition: between checking isReading (line 29) and setting it later (line 38 in the original, not shown but implied), another goroutine could start. Consider using atomic.CompareAndSwap to atomically check and set the flag to prevent this race condition.
|
|
||
| func (f *ZkEVMDataStreamServerFactory) CreateStreamServer(port uint16, systemID uint64, streamType datastreamer.StreamType, fileName string, writeTimeout time.Duration, inactivityTimeout time.Duration, inactivityCheckInterval time.Duration, cfg *dslog.Config) (StreamServer, error) { | ||
| // after we moved to protobuff encoding we no longer need to support multiple versions. | ||
| // The version parameter from the interface is ignored as we've hardcoded the version to 3 |
There was a problem hiding this comment.
The comment states that the version parameter is ignored, but the method signature in the interface (line 57 of interfaces.go) doesn't include a version parameter anymore. This comment appears to be outdated and should be updated or removed to avoid confusion.
| func (n *NATSStreamServer) GetDataBetweenBookmarks(bookmarkFrom, bookmarkTo []byte) ([]byte, error) { | ||
| // TODO: This method appears to be unused and should be removed from the interface | ||
| // after the original datastreamer is retired. We're not implementing it for NATS. | ||
| panic("GetDataBetweenBookmarks is not implemented for NATS and appears to be unused. " + | ||
| "This method should be removed from the interface after datastreamer is fully retired.") | ||
| } |
There was a problem hiding this comment.
Using panic for unimplemented methods in production code is problematic. If this method is called, it will crash the application. Consider returning an error like fmt.Errorf('GetDataBetweenBookmarks is not implemented for NATS') instead, which allows callers to handle the situation gracefully.
Resolves three issues identified by GitHub Copilot PR review on PR 0xPolygon#1966. ## 1. Fix race condition in DatastreamClientRunner.StartRead **File:** zk/stages/stage_batches_datastream.go **Issue:** TOCTOU (time-of-check-to-time-of-use) race condition between checking isReading flag and setting it inside goroutine. **Fix:** Use atomic.CompareAndSwap to atomically check and set the flag: - Changed from Load() + Store() pattern to CompareAndSwap(false, true) - Removed redundant Store(true) from inside goroutine - Ensures only one goroutine can start reading at a time **Impact:** Prevents potential race where multiple goroutines could start reading simultaneously. ## 2. Update outdated comment about version parameter **File:** zk/datastream/server/data_stream_server.go **Issue:** Comment referenced non-existent "version parameter from interface" that was removed in earlier refactoring. **Fix:** Updated comment to explain why version 3 is hardcoded: - Before: "The version parameter from the interface is ignored..." - After: "Version 3 is hardcoded for protobuf encoding support" **Impact:** Improves code clarity and removes confusion. ## 3. Replace panic with error return **File:** zk/datastream/natsstream/stream_server.go **Issue:** GetDataBetweenBookmarks() used panic() for unimplemented method, which would crash the application if called. **Fix:** Return proper error instead of panic: - Changed: panic("...") - To: return nil, fmt.Errorf("...") **Impact:** Allows callers to handle unimplemented method gracefully instead of crashing. Method is marked for removal after datastreamer retirement.
This pull request introduces support for NATS-based datastreaming in the zkevm module, allowing the system to use NATS as a backend for data streaming in addition to the existing TCP-based solution. It adds new configuration flags and options, updates the client and server initialization logic to support NATS, and refactors related code to use more flexible interfaces. Several dependencies are also updated to support the new functionality.
NATS datastreaming integration:
L2NatsUrl,DataStreamNatsHost,DataStreamNatsPort) to enable and configure NATS-based datastream endpoints (cmd/utils/flags.go,eth/ethconfig/config_zkevm.go,turbo/cli/default_flags.go,turbo/cli/flags_zkevm.go) [1] [2] [3] [4] [5].natsManagerin theEthereumstruct, initialized and started in the backend, with proper shutdown logic (eth/backend.go) [1] [2] [3].eth/backend.go,zk/datastream/client/stream_client.go) [1] [2] [3] [4].Refactoring and abstraction improvements:
eth/backend.go,turbo/stages/zk_stages.go,zk/datastream/client/stream_client.go) [1] [2] [3] [4].NewClientintoNewClient(returns interface) andNewStreamClient(returns concrete type), and updated tests to use the correct constructor (zk/datastream/client/stream_client.go,zk/datastream/client/stream_client_test.go) [1] [2] [3] [4] [5] [6] [7] [8].Dependency updates:
go.modto support NATS and other improvements [1] [2] [3] [4] [5].Minor improvements:
eth/backend.go).