Skip to content

fix(fleet): drop redundant instance.start() in runCreateContainer#132

Merged
TSavo merged 1 commit intomainfrom
fix/instance-service-drop-redundant-start
Apr 18, 2026
Merged

fix(fleet): drop redundant instance.start() in runCreateContainer#132
TSavo merged 1 commit intomainfrom
fix/instance-service-drop-redundant-start

Conversation

@TSavo
Copy link
Copy Markdown
Contributor

@TSavo TSavo commented Apr 18, 2026

Summary

The last gap for engine→core fleet provision.

Traced via prod logs (battleaxe → core VPS):

```
holyship: [fleet] calling core.fleet.createContainer
core: QueueWorker: handler failed
error: "Instance 6baaf660-...: Docker not available — use command bus"
workerId: core-e3f022ec-...
```

Sequence:

  1. holyship's core-client calls `fleet.createContainer.mutate(...)`
  2. core enqueues `instance.create_container` (target: "core")
  3. core's queue worker picks it up, runs `InstanceService.runCreateContainer`
  4. `Fleet.create()` enqueues `bot.start` (target: null) → node-agent claims it → `dockerManager.startBot()` creates AND starts the container in one step → returns containerId/nodeId
  5. Core constructs an `Instance` value object from the result with no `docker` handle (by design — core is orchestrator, not a docker node)
  6. `instance-service.ts:399` calls `await instance.start()` → `getDocker()` → throws "Docker not available — use command bus"

Step 6 is redundant. The container is already running from step 4. The stray `instance.start()` was left behind and breaks every bare-container creation path.

Fix

Delete the line. Add a comment explaining why the start is already handled.

Test plan

  • `pnpm --filter @wopr-network/platform-core build` — clean
  • Merge, deploy, ship a fresh issue on wopr-network/.github
  • Engine→core fleet.createContainer returns a proper `CreatedBareContainer` (id, url, containerId, gatewayKey)
  • holyshipper container spawns via node-agent, opens a PR on the target repo. E2E green.

🤖 Generated with Claude Code

Summary by Sourcery

Bug Fixes:

  • Fix bare-container creation by dropping a redundant instance.start() call that failed when invoked from core without a Docker handle.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed container creation failures in fleet.createContainer workflows. Containers now successfully create and start without errors.

