Repository: Chia-Network/chia-blockchain
File: tools/validate_rpcs.py (Python)

Code before:

        def add_tasks_for_height(height: int) -> None:
            block_header_hash = get_block_hash_from_height(height, height_to_hash_bytes)
            # Create tasks for each RPC call based on the flags
            if spends_with_conditions:
                in_flight.add(
                    create_referenced_task(
                        node_spends_with_conditions(node_client, block_header_hash, height, repeat_list)
                    )
                )
            if block_spends:
                in_flight.add(
                    create_referenced_task(node_block_spends(node_client, block_header_hash, height, repeat_list))
                )
            if additions_and_removals:
                in_flight.add(
                    create_referenced_task(node_additions_removals(node_client, block_header_hash, height, repeat_list))
                )

        for i in range(start_height, end_height + 1):
            add_tasks_for_height(height=i)
            # Make Status Updates.
            if len(in_flight) >= concurrent_requests:
                done, in_flight = await asyncio.wait(in_flight, return_when=asyncio.FIRST_COMPLETED)
                completed_requests += len(done)
                if completed_requests >= REQUESTS_PER_STATUS_UPDATE:
                    time_taken = time.time() - cycle_start
                    print(
                        f"Processed {completed_requests} RPCs in {time_taken:.2f}s, "
                        f"{time_taken / completed_requests:.4f}s per RPC "
                        f"({i - start_height} Blocks completed out of {end_height - start_height})"
                    )
                    completed_requests = 0
                    cycle_start = time.time()
                    # Retry any blocks that failed
                    if len(repeat_list) > 0:
                        print(f"Some blocks failed, retrying: {len(repeat_list)} blocks")
                        for height in repeat_list:
                            add_tasks_for_height(height)
                        repeat_list.clear()

        # Wait for any remaining tasks to complete
        print(f"Waiting for {len(in_flight)} remaining tasks to complete...")
        if in_flight:
            await asyncio.gather(*in_flight)

        if repeat_list:
            print(f"Some blocks failed after retrying: {len(repeat_list)} blocks")
            for height in repeat_list:
                print(f"Failed block at height: {height}")


Review comment (suggestion):
I think it would be simpler (and sufficient) to just print this every 5 seconds or so. i.e.
```suggestion
                now = time.monotonic()
                if cycle_start + 5 < now:
```

Code after:
                pipeline.add(create_referenced_task(node_block_spends(node_client, block_header_hash, height)))
            if additions_and_removals:
                pipeline.add(create_referenced_task(node_additions_removals(node_client, block_header_hash, height)))

        for i in range(start_height, end_height + 1):
            add_tasks_for_height(height=i)
            # Make Status Updates.
            if len(pipeline) >= pipeline_depth:
                done, pipeline = await asyncio.wait(pipeline, return_when=asyncio.FIRST_COMPLETED)
                completed_requests += len(done)
                now = time.monotonic()
                if cycle_start + 5 < now:
                    time_taken = now - cycle_start
                    print(
                        f"Processed {completed_requests} RPCs in {time_taken:.2f}s, "
                        f"{time_taken / completed_requests:.4f}s per RPC "
                        f"({i - start_height} Blocks completed out of {end_height - start_height})"
                    )
                    completed_requests = 0
                    cycle_start = now

        # Wait for any remaining tasks to complete
        print(f"Waiting for {len(pipeline)} remaining tasks to complete...")
        if pipeline:
            await asyncio.gather(*pipeline)

        print(f"Finished processing blocks from {start_height} to {end_height} (peak: {peak_height})")
        print(
            f"Time per block for the whole process: "
            f"{(time.monotonic() - start_time) / (end_height - start_height):.4f} seconds"
        )


if __name__ == "__main__":
    cli()