Skip to content

feat: graceful drain and multi-package refactoring#14

Merged
mlorentedev merged 2 commits into
masterfrom
feature/arch-refactor-and-graceful-drain
Mar 8, 2026
Merged

feat: graceful drain and multi-package refactoring#14
mlorentedev merged 2 commits into
masterfrom
feature/arch-refactor-and-graceful-drain

Conversation

@mlorentedev
Copy link
Copy Markdown
Owner

Summary

This PR modernizes the architecture of ts-bridge by splitting the codebase into focused internal packages and adding a graceful shutdown mechanism for active connections.

Changes

1. Reliability (REL-001)

  • Added TS_DRAIN_TIMEOUT (default: 15s) to allow active RDP/SSH connections to finish before the bridge closes.
  • Implemented sync.WaitGroup in acceptLoop to track active connections during shutdown.

2. Architecture Refactor (ARCH-002)

  • Split main.go into:
    • internal/config: Environment parsing and auto-instance logic.
    • internal/proxy: Core TCP proxying, Dialer interface, and bidirectional copy loop.
    • internal/telemetry: Atomic counters and metrics snapshotting (decoupled from health).
    • internal/health: HTTP server for liveness, readiness, and metrics.
  • Simplified main.go to act as a thin orchestrator.

3. Testability (ARCH-003)

  • Moved unit tests into their respective packages.
  • Enhanced internal/proxy tests with a mock Dialer to verify proxy logic without a Tailscale network.
  • Updated main_integration_test.go to work with the new package structure.

4. Documentation (BP-001)

  • Restructured README.md to use a problem-first approach with quantified value comparison.
  • Added TS_DRAIN_TIMEOUT to configuration references in README and Starlight docs.

Testing

  • go test ./... — All tests passing (including new unit tests for packages).
  • go build ./... — Clean build.
  • Manual verification of package structure and imports.

Fixes Stream B (REL-001) and Stream E (ARCH-002, ARCH-003) from the roadmap.

## Summary

- Add graceful drain of active connections on shutdown (TS_DRAIN_TIMEOUT)
- Refactor main.go into multi-package architecture (internal/config, internal/proxy, internal/health, internal/telemetry)
- Add mock-based unit tests for proxy logic
- Update README to problem-first structure
- Add Astro output folders to .gitignore
## Changes

- Fix missing net/http import in main.go
- Refactor IsExpectedCloseError to use a loop/switch for lower complexity
- Refactor LoadConfig using helper functions to reduce complexity
- Ensure all tests pass after structural changes
@mlorentedev mlorentedev merged commit 14355b7 into master Mar 8, 2026
11 checks passed
@mlorentedev mlorentedev deleted the feature/arch-refactor-and-graceful-drain branch March 8, 2026 03:52
mlorentedev added a commit that referenced this pull request Mar 8, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.5.0](v1.4.0...v1.5.0)
(2026-03-08)


### Features

* graceful drain and multi-package refactoring
([#14](#14))
([14355b7](14355b7))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Manu Lorente <mlorentedev@gmail.com>
mlorentedev added a commit that referenced this pull request May 18, 2026
Two related DX papercuts surfaced by the 2026-05-18 multi-dim audit:

1. CLAUDE.md "Tech Stack" claimed `main.go ~785 lines` and "single-file"
   architecture. After ARCH-002 (PR #14), main.go is ~270 lines of
   orchestration plus four `internal/` packages (config, proxy, health,
   telemetry). The "Key Paths" table listed only main_test.go and
   main_integration_test.go, missing every internal/ package and the
   specs/ + scripts/tests/ trees added since.

   New contributors landing on the wrong file wastes onboarding time;
   tooling (claude-mem, vault refs, ADRs in the doc itself) was the
   only source of truth. Stale memory is worse than no memory.

2. .github/workflows/ci.yml pinned golangci-lint to `version: latest`,
   so contributors running `make lint` locally with whatever they
   installed could see green while CI sees red (or vice versa). Pinned
   to v1.62.2 in CI and documented the same install command in
   CLAUDE.md's Commands block so the two stay in lockstep.

CLAUDE.md also gains explicit references to ADR-006 (Dialer) and
ADR-007 (multi-package split) in the Architecture Decisions section,
making the layout discoverable from the project memory file.

Audit reference: 40-runbooks/audit-2026-05-18-multi-dim.md
(Major DX-1 and DX-2 entries).
mlorentedev added a commit that referenced this pull request May 18, 2026
## Summary

Two DX papercuts from the [2026-05-18 multi-dim
audit](https://github.com/mlorentedev/ts-bridge/blob/master/specs/)
(Major DX-1 and DX-2).

### Fix 1 — Stale CLAUDE.md

\`CLAUDE.md\` claimed:
- \"Architecture: Single-binary, single-file (\`main.go\` ~785 lines)\"
→ wrong since PR #14 (ARCH-002) split into \`main.go\` (~270 lines
orchestration) + four \`internal/\` packages.
- Key Paths table listed only \`main_test.go\` and
\`main_integration_test.go\` — missing every \`internal/*\` package,
\`specs/\`, \`scripts/tests/\`.

Refreshed:
- Updated Tech Stack to "Single binary, multi-package".
- Key Paths now lists each \`internal/\` package + their roles,
\`specs/\` SDD trees, \`scripts/tests/\` BATS suite, updated CI section.
- Architecture Decisions block adds ADR-006 (Dialer) and ADR-007
(multi-package split) — making the current layout discoverable from the
project memory file alone.

### Fix 2 — Pin golangci-lint

\`.github/workflows/ci.yml\` had \`version: latest\`. Contributors
running \`make lint\` locally with an older version see green while CI
sees red (or the reverse), wasting investigation time.

Pinned to \`v1.62.2\` in CI and documented the same \`go install
...@v1.62.2\` in CLAUDE.md's Commands block. Bump deliberately on
upgrade.

## Diff

2 files changed, +22 / -11.

## Test plan

- [x] CLAUDE.md text reflects actual file structure as of v1.7.0
(verified \`wc -l\` on every cited file)
- [x] CI's existing lint job continues to pass with v1.62.2 (the version
was already passing prior commits at \`latest\` resolving to this range)
- [ ] CI green on this PR
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