55 "crypto/tls"
66 "encoding/json"
77 "fmt"
8- "hash/fnv"
9- "math"
108 "net"
119 "strings"
1210 "sync"
@@ -25,12 +23,39 @@ type KafkaPublisher struct {
2523 chainID string
2624}
2725
28- type PublishableBlockMessage struct {
26+ type MessageType string
27+
28+ type PublishableData interface {
29+ GetType () MessageType
30+ }
31+
32+ type PublishableMessagePayload struct {
33+ Data PublishableData `json:"data"`
34+ Type MessageType `json:"type"`
35+ Timestamp time.Time `json:"timestamp"`
36+ }
37+
38+ type PublishableMessageBlockData struct {
2939 common.BlockData
3040 Sign int8 `json:"sign"`
3141 InsertTimestamp time.Time `json:"insert_timestamp"`
3242}
3343
44+ type PublishableMessageRevert struct {
45+ ChainId uint64 `json:"chain_id"`
46+ BlockNumber uint64 `json:"block_number"`
47+ Sign int8 `json:"sign"`
48+ InsertTimestamp time.Time `json:"insert_timestamp"`
49+ }
50+
51+ func (b PublishableMessageBlockData ) GetType () MessageType {
52+ return "block_data"
53+ }
54+
55+ func (b PublishableMessageRevert ) GetType () MessageType {
56+ return "revert"
57+ }
58+
3459// NewKafkaPublisher method for storage connector (public)
3560func NewKafkaPublisher (cfg * config.KafkaConfig ) (* KafkaPublisher , error ) {
3661 brokers := strings .Split (cfg .Brokers , "," )
@@ -91,6 +116,12 @@ func (p *KafkaPublisher) PublishBlockData(blockData []common.BlockData) error {
91116}
92117
93118func (p * KafkaPublisher ) PublishReorg (oldData []common.BlockData , newData []common.BlockData ) error {
119+ newHead := uint64 (newData [0 ].Block .Number .Uint64 ())
120+ // Publish revert the revert to the new head - 1, so that the new updated block data can be re-processed
121+ if err := p .publishBlockRevert (newData [0 ].ChainId , newHead - 1 ); err != nil {
122+ return fmt .Errorf ("failed to revert: %v" , err )
123+ }
124+
94125 if err := p .publishBlockData (oldData , true ); err != nil {
95126 return fmt .Errorf ("failed to publish old block data: %v" , err )
96127 }
@@ -149,6 +180,27 @@ func (p *KafkaPublisher) publishMessages(ctx context.Context, messages []*kgo.Re
149180 return nil
150181}
151182
183+ func (p * KafkaPublisher ) publishBlockRevert (chainId uint64 , blockNumber uint64 ) error {
184+ publishStart := time .Now ()
185+
186+ // Prepare messages for blocks, events, transactions and traces
187+ blockMessages := make ([]* kgo.Record , 1 )
188+
189+ // Block message
190+ if blockMsg , err := p .createBlockRevertMessage (chainId , blockNumber ); err == nil {
191+ blockMessages [0 ] = blockMsg
192+ } else {
193+ return fmt .Errorf ("failed to create block revert message: %v" , err )
194+ }
195+
196+ if err := p .publishMessages (context .Background (), blockMessages ); err != nil {
197+ return fmt .Errorf ("failed to publish block revert messages: %v" , err )
198+ }
199+
200+ log .Debug ().Str ("metric" , "publish_duration" ).Msgf ("Publisher.PublishBlockData duration: %f" , time .Since (publishStart ).Seconds ())
201+ return nil
202+ }
203+
152204func (p * KafkaPublisher ) publishBlockData (blockData []common.BlockData , isDeleted bool ) error {
153205 if len (blockData ) == 0 {
154206 return nil
@@ -176,47 +228,71 @@ func (p *KafkaPublisher) publishBlockData(blockData []common.BlockData, isDelete
176228 return nil
177229}
178230
179- func (p * KafkaPublisher ) createBlockDataMessage (data common.BlockData , isDeleted bool ) (* kgo.Record , error ) {
180- insertTimestamp := time .Now ()
181- msg := PublishableBlockMessage {
182- BlockData : data .Serialize (),
231+ func (p * KafkaPublisher ) createBlockDataMessage (block common.BlockData , isDeleted bool ) (* kgo.Record , error ) {
232+ timestamp := time .Now ()
233+
234+ data := PublishableMessageBlockData {
235+ BlockData : block ,
183236 Sign : 1 ,
184- InsertTimestamp : insertTimestamp ,
237+ InsertTimestamp : timestamp ,
185238 }
186239 if isDeleted {
187- msg .Sign = - 1 // Indicate deletion with a negative sign
240+ data .Sign = - 1
188241 }
242+
243+ msg := PublishableMessagePayload {
244+ Data : data ,
245+ Type : data .GetType (),
246+ Timestamp : timestamp ,
247+ }
248+
189249 msgJson , err := json .Marshal (msg )
190250 if err != nil {
191251 return nil , fmt .Errorf ("failed to marshal block data: %v" , err )
192252 }
193253
194- // Determine partition based on chainID
195- var partition int32
196- if data .ChainId <= math .MaxInt32 {
197- // Direct assignment for chain IDs that fit in int32
198- partition = int32 (data .ChainId )
199- } else {
200- // Hash for larger chain IDs to avoid overflow
201- h := fnv .New32a ()
202- fmt .Fprintf (h , "%d" , data .ChainId )
203- partition = int32 (h .Sum32 () & 0x7FFFFFFF ) // Ensure positive
254+ return p .createRecord (data .GetType (), block .ChainId , block .Block .Number .Uint64 (), timestamp , msgJson )
255+ }
256+
257+ func (p * KafkaPublisher ) createBlockRevertMessage (chainId uint64 , blockNumber uint64 ) (* kgo.Record , error ) {
258+ timestamp := time .Now ()
259+
260+ data := PublishableMessageRevert {
261+ ChainId : chainId ,
262+ BlockNumber : blockNumber ,
263+ Sign : 1 ,
264+ InsertTimestamp : timestamp ,
265+ }
266+
267+ msg := PublishableMessagePayload {
268+ Data : data ,
269+ Type : data .GetType (),
270+ Timestamp : timestamp ,
204271 }
205272
273+ msgJson , err := json .Marshal (msg )
274+ if err != nil {
275+ return nil , fmt .Errorf ("failed to marshal block data: %v" , err )
276+ }
277+
278+ return p .createRecord (data .GetType (), chainId , blockNumber , timestamp , msgJson )
279+ }
280+
281+ func (p * KafkaPublisher ) createRecord (msgType MessageType , chainId uint64 , blockNumber uint64 , timestamp time.Time , msgJson []byte ) (* kgo.Record , error ) {
206282 // Create headers with metadata
207283 headers := []kgo.RecordHeader {
208- {Key : "chain_id" , Value : []byte (fmt .Sprintf ("%d" , data . ChainId ))},
209- {Key : "block_number" , Value : []byte (fmt .Sprintf ("%d" , data . Block . Number ))},
210- {Key : "sign " , Value : []byte (fmt .Sprintf ("%d " , msg . Sign ))},
211- {Key : "insert_timestamp " , Value : []byte (insertTimestamp .Format (time .RFC3339Nano ))},
284+ {Key : "chain_id" , Value : []byte (fmt .Sprintf ("%d" , chainId ))},
285+ {Key : "block_number" , Value : []byte (fmt .Sprintf ("%d" , blockNumber ))},
286+ {Key : "type " , Value : []byte (fmt .Sprintf ("%s " , msgType ))},
287+ {Key : "timestamp " , Value : []byte (timestamp .Format (time .RFC3339Nano ))},
212288 {Key : "schema_version" , Value : []byte ("1" )},
213289 }
214290
215291 return & kgo.Record {
216- Topic : "insight.commit.blocks" ,
217- Key : []byte (fmt .Sprintf ("blockdata-%d-%d-%s- %d" , data . ChainId , data . Block . Number , data . Block . Hash , msg . Sign )),
292+ Topic : fmt . Sprintf ( "insight.commit.blocks.%d" , chainId ) ,
293+ Key : []byte (fmt .Sprintf ("%d:%s: %d" , chainId , msgType , blockNumber )),
218294 Value : msgJson ,
219295 Headers : headers ,
220- Partition : partition ,
296+ Partition : 0 ,
221297 }, nil
222298}
0 commit comments