我试图在 Golang 中监听块级事件。我根本无法接收块级事件。它只是始终显示块 0 并且不向前移动。我已经给出了示例代码。如果代码或在网络级别执行的任何其他设置有任何问题,请告诉我。 另一项观察是,如果代码是用 Nodejs 编写的,那么我能够监听块级事件,但不能用 Golang 来监听。
如果有任何解决方案,请告诉我。 我们正在使用 hyperledgr Fabric 2.4
func startBlocklevelEventListening(ctx context.Context, network client.Network) {
blockEvents, blockErr := network.BlockEvents(ctx, client.WithStartBlock(1))
if blockErr != nil {
panic(fmt.Errorf("failed to start chaincode event listening: %w", blockErr))
}
fmt.Println("\n** Start Block event listening")
go func() {
for event := range blockEvents {
hashBytes := event.GetHeader().GetDataHash()
hashString := fmt.Sprintf("%x", hashBytes)
blockNumber := event.GetHeader().GetNumber()
fmt.Printf("\n<-- Block event received: \n Received block number : %d \n Received block hash - %s\n", blockNumber, hashString)
}
}()
我使用 Fabric v2.5 和 Fabric-gateway v1.4 进行了尝试,并且能够接收块事件。我对现有的 asset-transfer-events/application-gateway-go 示例进行了以下修改:
修改了deleteAsset函数,使其返回提交交易的区块号(类似于现有的createAsset函数)。
func deleteAsset(contract *client.Contract) uint64 {
fmt.Printf("\n--> Submit transaction: DeleteAsset, %s\n", assetID)
_, commit, err := contract.SubmitAsync("DeleteAsset", client.WithArguments(assetID))
if err != nil {
panic(fmt.Errorf("failed to submit transaction: %w", err))
}
status, err := commit.Status()
if err != nil {
panic(fmt.Errorf("failed to get transaction commit status: %w", err))
}
if !status.Successful {
panic(fmt.Errorf("failed to commit transaction with status code %v", status.Code))
}
fmt.Println("\n*** DeleteAsset committed successfully")
return status.BlockNumber
}
添加了 replayBlockEvents 函数,类似于现有的 replayChaincodeEvents 函数。
func replayBlockEvents(ctx context.Context, network *client.Network, endBlock uint64) {
fmt.Println("\n*** Start block event replay")
events, err := network.BlockEvents(ctx, client.WithStartBlock(0))
if err != nil {
panic(fmt.Errorf("failed to start block event listening: %w", err))
}
for {
select {
case <-time.After(10 * time.Second):
panic(errors.New("timeout waiting for event replay"))
case event := <-events:
blockNumber := event.GetHeader().GetNumber()
fmt.Printf("\n<-- Replayed block number %d\n", blockNumber)
if blockNumber == endBlock {
// Reached the block containing the last submitted transaction so return to stop listening for events
return
}
}
}
}
修改了main函数的最后一部分以添加块事件的重播。
firstBlockNumber := createAsset(contract)
updateAsset(contract)
transferAsset(contract)
lastBlockNumber := deleteAsset(contract)
// Replay chaincode events from the block containing the first transaction
replayChaincodeEvents(ctx, network, firstBlockNumber)
// Replay block events up to the last committed block
replayBlockEvents(ctx, network, lastBlockNumber)
运行此应用程序会产生通常的控制台输出,加上 replayBlockEvents 函数的附加输出,清楚地表明块事件正在工作:
*** Start block event replay
<-- Replayed block number 0
<-- Replayed block number 1
<-- Replayed block number 2
<-- Replayed block number 3
<-- Replayed block number 4
<-- Replayed block number 5
<-- Replayed block number 6
<-- Replayed block number 7
<-- Replayed block number 8
<-- Replayed block number 9
在 replayBlockEvents 函数中使用更简单的 for-range 循环也有效。
for event := range events {
blockNumber := event.GetHeader().GetNumber()
fmt.Printf("\n<-- Replayed block number %d\n", blockNumber)
if blockNumber == endBlock {
// Reached the block containing the last submitted transaction so return to stop listening for events
return
}
}