Skip to content

refactor: VM 할당 개선#72

Open
ga111o wants to merge 4 commits into
easy-cloud-Knet:stagingfrom
ga111o:refactor/core-vm-allocation-v2
Open

refactor: VM 할당 개선#72
ga111o wants to merge 4 commits into
easy-cloud-Knet:stagingfrom
ga111o:refactor/core-vm-allocation-v2

Conversation

@ga111o

@ga111o ga111o commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

  • 기존 first-fit -> 부하 분산
  • race condition 제거
  • 삭제 시 자원 회수

Motivation

기존 SelectCore는 그저 앞에서부터 조건을 만족하는 첫 코어를 고르는 문제가 있었음.
동시 생성 시 over subscription이 발생 가능했으며, 삭제 시 인메모리쪽 되돌리지 않았음.

Approach

부하분산 스케줄링

  • first-fit 대신 적합한 코어 전체를 스캔해 loadScore가 가장 작은 코어 선택.
  • 스코어링
    • 포화 페널티: 한 차원이라도 사용률이 100%에 근접하면 점수가 폭증하도록.
    • 메모리, 디스크, 시퓨 중 하나라도 포화된 코어는 선택되지 않음.
    • 자원 우선순위 가중치 mem 0.6 > disk 0.3 > cpu 0.1.
      • 우선은 하드코딩. 추후 data fetching 등으로 관리하도록 하는 것이 좋아보임.

init CPU 정보

  • 기존 cpu 9999 하드코딩 제거. 코어의 GetCoreMachineCpuInfo(vcpu_status)로
    CoreInfoIdx.Cpu(total)·FreeCPU(idle)를 실제 값으로 설정.
  • CPU 정보 조회 실패 시 해당 코어를 IsAlive = false 처리.

VM 삭제 시 인메모리 회수

  • ReleaseVM(core, uuid) 추가, Reserve+Attach+Register atomic하게 역연산.
    Free* 복구 + VMInfoIdx/VMLocation/AliveVM 정리를 한 lock 안에서 수행.

Type of Change

  • Bug fix
  • New feature
  • Refactoring
  • Docs / Config
  • CI/CD

Related Issue

Testing

  • Tested locally
  • No regression in existing functionality

Checklist

  • Reviewers assigned
  • Related issue linked

추후 개선 필요.

  • 아래 내용들 매우 치명적인 문제가 아니며, 현재 pr 범위가 아니기에 진행하지는 않았습니다.
    • 코어 삭제 성공 후 DB DeleteInstance 실패 시 DB에 레코드가 남아 서버 재부팅 시 다시 생겨버릴 수도 있음. 코어 삭제를 idempotent하게 만들거나 할 필요가 있음.
    • init은 코어 실측 available 기반, 런타임은 예약 기반.

Summary by CodeRabbit

  • New Features

    • Added vCPU allocation details to CPU status responses, including total, allocated, sleeping, and idle vCPU counts.
  • Bug Fixes

    • Improved VM provisioning and deletion handling to better prevent resource over-allocation and keep reported CPU/memory availability accurate.
    • Updated core initialization to use live CPU availability data when determining whether a core is healthy.

ga111o added 4 commits July 7, 2026 14:55
- Introduced loadScore function to calculate core load based on resource utilization.
- Added utilRatio and saturationPenalty functions for improved resource management.
- Updated SelectCore to select the core with the lowest load score that meets resource requirements.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a VcpuStatus field to CPU info responses, replaces the resource manager's first-fit core selection with a scored ReserveCore/AttachVMInfo/ReleaseVM model, and updates CreateVM/DeleteVM and core initialization to use these APIs with centralized cleanup and idle-based FreeCPU tracking.

Changes

vCPU status and resource manager rework

Layer / File(s) Summary
VcpuStatus data contract and API docs
client/model/vm.go, client/vm.go
Adds VcpuStatus struct (Total, Allocated, Sleeping, Idle) and an optional VcpuStatus field on CoreMachineCpuInfoResponse; updates doc comments for vcpu_status.total/vcpu_status.idle.
Scored ReserveCore, AttachVMInfo, ReleaseVM
structure/resource_manager.go
Replaces SelectCore/AllocateResources/DeallocateResources with a load-scored ReserveCore (locks and decrements Free* atomically), AttachVMInfo (registers VM metadata), and ReleaseVM (restores Free*, removes VM state).
CreateVM/DeleteVM wiring and cleanup chain
service/vm.go
CreateVM uses reserveCoreOrFail with a cleanupChain that rolls back on SSH key or CMS subnet failures, then AttachVMInfo instead of AllocateResources. DeleteVM calls ReleaseVM after core deletion and logs updated Free* values.
Core init CPU sizing from vcpu_status
startup/init.go
Fetches CPU info per core, marks core not alive on failure or missing vcpu_status, and sets CoreInfoIdx.Cpu/FreeCPU from VcpuStatus.Total/VcpuStatus.Idle.

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