Fleet.create() enqueues \`bot.start\` which dockerManager.startBot()
handles in a single create-AND-start step on the node-agent. The
followup \`await instance.start()\` at line 399 always threw:

  Instance 6baaf660-...: Docker not available — use command bus

The Instance constructed at fleet.ts:97-105 from the queue result is
a value object for the core-side caller — no \`docker\` handle, no
\`instanceRepo\`, no \`eventEmitter\`. start()/stop()/etc. call
getDocker() and fail. That's intentional for everything EXCEPT this
one redundant start that slipped in.

Verified via prod logs (battleaxe → core):

  createContainer → queue dispatch → handler runs on core worker →
  fleet.create → bot.start op to node-agent succeeds → container up →
  instance.start() on core-side Instance → throw → op marked failed →
  holyship's tRPC surfaces the error.

Deleting the line closes the last gap for engine→core fleet provision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 18, 2026 00:43
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 18, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Removes a redundant container start call in InstanceService.runCreateContainer and documents the correct lifecycle, ensuring core no longer tries to start containers directly when Docker is only available on node-agents.

Sequence diagram for fleet.createContainer container lifecycle fix

sequenceDiagram
    participant Engine as Engine_holyship
    participant CoreClient as Core_client
    participant Core as Core_service
    participant Queue as Core_queue
    participant NodeAgent as Node_agent
    participant DockerMgr as DockerManager

    Engine->>CoreClient: call fleet.createContainer
    CoreClient->>Core: fleet.createContainer.mutate(params)
    Core->>Queue: enqueue instance.create_container (target: core)
    Queue->>Core: deliver instance.create_container job
    Core->>Core: InstanceService.runCreateContainer
    Core->>Core: Fleet.create(params)
    Core->>Queue: enqueue bot.start (target: null)
    Queue->>NodeAgent: deliver bot.start job
    NodeAgent->>DockerMgr: startBot(botId)
    DockerMgr->>DockerMgr: create_and_start_container
    DockerMgr-->>NodeAgent: containerId, nodeId
    NodeAgent-->>Core: bot.start result
    Core->>Core: construct Instance value (no docker field)
    Note over Core,Core: Previously: await instance.start() here (now removed)
    Core-->>CoreClient: CreatedBareContainer(id, url, containerId, gatewayKey)
    CoreClient-->>Engine: return result
Loading

File-Level Changes

Change Details Files
Stop invoking instance.start() during fleet bare-container creation because the container is already started by the node-agent, and document this behavior.
  • Removed the direct call to instance.start() after Fleet.create() in the create-container path.
  • Added a detailed comment explaining that Fleet.create() enqueues bot.start, which node-agent handles via dockerManager.startBot() as a create-and-start operation.
  • Clarified in the comment that the Instance returned to core is a value object without a docker handle, so calling start() from core always throws and breaks engine→core fleet.createContainer calls.
core/platform-core/src/fleet/instance-service.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b8d49295-417a-424c-a476-c335bec1cad8

📥 Commits

Reviewing files that changed from the base of the PR and between 072cb67 and d7514e1.

📒 Files selected for processing (1)
  • core/platform-core/src/fleet/instance-service.ts

📝 Walkthrough

Walkthrough

The InstanceService.runCreateContainer method removes an explicit instance.start() call that was causing Docker access failures on the core-side. The start operation is now delegated to Fleet.create(), which enqueues the operation for the node-agent to execute via dockerManager.startBot().

Changes

Cohort / File(s) Summary
Instance Service Container Creation
core/platform-core/src/fleet/instance-service.ts
Removed explicit await instance.start() call from runCreateContainer. The method now relies on Fleet.create() to enqueue the start operation for the node-agent to execute, eliminating Docker access failures on the core-side.

Sequence Diagram(s)

sequenceDiagram
    participant Core as InstanceService<br/>(Core)
    participant Fleet as Fleet.create()
    participant NodeAgent as Node-Agent
    participant Docker as dockerManager

    Note over Core,Docker: OLD FLOW (Failed)
    Core->>Core: runCreateContainer()
    Core->>Core: instance.start()
    Core->>Docker: Access Docker
    Note over Docker: ❌ Docker not accessible<br/>on core-side
    Docker-->>Core: Error

    Note over Core,Docker: NEW FLOW (Correct)
    Core->>Fleet: runCreateContainer()
    Core->>Fleet: Fleet.create()
    Fleet->>Fleet: Enqueue bot.start
    Fleet-->>Core: ✓ Returns (async)
    NodeAgent->>NodeAgent: Process queued bot.start
    NodeAgent->>Docker: dockerManager.startBot()
    Docker->>Docker: Execute container start
    Docker-->>NodeAgent: ✓ Success
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hop, skip, and a queue away,
Docker calls now find their day,
No more waiting on the core so strained,
Node-agents handle what's ordained,
Start and create in harmony play! 🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main change: removing a redundant instance.start() call in runCreateContainer, which is the core fix addressing the Docker access failure in fleet provisioning.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/instance-service-drop-redundant-start

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 and usage tips.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The new comment block is quite long and implementation-specific; consider tightening it to a brief lifecycle invariant (e.g. InstanceService assumes Fleet.create() enqueues bot.start and returns an already-started container on core) and moving any deeper explanation into a code comment near the Instance construction or an internal design note.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new comment block is quite long and implementation-specific; consider tightening it to a brief lifecycle invariant (e.g. `InstanceService assumes Fleet.create() enqueues bot.start and returns an already-started container on core`) and moving any deeper explanation into a code comment near the `Instance` construction or an internal design note.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 18, 2026

Greptile Summary

Removes a stray instance.start() call in runCreateContainer that always threw "Docker not available — use command bus" in production. The fix is correct: Fleet.create() enqueues bot.start which calls dockerManager.startBot() on the winning node-agent in a single create-and-start step, so the returned Instance value object (which has no docker handle) never needs an explicit start() call.

Confidence Score: 5/5

Safe to merge — single-line deletion of a call that always threw in production, with no remaining P0/P1 issues.

The fix is minimal, correct, and well-documented. Fleet.create() already starts the container via the bot.start queue job, and the Instance value object constructed on the core side has no docker field (confirmed in instance.ts line 53), so instance.start() always threw. Removing the call and documenting the architectural invariant is the right fix. Build confirmed clean. No edge cases missed.

No files require special attention.

Important Files Changed

Filename Overview
core/platform-core/src/fleet/instance-service.ts Removes the redundant await instance.start() (line 398) that always threw on the core side; adds a detailed comment explaining that bot.start via the queue already handles create+start atomically on the node-agent.

Sequence Diagram

sequenceDiagram
    participant holyship as holyship (engine)
    participant core as core tRPC handler
    participant queue as DB Queue
    participant agent as node-agent
    participant docker as Docker

    holyship->>core: fleet.createContainer.mutate(...)
    core->>queue: enqueue instance.create_container (target: "core")
    queue->>core: QueueWorker picks up → runCreateContainer()
    core->>queue: Fleet.create() → enqueue bot.start (target: null)
    queue->>agent: agent claims bot.start job
    agent->>docker: dockerManager.startBot() — create + start in one step
    docker-->>agent: containerId, url
    agent-->>queue: result {nodeId, containerId, url}
    queue-->>core: BotStartResult
    core->>core: construct Instance value object (no docker handle)
    Note over core: ✅ AFTER FIX: skip instance.start()<br/>❌ BEFORE FIX: instance.start() → getDocker() → throws
    core-->>holyship: CreatedBareContainer {id, url, containerId, gatewayKey}
Loading

Reviews (1): Last reviewed commit: "fix(fleet): drop redundant instance.star..." | Re-trigger Greptile

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Removes a core-side instance.start() call from the bare-container creation path to avoid invoking Docker operations from the orchestrator (core), where Instance is intentionally constructed without a Docker handle and container start is already performed by the node-agent via the bot.start operation.

Changes:

  • Drop redundant await instance.start() in InstanceService.runCreateContainer().
  • Add an explanatory comment documenting that Fleet.create() enqueues bot.start and the node-agent performs a single create-and-start step.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@TSavo TSavo merged commit d15a962 into main Apr 18, 2026
13 checks passed
@TSavo TSavo deleted the fix/instance-service-drop-redundant-start branch April 18, 2026 00:48
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