Skip to content

feat: pressure non streaming mode - #806

Open
yanksyoon wants to merge 2 commits into
mainfrom
feat/pressure-request-mode
Open

feat: pressure non streaming mode#806
yanksyoon wants to merge 2 commits into
mainfrom
feat/pressure-request-mode

Conversation

@yanksyoon

Copy link
Copy Markdown
Member

What this PR does

Introduce non streaming mode for pressure

Why we need it

Flaky network infrastructure will always fail on pressure stream

Checklist

  • I followed the contributing guide
  • I added or updated the documentation (if applicable)
  • I updated docs/changelog.md with user-relevant changes
  • I used AI to assist with preparing this PR
  • I added or updated tests as needed (unit and integration)
  • If this is a Grafana dashboard: I added a screenshot of the dashboard
  • If this is Terraform:terraform fmt passes and tflint reports no errors
  • If the github-runner-manager application has been changed: The application version number is updated in github-runner-manager/pyproject.toml.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a non-streaming (polling) mode for fetching planner “pressure”, allowing deployments with unreliable streaming connectivity to still scale runner creation based on planner demand.

Changes:

  • Introduces new charm config planner-pressure-mode (stream default, request polling) and validates it in charm state.
  • Plumbs planner_pressure_mode into the generated manager ApplicationConfiguration and into PressureReconcilerConfig.
  • Implements PlannerClient.get_pressure() and updates PressureReconciler create loop to support request-mode polling; updates unit tests and changelog accordingly.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
tests/unit/test_factories.pyAsserts planner_pressure_mode is included in generated application config.
tests/unit/test_charm_state.pyAdds validation test for invalid mode; asserts valid mode is stored in CharmConfig.
tests/unit/factories.pySets default planner-pressure-mode in mock charm config.
tests/unit/conftest.pyUpdates charm state fixture to include planner_pressure_mode.
src/factories.pyPlumbs state.charm_config.planner_pressure_mode into ApplicationConfiguration.
src/charm_state.pyAdds planner-pressure-mode config name, type, default, and validation/parsing.
github-runner-manager/tests/unit/manager/test_pressure_reconciler.pyUpdates fake planner for request-mode support and adds request-mode create loop test.
github-runner-manager/src/github_runner_manager/planner_client.pyAdds get_pressure() one-shot pressure fetch method.
github-runner-manager/src/github_runner_manager/manager/pressure_reconciler.pyAdds planner_pressure_mode to config and implements request-mode polling path in create loop.
github-runner-manager/src/github_runner_manager/configuration/base.pyExtends ApplicationConfiguration with planner_pressure_mode.
docs/changelog.mdDocuments the new config option and reconciler behavior change.
charmcraft.yamlAdds planner-pressure-mode charm config option with default and description.

Comment on lines +89 to +92
data = response.json()
if not isinstance(data, dict) or name not in data:
raise PlannerApiError(f"Unexpected pressure response payload: {data}")

Comment on lines +66 to +80
def get_pressure(self, name: str) -> PressureInfo:
"""Get pressure for the given flavor with a single request.

Args:
name: Flavor name.

Returns:
Parsed pressure info.

Raises:
PlannerConnectionError: On transient connection failures or timeouts.
PlannerApiError: On HTTP errors or invalid payloads.
"""
base = str(self._config.base_url).rstrip("/") + "/"
url = urljoin(base, f"api/v1/flavors/{name}/pressure")
Comment on lines 159 to +162
return
self._handle_create_runners(update.pressure)
self._stop.wait(5)
else:

@yhaliawyhaliaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with minor changes needed


🤝 Human review with AI assistance.

response = self._session.get(
url,
headers={"Authorization": f"Bearer {self._config.token}"},
timeout=self._config.timeout,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_pressure() uses self._config.timeout, whose default is 5 * 60 (300s, line 42) — a value chosen for long-lived streaming connections, not one-shot polls. build_pressure_reconciler constructs PlannerConfiguration without overriding it, so request mode inherits the streaming timeout unchanged.

A slow or hung planner can block the create loop for up to 300 seconds per poll attempt, compounded by the session's urllib3.Retry(total=3, backoff_factor=0.3) on 5xx responses. That makes the effective poll cadence wildly variable under exactly the flaky-network conditions this PR exists to handle, and delays the fallback-to-min_pressure behavior meant to keep runners flowing when the planner is unreachable.

Pass a short explicit timeout for the one-shot request path (a few seconds, consistent with the 5-second poll interval) — either a separate request_timeout field on PlannerConfiguration or an explicit argument at the get_pressure call site.

🤖 AI-assisted

Comment on lines +34 to 35
PLANNER_PRESSURE_MODE_CONFIG_NAME,
PLANNER_INTEGRATION_NAME,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLANNER_PRESSURE_MODE_CONFIG_NAME is imported before PLANNER_INTEGRATION_NAME, breaking the alphabetical ordering isort enforces here (every other name in this block is correctly ordered).

The lint tox env runs isort --check-only --diff, so this will fail CI lint as-is.

Suggested change
PLANNER_PRESSURE_MODE_CONFIG_NAME,
PLANNER_INTEGRATION_NAME,
PLANNER_INTEGRATION_NAME,
PLANNER_PRESSURE_MODE_CONFIG_NAME,

🤖 AI-assisted

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@yanksyoon@yhaliaw