Conversation
📝 WalkthroughWalkthroughNodeResource.Create now scans all InstanceIDs, ignoring ErrNotFound until finding a non-empty PrimaryInstanceID; FromState returns not-found when ResourceData.NeedsRecreate is true; InstanceResource.isFirstTimeSetup signature was simplified to return only a bool and its logic reduced to an identifier existence check. Changes
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
mmols
left a comment
There was a problem hiding this comment.
LGTM, I suggest following later with an E2E focused around this case
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@server/internal/database/node_resource.go`:
- Around line 68-75: The loop currently returns on any error from
resource.FromContext[*InstanceResource](rc, InstanceResourceIdentifier(id));
instead, check if err == resource.ErrNotFound and in that case skip this id and
continue scanning for other instances, only returning an error for
non-ErrNotFound failures; once a valid instance is returned, if
instance.PrimaryInstanceID != "" assign it to n.PrimaryInstanceID and break as
before. Ensure you reference the FromContext[*InstanceResource] call, the
InstanceResourceIdentifier(id) argument, the resource.ErrNotFound sentinel, and
the instance.PrimaryInstanceID check when making this change.
In `@server/internal/resource/state.go`:
- Around line 425-426: FromState must not map NeedsRecreate to ErrNotFound
because callers (e.g., update_database.go and plan_restore.go) rely on
ErrNotFound meaning “truly absent”; instead introduce and return a distinct
exported sentinel (e.g., ErrNeedsRecreate) from the resource package when
data.NeedsRecreate is true, update FromState to return that sentinel (not
ErrNotFound), and then adjust only the resource-lifecycle-only helpers or
callers that actually want to treat recreate as absent to check errors.Is(err,
resource.ErrNeedsRecreate) (or keep existing resource-only filtering) while
leaving callers that use errors.Is(..., resource.ErrNotFound) unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 07210c25-2804-43c5-9e2b-3a09d85bbf64
📒 Files selected for processing (2)
server/internal/database/node_resource.goserver/internal/resource/state.go
d1a1c05 to
1b1f8d7
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@server/internal/database/node_resource.go`:
- Around line 66-77: In node_resource.go inside the loop that iterates
n.InstanceIDs (the block calling resource.FromContext[*InstanceResource] with
InstanceResourceIdentifier), reset n.PrimaryInstanceID to empty string before
the loop begins, and after calling resource.FromContext add a continue when err
!= nil && errors.Is(err, resource.ErrNotFound) so the nil instance is skipped;
keep the existing return for other errors and only access
instance.PrimaryInstanceID when instance != nil to avoid nil dereference.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6d896f10-3bce-47e1-8708-f1c254c5ad5f
📒 Files selected for processing (2)
server/internal/database/node_resource.goserver/internal/resource/state.go
🚧 Files skipped from review as they are similar to previous changes (1)
- server/internal/resource/state.go
When a resource `Create` or `Refresh` fails, we still record the resource in state so that it can be cleaned up by a later delete operation. To distinguish this state, we set a special `NeedsRecreate` flag. However, we did not account for this in the helper functions that retrieve resources from the state. This made it possible for callers to get stale state for a resource that no longer exists. This commit fixes that issue by adding a check for the `NeedsRecreate` flag in the helper functions that all the resources use to inspect the state. I've also added a related fix in `NodeResource.Create` to handle cases where the first instance resource is in a bad state.
1b1f8d7 to
16cd1bb
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
server/internal/database/instance_resource.go (1)
400-403: Tighten the inline comment to match the actual semantics.This check now means “the resource has no prior state entry,” not strictly “it was never successfully created.” Updating the comment would make the retry behavior clearer. Based on learnings: In
server/internal/database/postgres_database.go,isFirstTimeSetup()intentionally uses resource presence in state rather thanNeedsRecreatebecause the post-restore flow is destructive and must not rerun on retry.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@server/internal/database/instance_resource.go` around lines 400 - 403, Update the inline comment above the check that calls rc.State.Get(r.Identifier()) and returns !ok to reflect that it checks for absence of a prior state entry (i.e., "no prior state entry exists") instead of claiming the resource was "never successfully created"; reference the exact symbols rc.State.Get and r.Identifier() in the comment and, if helpful, mirror the phrasing used by isFirstTimeSetup() in server/internal/database/postgres_database.go to make the retry/destructive-restore semantics clear.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@server/internal/database/instance_resource.go`:
- Around line 400-403: Update the inline comment above the check that calls
rc.State.Get(r.Identifier()) and returns !ok to reflect that it checks for
absence of a prior state entry (i.e., "no prior state entry exists") instead of
claiming the resource was "never successfully created"; reference the exact
symbols rc.State.Get and r.Identifier() in the comment and, if helpful, mirror
the phrasing used by isFirstTimeSetup() in
server/internal/database/postgres_database.go to make the
retry/destructive-restore semantics clear.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ebe0a971-1404-4c77-b291-92f53de036f1
📒 Files selected for processing (3)
server/internal/database/instance_resource.goserver/internal/database/node_resource.goserver/internal/resource/state.go
🚧 Files skipped from review as they are similar to previous changes (2)
- server/internal/resource/state.go
- server/internal/database/node_resource.go
Summary
When a resource
CreateorRefreshfails, we still record the resource in state so that it can be cleaned up by a later delete operation. To distinguish this state, we set a specialNeedsRecreateflag. However, we did not account for this in the helper functions that retrieve resources from the state. This made it possible for callers to get stale state for a resource that no longer exists.This commit fixes that issue by adding a check for the
NeedsRecreateflag in the helper functions that all the resources use to inspect the state.I've also added a related fix in
NodeResource.Createto handle cases where the first instance resource is in a bad state.Testing
The scenario that this PR fixes:
Prior to this fix, you would get an error like: