1. 程式人生 > >HyperLeger Fabric SDK開發(五)——event

HyperLeger Fabric SDK開發(五)——event

HyperLeger Fabric SDK開發(五)——event

一、event簡介

1、event簡介

event包支援訪問Fabric網路上的通道事件。事件客戶端可以接收區塊事件,過濾區塊事件,鏈碼事件和交易狀態事件。
官方文件:
https://godoc.org/github.com/hyperledger/fabric-sdk-go/pkg/client/event

2、event使用基本流程

event使用基本流程如下:
A、準備通道客戶端上下文
B、建立事件客戶端
C、註冊事件
D、處理事件(或超時)
E、登出事件
使用示例:

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

registration, notifier, err := ec.RegisterChaincodeEvent("examplecc", "event123")
if err != nil {
    fmt.Println("failed to register chaincode event")
}
defer ec.Unregister(registration)

select {
case ccEvent := <-notifier:
    fmt.Printf("received chaincode event %v\n", ccEvent)
case <-time.After(time.Second * 5):
    fmt.Println("timeout while waiting for chaincode event")
}

// Timeout is expected since there is no event producer
// output:
// timeout while waiting for chaincode event   

二、event常用介面

1、事件客戶端獲取

type Client struct {
   eventService      fab.EventService
   permitBlockEvents bool
   fromBlock         uint64
   seekType          seek.Type
}
func New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client, error)

返回事件客戶端例項。客戶端接收區塊事件,過濾區塊事件,鏈碼事件和交易狀態事件。
使用示例:

ctx := mockChannelProvider("mychannel")

ec, err := New(ctx, WithBlockEvents())
if err != nil {
    fmt.Println(err)
}

if ec != nil {
    fmt.Println("event client created")
} else {
    fmt.Println("event client is nil")
}
// output:
// event client created     

2、註冊區塊事件

func (c *Client) RegisterBlockEvent(filter ...fab.BlockFilter) (fab.Registration, &lt;-chan *fab.BlockEvent, error)


註冊塊事件。如果呼叫者沒有註冊區塊事件的許可權,則返回錯誤。不再需要註冊時,必須呼叫取消註冊。
引數:
filter是一個可選的過濾器,可過濾掉不需要的事件。只能指定一個過濾器。
返回:註冊物件和用於接收事件的通道。呼叫Unregister時,通道將關閉。
使用示例:

ec, err := New(mockChannelProvider("mychannel"), WithBlockEvents())
if err != nil {
    fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterBlockEvent()
if err != nil {
    fmt.Println("failed to register block event")
}
defer ec.Unregister(registration)

fmt.Println("block event registered successfully")
// output:
// block event registered successfully

3、註冊鏈碼事件

func (c *Client) RegisterChaincodeEvent(ccID, eventFilter string) (fab.Registration, &lt;-chan *fab.CCEvent, error)
註冊鏈程式碼事件。不再需要註冊時,必須呼叫Unregister。
引數:
ccID是用於接收事件的鏈碼ID
eventFilter是用於接收事件的鏈碼事件過濾器(正則表示式)
返回:註冊物件和用於接收事件的通道。 呼叫取消註冊時,通道將關閉。
使用示例:

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterChaincodeEvent("examplecc", "event123")
if err != nil {
    fmt.Println("failed to register chaincode event")
}
defer ec.Unregister(registration)

fmt.Println("chaincode event registered successfully")
// output:
// chaincode event registered successfully

使用示例:

// If you require payload for chaincode events you have to use WithBlockEvents() option
ec, err := New(mockChannelProvider("mychannel"), WithBlockEvents())
if err != nil {
    fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterChaincodeEvent("examplecc", "event123")
if err != nil {
    fmt.Println("failed to register chaincode event")
}
defer ec.Unregister(registration)

fmt.Println("chaincode event registered successfully")
// output:
// chaincode event registered successfully

4、註冊過濾區塊事件

func (c *Client) RegisterFilteredBlockEvent() (fab.Registration, &lt;-chan *fab.FilteredBlockEvent, error)
註冊過濾區塊事件。當不再需要註冊時,必須呼叫Unregister。
返回:註冊物件和用於接收事件的通道。呼叫Unregister時,通道將關閉。
使用示例:

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterFilteredBlockEvent()
if err != nil {
    fmt.Println("failed to register filtered block event")
}
defer ec.Unregister(registration)

fmt.Println("filtered block event registered successfully")
// output:
// filtered block event registered successfully

5、註冊交易狀態事件

func (c *Client) RegisterTxStatusEvent(txID string) (fab.Registration, &lt;-chan *fab.TxStatusEvent, error)
註冊交易狀態事件。不再需要註冊時,必須呼叫Unregister。
引數:
txID是用於接收事件的交易ID
返回:註冊物件和用於接收事件的通道。呼叫Unregister時,通道將關閉。
使用示例:

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterTxStatusEvent("tx123")
if err != nil {
    fmt.Println("failed to register tx status event")
}
defer ec.Unregister(registration)

fmt.Println("tx status event registered successfully")
// output:
// tx status event registered successfully

6、登出

func (c *Client) Unregister(reg fab.Registration)
刪除給定的註冊物件並關閉事件通道。
引數:
reg是從其中一個註冊函式返回的註冊控制代碼

7、ClientOption選項構建

type ClientOption func(*Client) error
func WithBlockEvents() ClientOption

WithBlockEvents指示要接收的區塊事件。 注意,呼叫者必須具有此選項的足夠許可權。
func WithBlockNum(from uint64) ClientOption
WithBlockNum表示用於接收事件的區塊編號。只有deliverclient支援次選項。
func WithSeekType(seek seek.Type) ClientOption
WithSeekType表示所需的搜尋型別,最新,最舊或來自給定區塊,只有deliverclient支援此項。

三、event示例

var (
   sdk           *fabsdk.FabricSDK
   channelName   = "assetchannel"
   org           = "org1"
   user          = "Admin"
)
ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))

cli, err := event.New(ctx)
if err != nil {
panic(err)
}

// 區塊事件
reg, blkevent, err := cli.RegisterBlockEvent()
if err != nil {
panic(err)
}
defer cli.Unregister(reg)

timeoutctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

for {
    select {
    case evt := <-blkevent:
    fmt.Printf("received a block", evt)
    case <-timeoutctx.Done():
    fmt.Println("event timeout, exit!")
    return
}