Skip to content

Add GPU server zone restriction and clarify spot price handling at UpCloud#101

Merged
bridgend84 merged 8 commits into
mainfrom
fix-upcloud-spot
Jul 7, 2026
Merged

Add GPU server zone restriction and clarify spot price handling at UpCloud#101
bridgend84 merged 8 commits into
mainfrom
fix-upcloud-spot

Conversation

@bridgend84

@bridgend84 bridgend84 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Overview

Add GPU server zone restriction and clarify spot price handling at UpCloud.

Required checks before merge

Mark all tasks that were completed with a checkmark. Unrelated tasks can be left unchecked.

PR status:

  • Branch is based on and up-to-date with main
  • PR has a clear title and/or brief description
  • PR builders passed
  • No red flags from coderabbit.ai
  • Pinged code owners for human review after all other major items in this list are completed
  • Human approval

Versioning, changelog, and documentation:

  • New features, bugfixes etc are tracked in CHANGELOG.md
  • Package version bumped in pyproject.toml
  • add_vendor.md is up-to-date (after schema changes or new learnings that generalizes well to future vendors)
  • mkdocs renders correctly in local preview and has been manually checked on new or updated functions/methods

Database:

  • Alembic migrations are provided for database schema changes
    • Tested on SQLite
    • Tested on PostgreSQL
  • sc-crawler pull was tested on all vendors and records
  • Data changes were manually cross-checked with the vendor homepages or other trusted sources
  • The output (e.g. SQLite file) of an example run is included in the PR to demonstrate major data changes

Summary by CodeRabbit

  • Bug Fixes
    • Improved GPU plan pricing accuracy by automatically excluding GPU plans in zones where GPU passthrough availability is zero.
    • Updated spot pricing so SPOT server plans now return proper spot price records (rather than being empty), applying the same GPU-availability filtering as standard pricing.
    • Normalized spot server identifiers to keep listings consistent and easier to interpret.

@bridgend84
bridgend84 requested a review from daroczig July 6, 2026 09:24
@bridgend84 bridgend84 self-assigned this Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@bridgend84, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 278f3bbe-8a54-4e58-9a16-eb3b61953c0e

📥 Commits

Reviewing files that changed from the base of the PR and between 51adc20 and be4fb78.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • src/sc_crawler/vendors/_upcloud.py
📝 Walkthrough

Walkthrough

UpCloud pricing inventory now caches per-zone GPU availability, uses it to filter regular GPU plans, and emits spot pricing records for SPOT* plans with the same GPU gating and normalized server IDs.

Changes

UpCloud pricing inventory

Layer / File(s) Summary
Cached GPU availability lookup
src/sc_crawler/vendors/_upcloud.py
Adds cached /device/availability lookups per zone and builds per-zone GPU availability data for later pricing filters.
Regular plan GPU filtering
src/sc_crawler/vendors/_upcloud.py
inventory_server_prices skips all SPOT plans and only includes GPU* plans when the cached zone availability reports a non-zero amount.
Spot plan inventory
src/sc_crawler/vendors/_upcloud.py
inventory_server_prices_spot now returns Allocation.SPOT records for SPOT* plans, applies the same GPU availability filter, and removes the SPOT- prefix from server_id.

Estimated code review effort: 4 (Complex) | ~40 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has the right template but leaves all required checklist items unchecked, so it lacks completion details. Check off completed items and add any missing PR status details, especially build/test, changelog, versioning, and review status.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title matches the main change: GPU zone restriction and spot price handling for UpCloud.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-upcloud-spot

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/sc_crawler/vendors/_upcloud.py Outdated
Comment thread src/sc_crawler/vendors/_upcloud.py Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/sc_crawler/vendors/_upcloud.py (2)

450-527: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

inventory_server_prices and inventory_server_prices_spot are near-identical; extract a shared builder.

