@@ -26,6 +26,7 @@ import (
26
26
"net/http"
27
27
"net/url"
28
28
"strings"
29
+ "time"
29
30
30
31
"github.com/google/go-querystring/query"
31
32
@@ -39,6 +40,8 @@ import (
39
40
"github.com/algorand/go-algorand/ledger/eval"
40
41
"github.com/algorand/go-algorand/ledger/ledgercore"
41
42
"github.com/algorand/go-algorand/protocol"
43
+ "github.com/algorand/go-algorand/rpcs"
44
+ "github.com/algorand/go-algorand/test/e2e-go/globals"
42
45
)
43
46
44
47
const (
@@ -283,12 +286,77 @@ func (client RestClient) Status() (response model.NodeStatusResponse, err error)
283
286
return
284
287
}
285
288
286
- // WaitForBlock returns the node status after waiting for the given round.
287
- func (client RestClient ) WaitForBlock (round basics.Round ) (response model.NodeStatusResponse , err error ) {
289
+ // WaitForBlockAfter returns the node status after trying to wait for the given
290
+ // round+1. This REST API has the documented misfeatures of returning after 1
291
+ // minute, regardless of whether the given block has been reached.
292
+ func (client RestClient ) WaitForBlockAfter (round basics.Round ) (response model.NodeStatusResponse , err error ) {
288
293
err = client .get (& response , fmt .Sprintf ("/v2/status/wait-for-block-after/%d/" , round ), nil )
289
294
return
290
295
}
291
296
297
+ // WaitForRound returns the node status after waiting for the given round.
298
+ func (client RestClient ) WaitForRound (round uint64 , waitTime time.Duration ) (status model.NodeStatusResponse , err error ) {
299
+ timeout := time .NewTimer (waitTime )
300
+ for {
301
+ status , err = client .Status ()
302
+ if err != nil {
303
+ return
304
+ }
305
+
306
+ if status .LastRound >= round {
307
+ return
308
+ }
309
+ select {
310
+ case <- timeout .C :
311
+ return model.NodeStatusResponse {}, fmt .Errorf ("timeout waiting for round %v with last round = %v" , round , status .LastRound )
312
+ case <- time .After (200 * time .Millisecond ):
313
+ }
314
+ }
315
+ }
316
+
317
+ const singleRoundMaxTime = globals .MaxTimePerRound * 40
318
+
319
+ // WaitForRoundWithTimeout waits for a given round to be reached. As it
320
+ // waits, it returns early with an error if the wait time for any round exceeds
321
+ // globals.MaxTimePerRound so we can alert when we're getting "hung" waiting.
322
+ func (client RestClient ) WaitForRoundWithTimeout (roundToWaitFor uint64 ) error {
323
+ status , err := client .Status ()
324
+ if err != nil {
325
+ return err
326
+ }
327
+ lastRound := status .LastRound
328
+
329
+ // If node is already at or past target round, we're done
330
+ if lastRound >= roundToWaitFor {
331
+ return nil
332
+ }
333
+
334
+ roundComplete := make (chan error , 2 )
335
+
336
+ for nextRound := lastRound + 1 ; lastRound < roundToWaitFor ; nextRound ++ {
337
+ roundStarted := time .Now ()
338
+
339
+ go func (done chan error ) {
340
+ stat , err := client .WaitForRound (nextRound , singleRoundMaxTime )
341
+ lastRound = stat .LastRound
342
+ done <- err
343
+ }(roundComplete )
344
+
345
+ select {
346
+ case lastError := <- roundComplete :
347
+ if lastError != nil {
348
+ close (roundComplete )
349
+ return lastError
350
+ }
351
+ case <- time .After (singleRoundMaxTime ):
352
+ // we've timed out.
353
+ time := time .Since (roundStarted )
354
+ return fmt .Errorf ("fixture.WaitForRound took %3.2f seconds between round %d and %d" , time .Seconds (), lastRound , nextRound )
355
+ }
356
+ }
357
+ return nil
358
+ }
359
+
292
360
// HealthCheck does a health check on the potentially running node,
293
361
// returning an error if the API is down
294
362
func (client RestClient ) HealthCheck () error {
@@ -301,14 +369,6 @@ func (client RestClient) ReadyCheck() error {
301
369
return client .get (nil , "/ready" , nil )
302
370
}
303
371
304
- // StatusAfterBlock waits for a block to occur then returns the StatusResponse after that block
305
- // blocks on the node end
306
- // Not supported
307
- func (client RestClient ) StatusAfterBlock (blockNum uint64 ) (response model.NodeStatusResponse , err error ) {
308
- err = client .get (& response , fmt .Sprintf ("/v2/status/wait-for-block-after/%d" , blockNum ), nil )
309
- return
310
- }
311
-
312
372
type pendingTransactionsParams struct {
313
373
Max uint64 `url:"max"`
314
374
Format string `url:"format"`
@@ -557,6 +617,16 @@ func (client RestClient) RawBlock(round uint64) (response []byte, err error) {
557
617
return
558
618
}
559
619
620
+ // EncodedBlockCert takes a round and returns its parsed block and certificate
621
+ func (client RestClient ) EncodedBlockCert (round uint64 ) (blockCert rpcs.EncodedBlockCert , err error ) {
622
+ resp , err := client .RawBlock (round )
623
+ if err != nil {
624
+ return
625
+ }
626
+ err = protocol .Decode (resp , & blockCert )
627
+ return
628
+ }
629
+
560
630
// Shutdown requests the node to shut itself down
561
631
func (client RestClient ) Shutdown () (err error ) {
562
632
response := 1
0 commit comments