Sequence Diagram(s)

sequenceDiagram
  participant Service as CreateVM/DeleteVM
  participant ResourceManager
  participant Core

  Service->>ResourceManager: reserveCoreOrFail (ReserveCore)
  ResourceManager->>Core: score cores, decrement Free*
  ResourceManager-->>Service: reserved core

  alt failure during setup
    Service->>ResourceManager: cleanup.run() triggers deallocation
  else success
    Service->>ResourceManager: AttachVMInfo(core, uuid, vm)
  end

  Service->>ResourceManager: ReleaseVM(core, uuid) on delete
  ResourceManager->>Core: restore Free*, clear VM metadata
  ResourceManager-->>Service: released
Loading

Possibly related PRs

  • easy-cloud-Knet/KWS_Control#58: Both PRs modify the core resource-management layer, introducing/relocating ResourceManager state and updating service code to use contextStruct.Resources alongside the new ReserveCore/AttachVMInfo/ReleaseVM APIs.

Suggested reviewers: kwonkwonn, wind5052

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: a refactor to improve VM allocation.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
structure/resource_manager.go (1)

36-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Solid scoring model — consider adding unit tests for the new helpers.

The weighting, saturation curve, and variance-balance terms are well thought out and internally consistent with their doc comments. Since this directly drives placement decisions, table-driven tests for utilRatio/saturationPenalty/loadScore (boundary cases: total==0, free==total, free==req) would guard against regressions when the weights are tuned later.

🤖 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 `@structure/resource_manager.go` around lines 36 - 95, Add table-driven unit
tests for the new scoring helpers in resource_manager.go, covering utilRatio,
saturationPenalty, and loadScore. Focus on boundary cases like total==0,
free==total, and free==req, plus a few representative weighting/variance
scenarios so future tuning of loadWeightMemory, loadWeightDisk, loadWeightCPU,
and loadBalanceGain won’t silently change placement behavior. Use the function
names utilRatio, saturationPenalty, and loadScore to locate the logic.
startup/init.go (1)

207-225: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated fetch/error-handling pattern across Memory, Disk, and CPU info.

The three info-fetch blocks (memory, disk, now CPU) repeat the same if err != nil { currentCore.IsAlive = false; return fmt.Errorf(...) } shape. Extracting a small helper (e.g., a generic wrapper taking a fetch func and a resource-name string) would reduce duplication and keep future resource additions consistent.

♻️ Example helper sketch
func fetchOrFail[T any](currentCore *structure.Core, resourceName, ip string, port uint16, fetch func() (T, error)) (T, error) {
	val, err := fetch()
	if err != nil {
		currentCore.IsAlive = false
	}
	return val, err
}
🤖 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 `@startup/init.go` around lines 207 - 225, The Memory, Disk, and CPU fetch
blocks in initCoreInfo repeat the same error-handling pattern, so factor that
logic into a small helper around the coreClient calls. Add a reusable function
(for example, a fetchOrFail-style helper near startup/init.go) that takes
currentCore, a resource name, and a fetch callback, sets currentCore.IsAlive to
false on failure, and returns the wrapped error message; then use it for
GetCoreMachineMemoryInfo, GetCoreMachineDiskInfo, and GetCoreMachineCpuInfo to
keep the behavior identical while removing duplication.
🤖 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 `@service/vm.go`:
- Around line 35-39: The rollback registered in the cleanup chain is only
releasing scheduler resources, but after core VM creation it can leave an
existing VM and Redis state behind if a later DB step fails. Update the failure
handling around core VM creation and the cleanup path in vm.go so that post-core
rollback first deletes the VM from the core and clears Redis state before
calling Resources.DeallocateResources. If needed, split the pre-core reservation
rollback from the post-core compensating rollback to ensure Free* capacity is
only restored after the core-side delete succeeds.
- Around line 247-252: The cleanup flow in ReleaseVM is removing
VMLocation/AliveVM too early, before VMRepo.DeleteInstance can still fail
afterward. Update the VM deletion path in ReleaseVM and its caller so the
in-memory VM mapping is only cleared after the fatal DB cleanup succeeds, or
otherwise make the later DeleteInstance failure non-fatal by preserving enough
state for a retry/reconciliation path. Use the ReleaseVM and
VMRepo.DeleteInstance flow to keep FindCoreByVmUUID retryable and avoid leaving
stale DB state with no recovery path.
- Line 174: The debug log in the core selection path is using the wrong units
for the request values. Update the log message in the core selection flow that
uses `log.DebugInfo` so it reports `HardwareRequirement.Memory` and `Disk` in
MiB, not GiB, while keeping `CPU` unchanged. Make sure the message in the
selection logic reflects the actual units used by `req.Memory`, `req.CPU`, and
`req.Disk`.

In `@startup/init.go`:
- Around line 217-225: Handle GetCoreMachineCpuInfo failures locally inside the
per-core goroutine in InitializeCoreData instead of returning the error to
errgroup and aborting g.Wait(). In the block that sets currentCore.IsAlive and
calls coreClient.GetCoreMachineCpuInfo, keep marking the specific core as not
alive and then continue processing the other cores; only return from the
goroutine for truly fatal setup errors. Use the existing InitializeCoreData,
GetCoreMachineCpuInfo, and currentCore.IsAlive flow to keep the failure scoped
to that core.

---

Nitpick comments:
In `@startup/init.go`:
- Around line 207-225: The Memory, Disk, and CPU fetch blocks in initCoreInfo
repeat the same error-handling pattern, so factor that logic into a small helper
around the coreClient calls. Add a reusable function (for example, a
fetchOrFail-style helper near startup/init.go) that takes currentCore, a
resource name, and a fetch callback, sets currentCore.IsAlive to false on
failure, and returns the wrapped error message; then use it for
GetCoreMachineMemoryInfo, GetCoreMachineDiskInfo, and GetCoreMachineCpuInfo to
keep the behavior identical while removing duplication.

In `@structure/resource_manager.go`:
- Around line 36-95: Add table-driven unit tests for the new scoring helpers in
resource_manager.go, covering utilRatio, saturationPenalty, and loadScore. Focus
on boundary cases like total==0, free==total, and free==req, plus a few
representative weighting/variance scenarios so future tuning of
loadWeightMemory, loadWeightDisk, loadWeightCPU, and loadBalanceGain won’t
silently change placement behavior. Use the function names utilRatio,
saturationPenalty, and loadScore to locate the logic.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c3f3fba-8be2-4cac-b200-7eca6f6ecee5

📥 Commits

Reviewing files that changed from the base of the PR and between 5a96e73 and c2f311c.

📒 Files selected for processing (5)
  • client/model/vm.go
  • client/vm.go
  • service/vm.go
  • startup/init.go
  • structure/resource_manager.go

Comment thread service/vm.go
Comment on lines +35 to +39
// 예약 직후 롤백 등록. 이후 모든 실패 경로는 cleanup.run()으로 예약을 되돌려야 함
cleanup := &cleanupChain{}
cleanup.push(func() {
contextStruct.Resources.DeallocateResources(selectedCore, uuid, hwReq)
})

@coderabbitai coderabbitai Bot Jul 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Don’t use resource-only rollback after the core VM may already exist.

This cleanup later runs on failures after coreClient.CreateVM succeeds. DeallocateResources restores scheduler capacity, but it does not delete the VM from the core or remove Redis state, so a DB failure can leave a running VM while its resources are made allocatable again. Add a post-core compensating delete and only release Free* after that delete succeeds, or split pre-core and post-core rollback paths.

🤖 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 `@service/vm.go` around lines 35 - 39, The rollback registered in the cleanup
chain is only releasing scheduler resources, but after core VM creation it can
leave an existing VM and Redis state behind if a later DB step fails. Update the
failure handling around core VM creation and the cleanup path in vm.go so that
post-core rollback first deletes the VM from the core and clears Redis state
before calling Resources.DeallocateResources. If needed, split the pre-core
reservation rollback from the post-core compensating rollback to ensure Free*
capacity is only restored after the core-side delete succeeds.

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.

일리는 있는데, 지금 모델은 컨트롤 코어가 상태를 지속적으로 비교하는게 아니라 롤백 과정이 과하게 복잡해질 것 같네요.
지금은 코어 자체 로직이나 가비지 컬랙션을 믿거나 삭제 요청하는 로직을 롤백에 넣어야 될 거 같아요

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kwonkwonn 말씀하신 방향에 동의합니다. 매번 실제 코어 상태를 재조회해서 비교하는 방식은 지금 구조에 비해 과합니다.

절충안으로, 완전한 상태 동기화 대신 최소한의 보정 조치만 추가하는 방법도 고려해볼 수 있습니다: coreClient.CreateVM 성공 이후 실패 경로(Redis 저장 실패는 이미 무시하니 해당 없음, DB persist 실패 등)에서만 cleanup 체인에 coreClient.DeleteVM 호출을 추가하고, 그 뒤에 DeallocateResources를 실행하는 정도입니다. 이렇게 하면 코어에 남은 VM을 정리 요청은 보내되, 삭제 성공/실패 여부와 무관하게 자원 반환은 지금처럼 단순하게 유지할 수 있습니다. 삭제 요청이 실패하더라도 코어 측 GC나 운영자의 후속 정리에 맡기는 것은 그대로 유지하시면 될 것 같습니다.

이 정도로도 과하다고 판단되시면 지금 구조를 그대로 유지하시고, 원하시면 후속 개선 항목으로 이슈를 만들어드릴 수도 있습니다. 필요하시면 말씀해주세요.


✏️ Learnings added
Learnt from: kwonkwonn
Repo: easy-cloud-Knet/KWS_Control PR: 72
File: service/vm.go:35-39
Timestamp: 2026-07-09T12:44:59.233Z
Learning: In `service/vm.go`'s `CreateVM` function (repository easy-cloud-Knet/KWS_Control), the maintainer (kwonkwonn) intentionally keeps rollback logic simple: the control core does not continuously reconcile VM state against cores, so post-core-creation failure rollback should rely on core-side logic/garbage collection or a simple delete-request call, rather than a full compensating delete + Redis state cleanup + resource release ordering. Avoid suggesting complex multi-step reconciliation-based rollback for this codebase's resource manager / cleanup chain pattern.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread service/vm.go
func reserveCoreOrFail(contextStruct *vms.ControlContext, req vms.HardwareRequirement) (*vms.Core, int, error) {
log := util.GetLogger()

log.DebugInfo("core selection process. req: memory=%d GiB, cpu=%d, disk=%d", req.Memory, req.CPU, req.Disk)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the diagnostic units.

HardwareRequirement.Memory and Disk are MiB, but this log prints GiB, which makes capacity failures look 1024x different from the actual request.

Suggested fix
-	log.DebugInfo("core selection process. req: memory=%d GiB, cpu=%d, disk=%d", req.Memory, req.CPU, req.Disk)
+	log.DebugInfo("core selection process. req: memory=%d MiB, cpu=%d, disk=%d MiB", req.Memory, req.CPU, req.Disk)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
log.DebugInfo("core selection process. req: memory=%d GiB, cpu=%d, disk=%d", req.Memory, req.CPU, req.Disk)
log.DebugInfo("core selection process. req: memory=%d MiB, cpu=%d, disk=%d MiB", req.Memory, req.CPU, req.Disk)
🤖 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 `@service/vm.go` at line 174, The debug log in the core selection path is using
the wrong units for the request values. Update the log message in the core
selection flow that uses `log.DebugInfo` so it reports
`HardwareRequirement.Memory` and `Disk` in MiB, not GiB, while keeping `CPU`
unchanged. Make sure the message in the selection logic reflects the actual
units used by `req.Memory`, `req.CPU`, and `req.Disk`.

Comment thread service/vm.go
Comment on lines +247 to +252
// Core 삭제 성공 -> 인메모리 자원 회수 (Free* 복구 + VMInfoIdx/VMLocation/AliveVM 정리)
if contextStruct.Resources.ReleaseVM(core, uuid) {
log.DebugInfo("released in-memory resources for VM %s on core %s: FreeMemory=%d, FreeCPU=%d, FreeDisk=%d",
uuid, core.IP, core.FreeMemory, core.FreeCPU, core.FreeDisk)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Don’t remove the in-memory VM location before later fatal cleanup can fail.

ReleaseVM deletes VMLocation/AliveVM, but VMRepo.DeleteInstance can still return an error afterward. A retry then may fail at FindCoreByVmUUID, leaving stale DB state without a normal retry path. Keep enough in-memory deletion state until fatal cleanup succeeds, or make the later DB failure non-fatal with a reconciliation/retry path.

🤖 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 `@service/vm.go` around lines 247 - 252, The cleanup flow in ReleaseVM is
removing VMLocation/AliveVM too early, before VMRepo.DeleteInstance can still
fail afterward. Update the VM deletion path in ReleaseVM and its caller so the
in-memory VM mapping is only cleared after the fatal DB cleanup succeeds, or
otherwise make the later DeleteInstance failure non-fatal by preserving enough
state for a retry/reconciliation path. Use the ReleaseVM and
VMRepo.DeleteInstance flow to keep FindCoreByVmUUID retryable and avoid leaving
stale DB state with no recovery path.

Comment thread startup/init.go
Comment on lines +217 to +225
cpuResp, err := coreClient.GetCoreMachineCpuInfo(ctx)
if err != nil {
currentCore.IsAlive = false
return fmt.Errorf("failed to get CPU info for core %s:%d: %w", currentCore.IP, currentCore.Port, err)
}
if cpuResp == nil || cpuResp.VcpuStatus == nil {
currentCore.IsAlive = false
return fmt.Errorf("core %s:%d returned no vcpu_status in CPU info", currentCore.IP, currentCore.Port)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== startup/init.go around InitializeCoreData ==\n'
nl -ba startup/init.go | sed -n '140,280p'

printf '\n== client/model/vm.go around VcpuStatus ==\n'
nl -ba client/model/vm.go | sed -n '70,120p'

printf '\n== client/vm.go around GetCoreMachineCpuInfo ==\n'
nl -ba client/vm.go | sed -n '80,140p'

printf '\n== search for errgroup usage in startup/init.go ==\n'
rg -n "errgroup|Wait\(\)|Go\(" startup/init.go

Repository: easy-cloud-Knet/KWS_Control

Length of output: 254


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== startup/init.go around InitializeCoreData ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path("startup/init.go")
for i, line in enumerate(p.read_text().splitlines(), 1):
    if 140 <= i <= 280:
        print(f"{i:4d}\t{line}")
PY

printf '\n== client/model/vm.go around VcpuStatus ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path("client/model/vm.go")
for i, line in enumerate(p.read_text().splitlines(), 1):
    if 70 <= i <= 120:
        print(f"{i:4d}\t{line}")
PY

printf '\n== client/vm.go around GetCoreMachineCpuInfo ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path("client/vm.go")
for i, line in enumerate(p.read_text().splitlines(), 1):
    if 80 <= i <= 140:
        print(f"{i:4d}\t{line}")
PY

printf '\n== search for errgroup usage in startup/init.go ==\n'
python3 - <<'PY'
from pathlib import Path
for i, line in enumerate(Path("startup/init.go").read_text().splitlines(), 1):
    if "errgroup" in line or "Wait()" in line or ".Go(" in line:
        print(f"{i:4d}\t{line}")
PY

Repository: easy-cloud-Knet/KWS_Control

Length of output: 9872


Single core CPU lookup still aborts startup for all cores. GetCoreMachineCpuInfo errors are returned from the errgroup goroutine, so g.Wait() fails InitializeCoreData instead of just marking that core IsAlive = false. If this is meant to be a per-core health update, keep the failure local and continue.

🤖 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 `@startup/init.go` around lines 217 - 225, Handle GetCoreMachineCpuInfo
failures locally inside the per-core goroutine in InitializeCoreData instead of
returning the error to errgroup and aborting g.Wait(). In the block that sets
currentCore.IsAlive and calls coreClient.GetCoreMachineCpuInfo, keep marking the
specific core as not alive and then continue processing the other cores; only
return from the goroutine for truly fatal setup errors. Use the existing
InitializeCoreData, GetCoreMachineCpuInfo, and currentCore.IsAlive flow to keep
the failure scoped to that core.

@kwonkwonn kwonkwonn 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.

눈에 띄는 에러가 안보이기도 했고, 기존 방식보다는 훨씬 나아 보입니다.
테스트 후 큰 문제가 없으면 머지해도 될 거 같아요

Comment thread service/vm.go
Comment on lines +35 to +39
// 예약 직후 롤백 등록. 이후 모든 실패 경로는 cleanup.run()으로 예약을 되돌려야 함
cleanup := &cleanupChain{}
cleanup.push(func() {
contextStruct.Resources.DeallocateResources(selectedCore, uuid, hwReq)
})

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.

일리는 있는데, 지금 모델은 컨트롤 코어가 상태를 지속적으로 비교하는게 아니라 롤백 과정이 과하게 복잡해질 것 같네요.
지금은 코어 자체 로직이나 가비지 컬랙션을 믿거나 삭제 요청하는 로직을 롤백에 넣어야 될 거 같아요

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