The two functions differ only in the SPOT filter direction, the prefix strip, and the allocation value. This duplication is exactly what allowed the ordering bug above to appear in only one of them. Consider factoring the shared loop/price-record construction into a helper parametrized by allocation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/sc_crawler/vendors/_upcloud.py` around lines 450 - 527, The two inventory
functions duplicate almost the same price-record building logic, so extract the
shared loop into a helper and parameterize the small differences. Refactor
`inventory_server_prices` and `inventory_server_prices_spot` around a common
helper that handles iterating `prices["prices"]["zone"]`, GPU availability
checks, and appending the price payload, while passing in the allocation and the
SPOT/non-SPOT filter behavior plus the server plan normalization. Keep the
existing public function names as thin wrappers calling the shared builder so
the logic stays in one place.

41-49: 🩺 Stability & Availability | 🔵 Trivial | ⚖️ Poor tradeoff

cachier has no stale_after, so GPU availability is cached to disk indefinitely across runs.

separate_files=True persists results between crawler invocations. Since GPU/passthrough availability changes over time, a region that gains or loses GPU capacity will keep returning the first cached response, silently skewing which GPU plans get emitted. Consider setting a stale_after window aligned with your crawl cadence.

♻️ Suggested change
-@cachier(hash_func=jsoned_hash, separate_files=True)
+@cachier(hash_func=jsoned_hash, separate_files=True, stale_after=timedelta(hours=1))
 def _get_device_region_availability(region_id: str, device_type: str = "gpu") -> dict:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/sc_crawler/vendors/_upcloud.py` around lines 41 - 49, The
_get_device_region_availability cache is persisted by cachier with
separate_files=True, so GPU availability can stay stale across crawler runs.
Update this function to use a finite cache lifetime by adding an appropriate
stale_after window aligned with crawl frequency, so region availability is
refreshed regularly. Keep the change local to _get_device_region_availability
and preserve the existing jsoned_hash/separate_files behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/sc_crawler/vendors/_upcloud.py`:
- Around line 502-508: Move the SPOT- prefix stripping in the server plan
handling logic before the GPU availability check so spot GPU plans are evaluated
correctly. In the code path inside the UpCloud vendor logic, update the server
plan normalization around the SPOT/GPU checks so server_plan is cleaned first,
then use the normalized value for the startswith("GPU") test and the
gpu_region_availability lookup.

---

Nitpick comments:
In `@src/sc_crawler/vendors/_upcloud.py`:
- Around line 450-527: The two inventory functions duplicate almost the same
price-record building logic, so extract the shared loop into a helper and
parameterize the small differences. Refactor `inventory_server_prices` and
`inventory_server_prices_spot` around a common helper that handles iterating
`prices["prices"]["zone"]`, GPU availability checks, and appending the price
payload, while passing in the allocation and the SPOT/non-SPOT filter behavior
plus the server plan normalization. Keep the existing public function names as
thin wrappers calling the shared builder so the logic stays in one place.
- Around line 41-49: The _get_device_region_availability cache is persisted by
cachier with separate_files=True, so GPU availability can stay stale across
crawler runs. Update this function to use a finite cache lifetime by adding an
appropriate stale_after window aligned with crawl frequency, so region
availability is refreshed regularly. Keep the change local to
_get_device_region_availability and preserve the existing
jsoned_hash/separate_files behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0ade9003-fe26-4bfa-843b-3032519a6ca7

📥 Commits

Reviewing files that changed from the base of the PR and between a51588d and 51adc20.

📒 Files selected for processing (1)
  • src/sc_crawler/vendors/_upcloud.py

Comment thread src/sc_crawler/vendors/_upcloud.py
Comment thread src/sc_crawler/vendors/_upcloud.py Outdated
Comment thread src/sc_crawler/vendors/_upcloud.py Outdated
@bridgend84 bridgend84 changed the title Add GPU server zone restriction and clarify spot price handling Add GPU server zone restriction and clarify spot price handling at UpCloud Jul 7, 2026
@bridgend84
bridgend84 merged commit 9ba8ac5 into main Jul 7, 2026
3 checks passed
@bridgend84
bridgend84 deleted the fix-upcloud-spot branch July 7, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants