Skip to content

Refactor: decouple solver from API services #2

@chris-ricketts

Description

@chris-ricketts

Problem Statement

bancod currently mixes generic solver runtime ownership into plugin-specific application services.

Banco/Taker service owns and starts the solver runtime, even though Banco is one solver plugin. Preimage service also builds and starts its own solver runtime. This makes dependency direction backwards:

feature service -> solver runtime -> plugin

Maintainers need the generic solver runtime to be owned by the composition layer, while feature services stay focused on their own APIs and state.

Solution

Move solver lifecycle ownership out of Banco and Preimage services.

The composition root should:

  • build enabled plugins
  • build feature services
  • build the arkd tx source
  • build one solver with all enabled plugins
  • start and stop the solver runtime for the daemon process

Feature services should stay focused:

  • Taker service handles pairs, trades, balance, and address APIs.
  • Preimage service exposes solver pubkey and introspector pubkey metadata.
  • Banco plugin handles swap offer match, validation, and fulfillment.
  • Preimage plugin handles preimage claim match, validation, and submission.

Target dependency direction:

composition root -> solver runtime -> plugins
composition root -> feature services

User Stories

  1. As maintainer, I want solver runtime ownership outside Banco service, so that plugin orchestration is not hidden inside swap code.

  2. As maintainer, I want one generic runtime for enabled plugins, so that Banco and Preimage use the same lifecycle model.

  3. As maintainer, I want the composition root to register enabled plugins, so that feature services do not own daemon orchestration.

  4. As maintainer, I want Banco/Taker service to stop depending on solver runtime, so that pair, trade, balance, and address APIs stay focused on Banco application behavior.

  5. As maintainer, I want Preimage service to stop owning solver runtime, so that preimage metadata APIs stay separate from tx-stream execution.

  6. As maintainer, I want arkd tx source construction outside feature services, so that tx-stream infrastructure remains orchestration concern.

  7. As maintainer, I want one solver runtime to receive all enabled plugins, so that plugin count does not change lifecycle shape.

  8. As maintainer, I want existing plugin behavior preserved, so that Banco fulfillment and Preimage claims do not change.

  9. As maintainer, I want existing config toggles preserved, so that current deployments keep working.

  10. As maintainer, I want existing gRPC/HTTP APIs preserved, so that clients do not observe this refactor.

  11. As maintainer, I want docs to describe one runtime with many plugins, so that implementation and architecture docs match.

  12. As maintainer, I want graceful shutdown behavior preserved, so that in-flight solves still drain before process exit.

  13. As maintainer, I want panic recovery behavior preserved, so that one plugin panic still cannot crash the daemon.

  14. As maintainer, I want solver lifecycle code to remain small and local until it proves it needs extraction, so that the refactor does not introduce unnecessary abstraction.

  15. As test author, I want service tests to avoid constructing solver runtime when testing feature APIs, so that tests stay focused.

  16. As test author, I want existing e2e behavior tests to cover the refactor, so that Banco and Preimage still work through the daemon.

Implementation Decisions

  • The composition root owns daemon assembly and solver lifecycle.

  • Do not introduce a separate runtime module unless the implementation grows enough to justify extraction.

  • Banco/Taker service no longer stores, starts, stops, or reports solver runtime state.

  • Preimage service no longer builds, starts, stops, or reports solver runtime state.

  • Preimage service becomes an API-facing metadata holder.

  • Preimage external setup and plugin construction happen in the composition root.

  • One solver runtime runs all enabled plugins.

  • Existing config, API, protocol, and DB contracts stay unchanged.

  • Status endpoint stays for dashboard compatibility.

  • This refactor does not add per-plugin health or supervision.

  • For now, plugin status remains a compatibility signal for whether that plugin is enabled and exposed by the daemon; richer runtime status can be designed later if needed.

  • Unexpected solver runtime exit should cause the daemon process to exit, allowing an OS-level process supervisor to restart it.

  • Documentation should stop saying each enabled plugin owns its own solver/subscription.

Testing Decisions

Good tests verify external behavior, not implementation plumbing.

Existing coverage remains primary:

  • Existing solver tests cover runtime guarantees: plugin subscriptions, cancel, drain, panic recovery, and solve dispatch.

  • Existing Banco tests cover swap plugin behavior.

  • Existing Preimage tests cover preimage claim behavior.

  • Existing e2e tests cover daemon behavior for Banco and Preimage.

Required test changes:

  • Update service/handler test setup so Taker service no longer needs solver/plugin construction.

  • Remove status passthrough test if it only verifies trivial plumbing.

  • Update e2e daemon wiring to start one shared solver runtime instead of service-owned runtimes.

  • Keep existing e2e cases as regression coverage.

No new tests needed for:

  • pure Preimage constructor behavior

  • status passthrough behavior

  • double start behavior

  • nil dependency behavior

  • per-plugin health

  • tiny lifecycle glue in the composition root

Out of Scope

  • Changing Banco swap protocol.

  • Changing Preimage claim protocol.

  • Changing solver.Plugin.

  • Adding per-plugin health.

  • Adding restart supervision.

  • Adding per-tx extension parse cache.

  • Adding lifecycle/outpoint dispatch.

  • Changing price feed behavior.

  • Changing SQLite schema.

  • Changing public gRPC/HTTP API.

  • Changing env vars or defaults.

  • Adding new plugin types.

  • Reworking builder.

  • Reworking txmatch.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions