From 38bbdf4b0490414584d455247c2d539c32054b5c Mon Sep 17 00:00:00 2001 From: Malaber Date: Tue, 14 Apr 2026 21:10:53 +0200 Subject: [PATCH] Stream follower blackbox progress --- spec/e2e/http/tournament_follow_sync_spec.rb | 14 +++++ tasks.py | 55 +++++++++++++------- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/spec/e2e/http/tournament_follow_sync_spec.rb b/spec/e2e/http/tournament_follow_sync_spec.rb index 736b7c5..ed8e5d9 100644 --- a/spec/e2e/http/tournament_follow_sync_spec.rb +++ b/spec/e2e/http/tournament_follow_sync_spec.rb @@ -215,12 +215,19 @@ RSpec.describe 'Tournament follower sync HTTP E2E' do def wait_for_tournament_sync!(source_tournament_id:, follower_tournament_id:, timeout: 90) deadline = Time.now + timeout + last_progress_at = Time.now loop do source = fetch_tournament(client: source_anonymous_client, tournament_id: source_tournament_id) follower = fetch_tournament(client: follower_anonymous_client, tournament_id: follower_tournament_id) return follower if tournament_signature(source) == tournament_signature(follower) + if Time.now - last_progress_at >= 5 + puts "sync wait source=#{sync_progress_signature(source).inspect} follower=#{sync_progress_signature(follower).inspect}" + $stdout.flush + last_progress_at = Time.now + end + if Time.now >= deadline raise <<~ERROR Follower did not catch up within #{timeout}s @@ -233,6 +240,13 @@ RSpec.describe 'Tournament follower sync HTTP E2E' do end end + def sync_progress_signature(tournament) + { + name: tournament.fetch(:name), + stages: tournament.fetch(:stages).map { |stage| [stage.fetch(:level), stage.fetch(:state)] } + } + end + def synced_team_id_pairs(source:, follower:) source_by_name = source.fetch(:teams).each_with_object({}) do |team, teams_by_name| teams_by_name[team.fetch(:name)] = team diff --git a/tasks.py b/tasks.py index a6dfb9e..09a8459 100644 --- a/tasks.py +++ b/tasks.py @@ -139,6 +139,35 @@ def _run_subprocess(command, env=None, capture_output=False, check=True): return completed +def _run_subprocess_live(command, env=None, check=True): + process = subprocess.Popen( + command, + env=env, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=1, + ) + + output_chunks = [] + assert process.stdout is not None + for line in process.stdout: + output_chunks.append(line) + print(line, end="", flush=True) + + process.wait() + stdout = "".join(output_chunks) + completed = subprocess.CompletedProcess(command, process.returncode, stdout=stdout, stderr="") + if check and completed.returncode != 0: + raise subprocess.CalledProcessError( + completed.returncode, + command, + output=completed.stdout, + stderr=completed.stderr, + ) + return completed + + def _compose_env( host_port=SERVER_PORT, app_image=PRODUCTION_TAG, @@ -207,7 +236,7 @@ def _compose_run(compose_args, env, capture_output=False, check=True, project_na def _print_header(title): - print(f"\n== {title} ==") + print(f"\n== {title} ==", flush=True) def _bootstrap_user_command(email, password, username): @@ -336,12 +365,8 @@ def _run_blackbox_rspec(base_url, email, password, username, alt_email=E2E_ALT_E if extra_env: env.update(extra_env) command = ["bundle", "exec", "rspec", spec_path, "--format", "documentation"] - print(_format_command(command)) - result = _run_subprocess(command, env=env, capture_output=True, check=False) - if result.stdout: - print(result.stdout.rstrip()) - if result.stderr: - print(result.stderr.rstrip()) + print(_format_command(command), flush=True) + result = _run_subprocess_live(command, env=env, check=False) report = _parse_rspec_report(f"{result.stdout}\n{result.stderr}") _print_header("Blackbox report") @@ -940,19 +965,9 @@ def docker_blackbox_follow_test( "inv", "blackbox-follow-service", ] - print(_format_command(_docker_compose_cmd(project_name=BLACKBOX_FOLLOW_PROJECT, compose_file=BLACKBOX_FOLLOW_COMPOSE_FILE) + command)) - result = _compose_run( - command, - env=env, - capture_output=True, - check=False, - project_name=BLACKBOX_FOLLOW_PROJECT, - compose_file=BLACKBOX_FOLLOW_COMPOSE_FILE, - ) - if result.stdout: - print(result.stdout.rstrip()) - if result.stderr: - print(result.stderr.rstrip()) + full_command = _docker_compose_cmd(project_name=BLACKBOX_FOLLOW_PROJECT, compose_file=BLACKBOX_FOLLOW_COMPOSE_FILE) + command + print(_format_command(full_command), flush=True) + result = _run_subprocess_live(full_command, env=env, check=False) if result.returncode != 0: raise subprocess.CalledProcessError(