Skip to content

Commit 734c5c7

Browse files
committed
fix(core): allocate SSH port by real socket availability
1 parent d24de22 commit 734c5c7

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

packages/lib/src/usecases/ports-reserve.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,39 @@ const filterReserved = (
2929
return path.resolve(item.projectDir) !== resolvedExclude
3030
}
3131

32-
// CHANGE: collect reserved SSH ports from existing docker-git projects
33-
// WHY: keep ports stable per project even when containers are stopped
32+
// CHANGE: collect SSH ports currently occupied by existing docker-git projects
33+
// WHY: avoid port collisions while allowing reuse of ports from stopped projects
3434
// QUOTE(ТЗ): "для каждого докера брать должен свой порт"
3535
// REF: user-request-2026-02-05-port-reserve
3636
// SOURCE: n/a
3737
// FORMAT THEOREM: ∀p∈Projects: reserved(port(p))
3838
// PURITY: SHELL
39-
// EFFECT: Effect<ReadonlyArray<ReservedPort>, PlatformError, FileSystem | Path>
39+
// EFFECT: Effect<ReadonlyArray<ReservedPort>, PlatformError | PortProbeError, FileSystem | Path.Path>
4040
// INVARIANT: excludes the current project dir when provided
4141
// COMPLEXITY: O(n) where n = number of projects
4242
export const loadReservedPorts = (
4343
excludeDir: string | null
44-
): Effect.Effect<ReadonlyArray<ReservedPort>, PlatformError, FileSystem | Path.Path> =>
44+
): Effect.Effect<
45+
ReadonlyArray<ReservedPort>,
46+
PlatformError | PortProbeError,
47+
FileSystem | Path.Path
48+
> =>
4549
Effect.gen(function*(_) {
4650
const path = yield* _(Path.Path)
4751
const items = yield* _(listProjectItems)
48-
return items
49-
.filter(filterReserved(path, excludeDir))
50-
.map((item) => ({ port: item.sshPort, projectDir: item.projectDir }))
52+
const reserved: Array<ReservedPort> = []
53+
const filter = filterReserved(path, excludeDir)
54+
55+
for (const item of items) {
56+
if (!filter(item)) {
57+
continue
58+
}
59+
if (!(yield* _(isPortAvailable(item.sshPort)))) {
60+
reserved.push({ port: item.sshPort, projectDir: item.projectDir })
61+
}
62+
}
63+
64+
return reserved
5165
})
5266

5367
const isReserved = (reserved: ReadonlySet<number>, port: number): boolean => reserved.has(port)

0 commit comments

Comments
 (0)