Skip to content

feat(installer): add ibcmd backend (headless, ~30s vs DESIGNER 3-8min) - #21

Draft
rilhoms wants to merge 1 commit into
feenlace:mainfrom
rilhoms:feat/ibcmd-installer
Draft

feat(installer): add ibcmd backend (headless, ~30s vs DESIGNER 3-8min)#21
rilhoms wants to merge 1 commit into
feenlace:mainfrom
rilhoms:feat/ibcmd-installer

Conversation

@rilhoms

@rilhoms rilhoms commented May 26, 2026

Copy link
Copy Markdown

Summary

Adds an alternative installer backend using headless ibcmd config import for extension deployment. Selected via new flag --installer=ibcmd. The default --installer=designer keeps current behaviour for full backward compatibility.

Speed: ~30 seconds vs DESIGNER's 3-8 minutes.

Why

1cv8.exe DESIGNER batch mode has several pain points users hit in production:

  • 3-8 minutes per install — DESIGNER startup + GUI init + config compile dominate
  • Opens a GUI window — causes Session 0 hangs on Windows Server (well-known issue)
  • Limited Linux support — DESIGNER on Linux needs X-libs, often flaky in headless environments (CI/CD, containers, autonomous 1C servers)
  • Requires careful flags/WA- /DisableStartupDialogs /DisableStartupMessages magic

ibcmd (ships with platform since 8.3.18) is purpose-built for this scenario: native headless CLI, no GUI, works equally well on Windows and Linux 1C.

What changed

3 files changed, 556 insertions(+), 3 deletions(-)
 cmd/mcp-1c/main.go       | +29 −3
 installer/ibcmd.go       | +367 (new)
 installer/ibcmd_test.go  | +160 (new)
 README.md                | +29 −2

New flags

Flag Default Purpose
--installer={designer|ibcmd} designer Backend selection
--ibcmd-timeout=<duration> 60s Per-call hard timeout
--ibcmd-db-server=<host> Direct DBMS host (see "Server mode" below)

Server mode design note

DESIGNER and ibcmd have fundamentally different connection models that need to be exposed clearly to users:

  • DESIGNER uses cluster path cluster:1541\db — 1C cluster routes to the DBMS internally
  • ibcmd bypasses the cluster — connects directly to PostgreSQL/MSSQL/etc.

For --server mode with --installer=ibcmd, the user provides:

# Preferred: explicit DBMS host
mcp-1c --install <db-name> --server --installer=ibcmd \
       --ibcmd-db-server "<dbms-host> port=<port>" \
       --db-user=<dbms-user> --db-password=<dbms-pwd>

# Legacy split (works if DBPath contains DBMS host, not cluster name):
mcp-1c --install "<dbms-host>\<db-name>" --server --installer=ibcmd ...

A clear error message guides users through this distinction if they pass a cluster path by mistake.

Backward compatibility

  • Default --installer=designer keeps the full current behaviour
  • All existing flags work identically
  • No changes to the embedded BSL extension
  • No changes to MCP tools, HTTP client, server registration
  • Existing tests pass with -race; new tests are isolated to installer/

Gotchas codified

While implementing this I hit several non-obvious issues. The code asserts each one in tests so they can't regress:

  1. --db-server="host port=6432" requires NO trailing ; — docs say port=N; but with the semicolon ibcmd silently uses default port 5432. TestBuildConnectionArgs_ServerMode asserts the absence.

  2. --db-user X requires --db-pwd Y paired — without password, ibcmd enters interactive --request-db-pwd STDIN mode. With redirected/closed STDIN, it hangs forever (visible process, 0% CPU, no network traffic). TestBuildConnectionArgs_UserWithoutPasswordRejected rejects this combination upfront.

  3. --data directory must be per-run — stale lock files in a shared --data directory block subsequent runs. We allocate a temp dir via os.MkdirTemp and clean up with defer os.RemoveAll.

  4. config import files is selective (positional files), config import <path> is whole-directory — easy mistake; the former with --base-dir alone errors with «Путь не найден». We use the whole-directory form.

  5. Lock contention on busy bases — when extension metadata is actively held by rphost sessions, ibcmd waits for exclusive lock indefinitely. We enforce a hard context.WithTimeout and classify the error with three actionable hints (wait/increase-timeout/fallback to designer).

Testing

