美文网首页
fabric支持的事件

fabric支持的事件

作者: CodingCode | 来源:发表于2020-09-04 08:18 被阅读0次
  1. fabric的事件

fabric支持四类事件:

  1. BlockEvent(filter ...fab.BlockFilter)
  2. FilteredBlockEvent()
  3. ChaincodeEvent(chaincodeID string, eventNameFilter string)
  4. TxStatusEvent(txID string)

几点注释

  • BlockEvent和FilteredBlockEvent是针对block的,即当生成一个block的时候就出发一个事件;两者的区别是是否包含block的payload数据(FilteredBlockEvent不含有payload,只包含block的metadata信息)。
  • 我不知道TxStatusEvent这个干什么用,用户怎么知道txID是什么呢?能想到的只有一种情况,即采用异步调用的时候,fabric首先返回txID,然后异步查询transaction的状态。
  • ChaincodeEvent:这个名字取得不好,让人误解,以为是chaincode相关的事件,其实这个是用户event,就是用户在chaincode里面显式的抛出的事件,我觉得这个事件最有用。

下面举一个ChaincodeEvent的例子

  1. ChaincodeEvent例子

2.1. chaincode抛出事件

func (e *ChaincodeImpl) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
  ...
  
  err = stub.PutState(mykey, myvalue)
  if err != nil {
    return shim.Error(fmt.Sprintf("unable put state (%s), error: %v", key, err))
  }

  err = stub.SetEvent("<eventName>", myvalue)
  if err != nil {
    return shim.Error(fmt.Sprintf("unable set event, error: %v", err))
  }

  return shim.Success(nil)
}

在chaincode invoke函数的最后return之前,通过调用stub.SetEven(name string, payload []byte)来抛出ChaincodeEvent。
包含两个参数eventName,和eventPayload。

2.2. 监听chaincode事件
下面是一个由fabric sdk实现的ChaincodeEvent的例子:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/hyperledger/fabric-sdk-go/pkg/client/event"
    "github.com/hyperledger/fabric-sdk-go/pkg/core/config"
    "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)

const (
    channelID   = "<channelID>"
    chaincodeID = "<chaincodeID>"
    eventID     = "<eventName>"
    mspID       = "<mspid>"
    userID      = "<userid>"
)

func main() {
    configOpt := config.FromFile("./profile.yaml")
    sdk, err := fabsdk.New(configOpt)
    if err != nil {
        log.Fatalf("Failed to create new SDK: %v\n", err)
        return
    }
    defer sdk.Close()

    clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser(userID), fabsdk.WithOrg(mspID))
    eventClient, err := event.New(clientChannelContext, event.WithBlockEvents())
    //eventClient, err := event.New(clientChannelContext)  // if this, you will not get payload data
    if err != nil {
        log.Fatalf("Failed to create event client: %v\n", err)
        return
    }

    reg, eventCh, err := eventClient.RegisterChaincodeEvent(chaincodeID, eventID)
    if err != nil {
        log.Fatalf("Failed to regitser block event: %v\n", err)
        return
    }
    defer eventClient.Unregister(reg)

    timeoutctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    defer cancel()
    for {
        select {
        case evtdata := <-eventCh:
            fmt.Printf("received a block: %s\n", evtdata.Payload)
        case <-timeoutctx.Done():
            fmt.Println("event timeout, exit!")
            return
        }
    }

    log.Printf("done\n")
}

需要匹配这里的eventID和chaincode里面stub.SetEvent(<eventName>,...),两个必须匹配。

可见ChaincodeEvent是比较常用的场景,用户只关注需要关注的内容,包括事件payload都是自定义的,而抛弃复杂的统一格式事件内容。

相关文章

网友评论

      本文标题:fabric支持的事件

      本文链接:https://www.haomeiwen.com/subject/mbgasktx.html