Skip to content

Commit

Permalink
Fix: Fix indexer sync issue in cucumber tests (#533)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonpaulos committed Feb 27, 2024
1 parent 53d5fb2 commit af3db1b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 27 deletions.
14 changes: 8 additions & 6 deletions examples/indexer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import json
from algosdk import transaction
from algosdk.v2client import indexer
from utils import get_accounts, get_algod_client, get_indexer_client
from utils import (
get_accounts,
get_algod_client,
get_indexer_client,
indexer_wait_for_round,
)


# example: INDEXER_CREATE_CLIENT
Expand Down Expand Up @@ -41,11 +46,8 @@
algod_client, algod_client.send_transaction(ptxn.sign(acct.private_key)), 4
)

# sleep for a couple seconds to allow indexer to catch up
import time

time.sleep(2)

# allow indexer to catch up
indexer_wait_for_round(indexer_client, res["confirmed-round"], 30)

# example: INDEXER_LOOKUP_ASSET
# lookup a single asset
Expand Down
26 changes: 26 additions & 0 deletions examples/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import base64
import time
from dataclasses import dataclass
from typing import List

Expand Down Expand Up @@ -55,6 +56,31 @@ def get_sandbox_default_wallet() -> Wallet:
)


def indexer_wait_for_round(
client: indexer.IndexerClient, round: int, max_attempts: int
) -> None:
"""waits for the indexer to catch up to the given round"""
indexer_round = 0
attempts = 0

while True:
indexer_status = client.health()
indexer_round = indexer_status["round"]
if indexer_round >= round:
# Success
break

# Sleep for 1 second and try again
time.sleep(1)
attempts += 1

if attempts >= max_attempts:
# Failsafe to prevent infinite loop
raise RuntimeError(
f"Timeout waiting for indexer to catch up to round {round}. It is currently on {indexer_round}"
)


@dataclass
class SandboxAccount:
"""SandboxAccount is a simple dataclass to hold a sandbox account details"""
Expand Down
49 changes: 28 additions & 21 deletions tests/steps/application_v2_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,27 +116,32 @@ def s512_256_uint64(witness):
return int.from_bytes(encoding.checksum(witness)[:8], "big")


# Dev mode helper functions
def wait_for_transaction_processing_to_complete_in_dev_mode(
millisecond_num=500,
):
"""
wait_for_transaction_processing_to_complete_in_dev_mode is a Dev mode helper method that waits for a transaction to be processed and serves as a rough analog to `context.app_acl.status_after_block(last_round + 2)`.
* <p>
* Since Dev mode produces blocks on a per transaction basis, it's possible algod generates a block _before_ the corresponding SDK call to wait for a block.
* Without _any_ wait, it's possible the SDK looks for the transaction before algod completes processing. The analogous problem may also exist in indexer. So, the method performs a local sleep to simulate waiting for a block.
"""
time.sleep(millisecond_num / 1000)


# Dev mode helper step
@then(
"I sleep for {millisecond_num} milliseconds for indexer to digest things down."
"I wait for indexer to catch up to the round where my most recent transaction was confirmed."
)
def wait_for_indexer_in_dev_mode(context, millisecond_num):
wait_for_transaction_processing_to_complete_in_dev_mode(
int(millisecond_num)
)
def wait_for_indexer_to_catch_up(context):
max_attempts = 30

round_to_wait_for = context.last_tx_confirmed_round
indexer_round = 0
attempts = 0

while True:
indexer_status = context.app_icl.health()
indexer_round = indexer_status["round"]
if indexer_round >= round_to_wait_for:
# Success
break

# Sleep for 1 second and try again
time.sleep(1)
attempts += 1

if attempts >= max_attempts:
# Failsafe to prevent infinite loop
raise RuntimeError(
f"Timeout waiting for indexer to catch up to round {round_to_wait_for}. It is currently on {indexer_round}"
)


@step(
Expand Down Expand Up @@ -439,8 +444,10 @@ def remember_app_id(context):
# TODO: this needs to be modified to use v2 only
@step("I wait for the transaction to be confirmed.")
def wait_for_app_txn_confirm(context):
wait_for_transaction_processing_to_complete_in_dev_mode()
transaction.wait_for_confirmation(context.app_acl, context.app_txid, 1)
tx_info = transaction.wait_for_confirmation(
context.app_acl, context.app_txid, 1
)
context.last_tx_confirmed_round = tx_info["confirmed-round"]


@given("an application id {app_id}")
Expand Down

0 comments on commit af3db1b

Please sign in to comment.