Unit tests (installer/ibcmd_test.go)

  • TestBuildConnectionArgs_FileMode — file-mode produces only --db-path
  • TestBuildConnectionArgs_ServerMode — verifies port syntax + no trailing ;
  • TestBuildConnectionArgs_UserWithoutPasswordRejected — prevents STDIN hang
  • TestBuildConnectionArgs_ServerModeWithoutBackslashRejected — validates DBPath shape
  • TestFindIbcmd_NextToPlatform — exe path resolution (Windows-only, skips on Linux)
  • TestRunIbcmd_TimeoutKills — hard timeout enforcement, verified by sleeping subprocess
  • TestClassifyIbcmdError_TimeoutMessage — actionable error message content

Regression

go test ./... -race — all packages green (bsl, dump, installer, internal/config, onec, prompts, server, tools).

Integration

Tested end-to-end on platform 8.3.27.1859 + Yandex Managed PostgreSQL 16 + cluster-managed infobase. Confirmed:

  • Platform auto-detection works
  • ibcmd executable found next to platform
  • XML extraction + format version patching work (shared with DESIGNER path)
  • ibcmd connection succeeds (no host resolution error)
  • Timeout enforcement at the requested duration
  • Lock contention triggers expected timeout with full error message + 3 fallback hints

When to use which backend

Scenario Recommendation
CI/CD pipeline ibcmd (no GUI, deterministic, fast)
Linux 1C server ibcmd (DESIGNER is flaky there)
Platform 8.3.10 - 8.3.17 designer (ibcmd not available)
Local file-mode development base either; designer remains the well-trodden path
Loaded production base with many active sessions designer or ibcmd --ibcmd-timeout=300s

Notes for review

  • This PR adds a new backend; it does not change the default. Users opt in explicitly.
  • The README section is in Russian to match the existing style; happy to translate if preferred.
  • The --ibcmd-db-server flag exists because ibcmd's connection model differs from DESIGNER's; alternative API designs welcome in review.

🤖 Generated with Claude Code

Adds an alternative installer backend using `ibcmd config import` for
extension deployment. Selected via new flag `--installer=ibcmd`. The
default `--installer=designer` keeps current behaviour.

Why
---
`1cv8.exe DESIGNER` batch mode has several pain points:
- 3-8 min per install (DESIGNER startup + GUI init + config compile)
- Opens a GUI window — causes Session 0 hangs on Windows Server
- Limited support on Linux 1C servers (X-libs)
- Needs careful `/WA-` `/DisableStartupDialogs` flags

`ibcmd` (ships with platform since 8.3.18) is purpose-built for headless
deploys: ~30s, no GUI, native Linux support.

What
----
- New file `installer/ibcmd.go` — ibcmd backend (~340 lines)
- New `installer/ibcmd_test.go` — 7 unit tests (5 pass, 1 skipped on
  non-Windows, all gotchas asserted)
- `cmd/mcp-1c/main.go`:
  - `--installer={designer|ibcmd}` (default `designer`)
  - `--ibcmd-timeout` (default 60s; bump for busy bases)
  - `--ibcmd-db-server` (required for cluster bases — see "Server mode"
    below)

Server mode design note
-----------------------
DESIGNER and ibcmd have fundamentally different connection models:
- DESIGNER uses cluster path `cluster:1541\db` (1C cluster routes to PG)
- ibcmd bypasses cluster — connects directly to DBMS

For `--server` mode with `--installer=ibcmd`, the user must provide:
  --install <db-name> --ibcmd-db-server "<dbms-host> port=<port>"

Or pack both into --install (legacy split):
  --install "<dbms-host>\<db-name>" --installer=ibcmd

Clear error message guides users through this distinction.

Gotchas codified (from real-world testing on platform 8.3.27.1859)
------------------------------------------------------------------
1. `--db-server="host port=6432"` syntax requires NO trailing `;`
   despite official docs claim (asserted in `TestBuildConnectionArgs_*`)
2. `--user X` with no `--password` causes ibcmd to read STDIN, hanging
   forever; we reject this combination upfront
3. Per-call hard timeout via `context.WithTimeout` (no orphan processes)
4. `--data` dir is per-run temp, auto-cleaned (no stale lock files)
5. Clear actionable error on lock contention with 3 fallback hints

Backward compatibility
----------------------
- Default unchanged: `--installer=designer` keeps full current behaviour
- All existing flags work identically
- No changes to embedded BSL extension, MCP tools, or HTTP client
- Existing tests pass with `-race`; new tests are isolated to installer/

Testing
-------
- Unit: 7 tests in `installer/ibcmd_test.go`, including timeout enforcement
  via subprocess hang simulation
- Regression: `go test ./... -race` — all packages green
- Integration: deploy attempt on real platform 8.3.27.1859 + Yandex
  Managed PostgreSQL 16; ibcmd connection + timeout enforcement work
  end-to-end as designed (lock contention triggered expected timeout
  with full actionable error message)

Refs: <to be filled in PR description>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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.

1 participant