From 2006f59bf7b3b51a6abf1896a9e15d0d8329cb53 Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Tue, 19 Nov 2019 05:40:18 +0000 Subject: [PATCH] peer/cmd/request: Introduce request timeout option MinBFT never fails in theory as long as we meet the requirement of "<= f faulty nodes", but unfortunately there's no bug-free softwares, so it's better to prepare for such potential issues to avoid infinite wait. This patch suggests to add timeout to the sample application. Note that if timeout value is not specified, sample application waits forever as it does now. Signed-off-by: Naoya Horiguchi --- sample/peer/cmd/request.go | 30 ++++++++++++++++++++++++++++-- sample/peer/peer.yaml | 3 +++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/sample/peer/cmd/request.go b/sample/peer/cmd/request.go index e234ac41..2d3103b9 100644 --- a/sample/peer/cmd/request.go +++ b/sample/peer/cmd/request.go @@ -19,8 +19,10 @@ package cmd import ( "bufio" + "context" "fmt" "os" + "time" "github.com/hyperledger-labs/minbft/api" "github.com/hyperledger-labs/minbft/client" @@ -57,6 +59,8 @@ func init() { requestCmd.Flags().Int("id", 0, "ID of the client") must(viper.BindPFlag("client.id", requestCmd.Flags().Lookup("id"))) + requestCmd.Flags().String("timeout", "0", "Timeout for the request") + must(viper.BindPFlag("client.timeout", requestCmd.Flags().Lookup("timeout"))) } type clientStack struct { @@ -64,12 +68,34 @@ type clientStack struct { api.ReplicaConnector } -func request(client client.Client, arg string) { - req := []byte(arg) +func requestInternal(ctx context.Context, ch chan bool, client client.Client, req []byte) { + defer func() { + ch <- true + }() res := <-client.Request(req) fmt.Println("Reply:", string(res)) } +func request(client client.Client, arg string) { + timeout := viper.GetDuration("client.timeout") + ctx := context.Background() + ch := make(chan bool) + req := []byte(arg) + + if timeout > time.Duration(0) { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, timeout) + time.AfterFunc(timeout, cancel) + } + + go requestInternal(ctx, ch, client, req) + select { + case <-ctx.Done(): + fmt.Println("Client Request timer expired.") + case <-ch: + } +} + func requests(args []string) ([]byte, error) { id := uint32(viper.GetInt("client.id")) diff --git a/sample/peer/peer.yaml b/sample/peer/peer.yaml index 79daba14..7d8ea249 100644 --- a/sample/peer/peer.yaml +++ b/sample/peer/peer.yaml @@ -16,6 +16,9 @@ client: # ID of the client instance id: 0 + # Client request timeout (default: 0s, i.e. never timeout) + timeout: 3s + # USIG options usig: # USIG enclave file (environment expansion is supported)