4runr-os 2.10.69 → 2.10.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,11 @@
1
+ export declare const FOURRUNR_DB_CONTAINERS: readonly ["4runr-postgres", "4runr-redis"];
1
2
  export declare function isDockerAvailable(): Promise<boolean>;
2
3
  export declare function isDockerRunning(): Promise<boolean>;
4
+ export declare function isContainerRunning(containerName: string): boolean;
3
5
  export declare function areContainersRunning(): Promise<boolean>;
6
+ export declare function startStoppedContainers(): Promise<void>;
4
7
  export declare function startDockerCompose(composeFilePath: string): Promise<void>;
8
+ export declare function ensure4RunrStackRunning(composeFilePath: string): Promise<void>;
5
9
  export declare function stopDockerCompose(composeFilePath: string): Promise<void>;
6
10
  export declare function stop4RunrContainers(): Promise<void>;
7
11
  export declare function waitForHealthy(containerName: string, timeoutMs?: number): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"docker-manager.d.ts","sourceRoot":"","sources":["../../../../../src/db/docker-manager.ts"],"names":[],"mappings":"AAMA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAW1D;AAKD,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAWxD;AAKD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAW7D;AAMD,wBAAsB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/E;AAMD,wBAAsB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9E;AAKD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBzD;AAOD,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCpG;AAMD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAchE;AAOD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,MAAM,CAUlF;AAYD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CA0B7D"}
1
+ {"version":3,"file":"docker-manager.d.ts","sourceRoot":"","sources":["../../../../../src/db/docker-manager.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,4CAA6C,CAAC;AAqBjF,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO1D;AAKD,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAOxD;AAKD,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAUjE;AAKD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE7D;AAKD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAW5D;AAMD,wBAAsB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/E;AAKD,wBAAsB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASpF;AAMD,wBAAsB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9E;AAKD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBzD;AAOD,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCpG;AAMD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOhE;AAOD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,MAAM,CAMlF;AAYD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CA0B7D"}
@@ -1,11 +1,20 @@
1
1
  import { execSync } from 'child_process';
2
+ export const FOURRUNR_DB_CONTAINERS = ['4runr-postgres', '4runr-redis'];
3
+ const COMPOSE_PROJECT = '4runr';
4
+ function dockerShell() {
5
+ return process.platform === 'win32' ? process.env['COMSPEC'] || 'cmd.exe' : undefined;
6
+ }
7
+ function dockerExec(command, timeoutMs = 30000) {
8
+ return execSync(command, {
9
+ encoding: 'utf-8',
10
+ stdio: 'pipe',
11
+ timeout: timeoutMs,
12
+ ...(dockerShell() ? { shell: dockerShell() } : {}),
13
+ });
14
+ }
2
15
  export async function isDockerAvailable() {
3
16
  try {
4
- const result = execSync('docker --version', {
5
- encoding: 'utf-8',
6
- stdio: 'pipe',
7
- timeout: 5000
8
- });
17
+ const result = dockerExec('docker --version', 5000);
9
18
  return result.includes('Docker version');
10
19
  }
11
20
  catch {
@@ -14,40 +23,56 @@ export async function isDockerAvailable() {
14
23
  }
15
24
  export async function isDockerRunning() {
16
25
  try {
17
- execSync('docker info', {
18
- encoding: 'utf-8',
19
- stdio: 'pipe',
20
- timeout: 5000
21
- });
26
+ dockerExec('docker info', 5000);
22
27
  return true;
23
28
  }
24
29
  catch {
25
30
  return false;
26
31
  }
27
32
  }
28
- export async function areContainersRunning() {
33
+ export function isContainerRunning(containerName) {
29
34
  try {
30
- const result = execSync('docker ps --filter "name=4runr-postgres" --format "{{.Names}}"', {
31
- encoding: 'utf-8',
32
- stdio: 'pipe',
33
- timeout: 5000
34
- });
35
- return result.trim().includes('4runr-postgres');
35
+ const state = dockerExec(`docker inspect --format="{{.State.Running}}" ${containerName}`, 5000).trim();
36
+ return state === 'true';
36
37
  }
37
38
  catch {
38
39
  return false;
39
40
  }
40
41
  }
42
+ export async function areContainersRunning() {
43
+ return FOURRUNR_DB_CONTAINERS.every((name) => isContainerRunning(name));
44
+ }
45
+ export async function startStoppedContainers() {
46
+ const stopped = FOURRUNR_DB_CONTAINERS.filter((name) => !isContainerRunning(name));
47
+ if (stopped.length === 0) {
48
+ return;
49
+ }
50
+ try {
51
+ dockerExec(`docker start ${stopped.join(' ')}`, 60000);
52
+ }
53
+ catch {
54
+ }
55
+ }
41
56
  export async function startDockerCompose(composeFilePath) {
42
- execSync(`docker compose -f "${composeFilePath}" up -d`, {
57
+ const cmd = `docker compose -p ${COMPOSE_PROJECT} -f "${composeFilePath}" up -d`;
58
+ execSync(cmd, {
43
59
  stdio: 'inherit',
44
- timeout: 60000
60
+ timeout: 120000,
61
+ ...(dockerShell() ? { shell: dockerShell() } : {}),
45
62
  });
46
63
  }
64
+ export async function ensure4RunrStackRunning(composeFilePath) {
65
+ await startStoppedContainers();
66
+ if (!(await areContainersRunning())) {
67
+ await startDockerCompose(composeFilePath);
68
+ }
69
+ await startStoppedContainers();
70
+ }
47
71
  export async function stopDockerCompose(composeFilePath) {
48
- execSync(`docker compose -f "${composeFilePath}" stop`, {
72
+ execSync(`docker compose -p ${COMPOSE_PROJECT} -f "${composeFilePath}" stop`, {
49
73
  stdio: 'pipe',
50
- timeout: 30000
74
+ timeout: 30000,
75
+ ...(dockerShell() ? { shell: dockerShell() } : {}),
51
76
  });
52
77
  }
53
78
  export async function stop4RunrContainers() {
@@ -74,39 +99,28 @@ export async function waitForHealthy(containerName, timeoutMs = 30000) {
74
99
  const start = Date.now();
75
100
  while (Date.now() - start < timeoutMs) {
76
101
  try {
77
- const health = execSync(`docker inspect --format="{{.State.Health.Status}}" ${containerName}`, {
78
- encoding: 'utf-8',
79
- stdio: 'pipe',
80
- timeout: 5000
81
- }).trim();
102
+ const health = dockerExec(`docker inspect --format="{{.State.Health.Status}}" ${containerName}`, 5000).trim();
82
103
  if (health === 'healthy') {
83
104
  return;
84
105
  }
85
106
  if (health === '' || health === '<no value>') {
86
- const running = execSync(`docker inspect --format="{{.State.Running}}" ${containerName}`, {
87
- encoding: 'utf-8',
88
- stdio: 'pipe',
89
- timeout: 5000
90
- }).trim();
107
+ const running = dockerExec(`docker inspect --format="{{.State.Running}}" ${containerName}`, 5000).trim();
91
108
  if (running === 'true') {
92
109
  await sleep(2000);
93
110
  return;
94
111
  }
95
112
  }
96
113
  }
97
- catch (err) {
114
+ catch {
98
115
  }
99
116
  await sleep(1000);
100
117
  }
101
- throw new Error(`Container ${containerName} did not become healthy within ${timeoutMs}ms`);
118
+ const logs = getContainerLogs(containerName, 20);
119
+ throw new Error(`Container ${containerName} did not become healthy within ${timeoutMs}ms. Recent logs:\n${logs}`);
102
120
  }
103
121
  export async function isPortInUse(port) {
104
122
  try {
105
- const result = execSync(`docker ps --filter "publish=${port}" --format "{{.Names}}"`, {
106
- encoding: 'utf-8',
107
- stdio: 'pipe',
108
- timeout: 5000
109
- });
123
+ const result = dockerExec(`docker ps --filter "publish=${port}" --format "{{.Names}}"`, 5000);
110
124
  return result.trim().length > 0;
111
125
  }
112
126
  catch {
@@ -115,24 +129,20 @@ export async function isPortInUse(port) {
115
129
  }
116
130
  export function getContainerLogs(containerName, lines = 50) {
117
131
  try {
118
- return execSync(`docker logs --tail ${lines} ${containerName}`, {
119
- encoding: 'utf-8',
120
- stdio: 'pipe',
121
- timeout: 10000
122
- });
132
+ return dockerExec(`docker logs --tail ${lines} ${containerName}`, 10000);
123
133
  }
124
134
  catch (err) {
125
135
  return `Failed to retrieve logs: ${err instanceof Error ? err.message : String(err)}`;
126
136
  }
127
137
  }
128
138
  function sleep(ms) {
129
- return new Promise(resolve => setTimeout(resolve, ms));
139
+ return new Promise((resolve) => setTimeout(resolve, ms));
130
140
  }
131
141
  export async function getDockerStatus() {
132
142
  const status = {
133
143
  available: false,
134
144
  running: false,
135
- containersRunning: false
145
+ containersRunning: false,
136
146
  };
137
147
  try {
138
148
  status.available = await isDockerAvailable();
@@ -1 +1 @@
1
- {"version":3,"file":"docker-manager.js","sourceRoot":"","sources":["../../../../../src/db/docker-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAMzC,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,kBAAkB,EAAE;YAC1C,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAKD,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,QAAQ,CAAC,aAAa,EAAE;YACtB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAKD,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,gEAAgE,EAAE;YACxF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,eAAuB;IAC9D,QAAQ,CAAC,sBAAsB,eAAe,SAAS,EAAE;QACvD,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,eAAuB;IAC7D,QAAQ,CAAC,sBAAsB,eAAe,QAAQ,EAAE;QACtD,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAKD,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,QAAQ,CAAC,8CAA8C,EAAE;gBACvD,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS;aAC3C,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,4DAA4D,EAAE;gBACrE,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;IAET,CAAC;AACH,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,aAAqB,EAAE,YAAoB,KAAK;IACnF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC;YAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,sDAAsD,aAAa,EAAE,EAAE;gBAC7F,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,IAAI;aACd,CAAC,CAAC,IAAI,EAAE,CAAC;YAEV,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO;YACT,CAAC;YAGD,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,gDAAgD,aAAa,EAAE,EAAE;oBACxF,QAAQ,EAAE,OAAO;oBACjB,KAAK,EAAE,MAAM;oBACb,OAAO,EAAE,IAAI;iBACd,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEV,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;oBAEvB,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;oBAClB,OAAO;gBACT,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;QAGf,CAAC;QAED,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,aAAa,aAAa,kCAAkC,SAAS,IAAI,CAAC,CAAC;AAC7F,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,IAAI,CAAC;QAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,+BAA+B,IAAI,yBAAyB,EAAE;YACpF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QAGP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,gBAAgB,CAAC,aAAqB,EAAE,QAAgB,EAAE;IACxE,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,sBAAsB,KAAK,IAAI,aAAa,EAAE,EAAE;YAC9D,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACxF,CAAC;AACH,CAAC;AAKD,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAeD,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GAAiB;QAC3B,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,KAAK;QACd,iBAAiB,EAAE,KAAK;KACzB,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,CAAC,SAAS,GAAG,MAAM,iBAAiB,EAAE,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,CAAC,KAAK,GAAG,sBAAsB,CAAC;YACtC,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,OAAO,GAAG,MAAM,eAAe,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,GAAG,2BAA2B,CAAC;YAC3C,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,iBAAiB,GAAG,MAAM,oBAAoB,EAAE,CAAC;QACxD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"docker-manager.js","sourceRoot":"","sources":["../../../../../src/db/docker-manager.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../src/db/init.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAiB9C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAQD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuGjF;AA2ID,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9F"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../src/db/init.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAkB9C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAQD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgGjF;AA2ID,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9F"}
@@ -7,7 +7,7 @@ import { PrismaClient } from '@prisma/client';
7
7
  import { get4RunrDataDir } from '@4runr/shared';
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = dirname(__filename);
10
- import { areContainersRunning, startDockerCompose, waitForHealthy, getDockerStatus } from './docker-manager.js';
10
+ import { ensure4RunrStackRunning, waitForHealthy, getDockerStatus } from './docker-manager.js';
11
11
  export async function initializeDatabase(logger) {
12
12
  const warnings = [];
13
13
  const persistenceMode = process.env['GATEWAY_PERSISTENCE'] || 'auto';
@@ -32,15 +32,8 @@ export async function initializeDatabase(logger) {
32
32
  return { mode: 'memory', client: null, warnings };
33
33
  }
34
34
  try {
35
- const containersRunning = await areContainersRunning();
36
- if (!containersRunning) {
37
- logger.info('Starting 4Runr Docker containers...');
38
- await startDockerContainers(logger);
39
- logger.info('✓ Docker containers started');
40
- }
41
- else {
42
- logger.info('✓ Docker containers already running');
43
- }
35
+ logger.info('Ensuring 4Runr Docker containers (Postgres + Redis) are running...');
36
+ await startDockerContainers(logger);
44
37
  logger.info('Waiting for database to be ready...');
45
38
  await waitForHealthy('4runr-postgres', 60000);
46
39
  await waitForHealthy('4runr-redis', 15000);
@@ -145,7 +138,7 @@ async function startDockerContainers(logger) {
145
138
  else {
146
139
  logger.warn(`Docker Compose template missing; using existing ${composeFilePath}`);
147
140
  }
148
- await startDockerCompose(composeFilePath);
141
+ await ensure4RunrStackRunning(composeFilePath);
149
142
  }
150
143
  async function runMigrations(databaseUrl, logger) {
151
144
  const candidates = [
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../../src/db/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../../src/db/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,OAAO,EAKL,uBAAuB,EACvB,cAAc,EACd,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAmB7B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAW;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAG9B,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,MAAM,CAAC;IACrE,IAAI,eAAe,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;QAC7E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC;IAGD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,eAAe,KAAK,UAAU,EAAE,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QACxD,OAAO,MAAM,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;IAGD,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;IAElE,MAAM,YAAY,GAAG,MAAM,eAAe,EAAE,CAAC;IAE7C,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;QAC3E,QAAQ,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC5F,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAChF,QAAQ,CAAC,IAAI,CAAC,yFAAyF,CAAC,CAAC;QACzG,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACpD,CAAC;IAGD,IAAI,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;QAClF,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAGpC,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACnD,MAAM,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAC9C,MAAM,cAAc,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAG7C,MAAM,WAAW,GAAG,8DAA8D,CAAC;QACnF,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAG1C,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,WAAW,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC;QAGpC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC9C,MAAM,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAGrC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;YAC9B,WAAW,EAAE;gBACX,EAAE,EAAE;oBACF,GAAG,EAAE,WAAW;iBACjB;aACF;YACD,GAAG,EAAE;gBACH,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;gBAChC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;aAClC;SACF,CAAC,CAAC;QAGH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAG3E,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAEjD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM;YACN,WAAW;SACZ,CAAC;IAEJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,sCAAsC,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QAEpD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,CAAC,8DAA8D,EAAE,QAAQ,CAAC;SACrF,CAAC;IACJ,CAAC;AACH,CAAC;AAKD,KAAK,UAAU,8BAA8B,CAAC,MAAW;IACvD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAE,CAAC;QAGjD,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC9C,MAAM,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAGrC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;YAC9B,GAAG,EAAE;gBACH,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;gBAChC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;aAClC;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAE3E,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAEjD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM;YACN,WAAW;SACZ,CAAC;IAEJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,+BAA+B,CAAC,CAAC;QAEvD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,CAAC,0DAA0D,EAAE,QAAQ,CAAC;SACjF,CAAC;IACJ,CAAC;AACH,CAAC;AAKD,KAAK,UAAU,qBAAqB,CAAC,MAAW;IAE9C,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAIjE,MAAM,aAAa,GAAG;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,0BAA0B,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gCAAgC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mCAAmC,CAAC;QACzD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,sCAAsC,CAAC;QAC5D,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uCAAuC,CAAC;KAClE,CAAC;IAEF,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,YAAY,GAAG,OAAO,CAAC;YACvB,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,wCAAwC,YAAY,MAAM,eAAe,EAAE,CAAC,CAAC;QACzF,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;IACjD,CAAC;SAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,6CAA6C,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,mDAAmD,eAAe,EAAE,CAAC,CAAC;IACpF,CAAC;IAGD,MAAM,uBAAuB,CAAC,eAAe,CAAC,CAAC;AACjD,CAAC;AAKD,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,MAAW;IAE3D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC;QAC/D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qCAAqC,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kCAAkC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,+BAA+B,CAAC;QACrD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,eAAe,CAAC;KACpD,CAAC;IACF,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,gBAAgB,GAAG,CAAC,CAAC;YACrB,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CACT,sCAAsC,UAAU,CAAC,MAAM,sDAAsD,CAC9G,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QAGH,MAAM,aAAa,GAAG,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,aAAa;YAC3B,CAAC,CAAC,uDAAuD;YACzD,CAAC,CAAC,2BAA2B,CAAC;QAEhC,QAAQ,CAAC,OAAO,EAAE;YAChB,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,YAAY,EAAE,WAAW;aAC1B;YACD,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC;YACnC,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAKD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAA2B,EAAE,MAAW;IAC7E,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,mCAAmC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAGD,IAAI,CAAC;QACH,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACpE,MAAM,mBAAmB,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAEb,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
@@ -2,6 +2,8 @@
2
2
  # Lightweight Postgres + Redis for local development
3
3
  # Volumes persist data across restarts and npm updates
4
4
 
5
+ name: 4runr
6
+
5
7
  services:
6
8
  postgres:
7
9
  image: postgres:15-alpine
@@ -1,16 +1,30 @@
1
1
  import { execSync } from 'child_process';
2
2
 
3
+ /** Must match `container_name` in docker-compose.local.yml */
4
+ export const FOURRUNR_DB_CONTAINERS = ['4runr-postgres', '4runr-redis'] as const;
5
+
6
+ const COMPOSE_PROJECT = '4runr';
7
+
8
+ function dockerShell(): string | undefined {
9
+ return process.platform === 'win32' ? process.env['COMSPEC'] || 'cmd.exe' : undefined;
10
+ }
11
+
12
+ function dockerExec(command: string, timeoutMs: number = 30000): string {
13
+ return execSync(command, {
14
+ encoding: 'utf-8',
15
+ stdio: 'pipe',
16
+ timeout: timeoutMs,
17
+ ...(dockerShell() ? { shell: dockerShell() } : {}),
18
+ });
19
+ }
20
+
3
21
  /**
4
22
  * Check if Docker is installed and available
5
23
  * Works with both Docker Desktop and Docker Engine
6
24
  */
7
25
  export async function isDockerAvailable(): Promise<boolean> {
8
26
  try {
9
- const result = execSync('docker --version', {
10
- encoding: 'utf-8',
11
- stdio: 'pipe',
12
- timeout: 5000
13
- });
27
+ const result = dockerExec('docker --version', 5000);
14
28
  return result.includes('Docker version');
15
29
  } catch {
16
30
  return false;
@@ -22,11 +36,7 @@ export async function isDockerAvailable(): Promise<boolean> {
22
36
  */
23
37
  export async function isDockerRunning(): Promise<boolean> {
24
38
  try {
25
- execSync('docker info', {
26
- encoding: 'utf-8',
27
- stdio: 'pipe',
28
- timeout: 5000
29
- });
39
+ dockerExec('docker info', 5000);
30
40
  return true;
31
41
  } catch {
32
42
  return false;
@@ -34,40 +44,79 @@ export async function isDockerRunning(): Promise<boolean> {
34
44
  }
35
45
 
36
46
  /**
37
- * Check if 4Runr containers are running
47
+ * Check if a named container is running
38
48
  */
39
- export async function areContainersRunning(): Promise<boolean> {
49
+ export function isContainerRunning(containerName: string): boolean {
40
50
  try {
41
- const result = execSync('docker ps --filter "name=4runr-postgres" --format "{{.Names}}"', {
42
- encoding: 'utf-8',
43
- stdio: 'pipe',
44
- timeout: 5000
45
- });
46
- return result.trim().includes('4runr-postgres');
51
+ const state = dockerExec(
52
+ `docker inspect --format="{{.State.Running}}" ${containerName}`,
53
+ 5000,
54
+ ).trim();
55
+ return state === 'true';
47
56
  } catch {
48
57
  return false;
49
58
  }
50
59
  }
51
60
 
61
+ /**
62
+ * Check if both 4Runr Postgres and Redis containers are running
63
+ */
64
+ export async function areContainersRunning(): Promise<boolean> {
65
+ return FOURRUNR_DB_CONTAINERS.every((name) => isContainerRunning(name));
66
+ }
67
+
68
+ /**
69
+ * Start stopped 4Runr containers by name (watchdog stops them on 4r exit)
70
+ */
71
+ export async function startStoppedContainers(): Promise<void> {
72
+ const stopped = FOURRUNR_DB_CONTAINERS.filter((name) => !isContainerRunning(name));
73
+ if (stopped.length === 0) {
74
+ return;
75
+ }
76
+
77
+ try {
78
+ dockerExec(`docker start ${stopped.join(' ')}`, 60000);
79
+ } catch {
80
+ // Container may not exist yet — compose up will create it
81
+ }
82
+ }
83
+
52
84
  /**
53
85
  * Start Docker Compose services
54
86
  * @param composeFilePath - Absolute path to docker-compose.yml
55
87
  */
56
88
  export async function startDockerCompose(composeFilePath: string): Promise<void> {
57
- execSync(`docker compose -f "${composeFilePath}" up -d`, {
89
+ const cmd = `docker compose -p ${COMPOSE_PROJECT} -f "${composeFilePath}" up -d`;
90
+ execSync(cmd, {
58
91
  stdio: 'inherit',
59
- timeout: 60000 // 60 seconds for pulling images if needed
92
+ timeout: 120000,
93
+ ...(dockerShell() ? { shell: dockerShell() } : {}),
60
94
  });
61
95
  }
62
96
 
97
+ /**
98
+ * Ensure Postgres + Redis are up: start stopped containers, then compose up if needed.
99
+ */
100
+ export async function ensure4RunrStackRunning(composeFilePath: string): Promise<void> {
101
+ await startStoppedContainers();
102
+
103
+ if (!(await areContainersRunning())) {
104
+ await startDockerCompose(composeFilePath);
105
+ }
106
+
107
+ // Watchdog may have stopped only one container — verify both after compose/start
108
+ await startStoppedContainers();
109
+ }
110
+
63
111
  /**
64
112
  * Stop Docker Compose services (preserves data volumes)
65
113
  * @param composeFilePath - Absolute path to docker-compose.yml
66
114
  */
67
115
  export async function stopDockerCompose(composeFilePath: string): Promise<void> {
68
- execSync(`docker compose -f "${composeFilePath}" stop`, {
116
+ execSync(`docker compose -p ${COMPOSE_PROJECT} -f "${composeFilePath}" stop`, {
69
117
  stdio: 'pipe',
70
- timeout: 30000
118
+ timeout: 30000,
119
+ ...(dockerShell() ? { shell: dockerShell() } : {}),
71
120
  });
72
121
  }
73
122
 
@@ -101,43 +150,41 @@ export async function stop4RunrContainers(): Promise<void> {
101
150
  */
102
151
  export async function waitForHealthy(containerName: string, timeoutMs: number = 30000): Promise<void> {
103
152
  const start = Date.now();
104
-
153
+
105
154
  while (Date.now() - start < timeoutMs) {
106
155
  try {
107
- // Use double quotes for Windows compatibility
108
- const health = execSync(`docker inspect --format="{{.State.Health.Status}}" ${containerName}`, {
109
- encoding: 'utf-8',
110
- stdio: 'pipe',
111
- timeout: 5000
112
- }).trim();
113
-
156
+ const health = dockerExec(
157
+ `docker inspect --format="{{.State.Health.Status}}" ${containerName}`,
158
+ 5000,
159
+ ).trim();
160
+
114
161
  if (health === 'healthy') {
115
162
  return;
116
163
  }
117
-
164
+
118
165
  // Also accept containers without health checks that are running
119
166
  if (health === '' || health === '<no value>') {
120
- const running = execSync(`docker inspect --format="{{.State.Running}}" ${containerName}`, {
121
- encoding: 'utf-8',
122
- stdio: 'pipe',
123
- timeout: 5000
124
- }).trim();
125
-
167
+ const running = dockerExec(
168
+ `docker inspect --format="{{.State.Running}}" ${containerName}`,
169
+ 5000,
170
+ ).trim();
171
+
126
172
  if (running === 'true') {
127
- // Give it a moment to stabilize
128
173
  await sleep(2000);
129
174
  return;
130
175
  }
131
176
  }
132
- } catch (err) {
133
- // Container might not exist yet or Docker command failed
134
- // Continue waiting
177
+ } catch {
178
+ // Container might not exist yet or Docker command failed — keep waiting
135
179
  }
136
-
180
+
137
181
  await sleep(1000);
138
182
  }
139
-
140
- throw new Error(`Container ${containerName} did not become healthy within ${timeoutMs}ms`);
183
+
184
+ const logs = getContainerLogs(containerName, 20);
185
+ throw new Error(
186
+ `Container ${containerName} did not become healthy within ${timeoutMs}ms. Recent logs:\n${logs}`,
187
+ );
141
188
  }
142
189
 
143
190
  /**
@@ -146,16 +193,9 @@ export async function waitForHealthy(containerName: string, timeoutMs: number =
146
193
  */
147
194
  export async function isPortInUse(port: number): Promise<boolean> {
148
195
  try {
149
- // Try to list containers using this port
150
- const result = execSync(`docker ps --filter "publish=${port}" --format "{{.Names}}"`, {
151
- encoding: 'utf-8',
152
- stdio: 'pipe',
153
- timeout: 5000
154
- });
196
+ const result = dockerExec(`docker ps --filter "publish=${port}" --format "{{.Names}}"`, 5000);
155
197
  return result.trim().length > 0;
156
198
  } catch {
157
- // If command fails, assume port might be in use by non-Docker process
158
- // Let Docker compose handle the conflict
159
199
  return false;
160
200
  }
161
201
  }
@@ -167,11 +207,7 @@ export async function isPortInUse(port: number): Promise<boolean> {
167
207
  */
168
208
  export function getContainerLogs(containerName: string, lines: number = 50): string {
169
209
  try {
170
- return execSync(`docker logs --tail ${lines} ${containerName}`, {
171
- encoding: 'utf-8',
172
- stdio: 'pipe',
173
- timeout: 10000
174
- });
210
+ return dockerExec(`docker logs --tail ${lines} ${containerName}`, 10000);
175
211
  } catch (err) {
176
212
  return `Failed to retrieve logs: ${err instanceof Error ? err.message : String(err)}`;
177
213
  }
@@ -181,7 +217,7 @@ export function getContainerLogs(containerName: string, lines: number = 50): str
181
217
  * Sleep helper
182
218
  */
183
219
  function sleep(ms: number): Promise<void> {
184
- return new Promise(resolve => setTimeout(resolve, ms));
220
+ return new Promise((resolve) => setTimeout(resolve, ms));
185
221
  }
186
222
 
187
223
  /**
@@ -201,22 +237,22 @@ export async function getDockerStatus(): Promise<DockerStatus> {
201
237
  const status: DockerStatus = {
202
238
  available: false,
203
239
  running: false,
204
- containersRunning: false
240
+ containersRunning: false,
205
241
  };
206
-
242
+
207
243
  try {
208
244
  status.available = await isDockerAvailable();
209
245
  if (!status.available) {
210
246
  status.error = 'Docker not installed';
211
247
  return status;
212
248
  }
213
-
249
+
214
250
  status.running = await isDockerRunning();
215
251
  if (!status.running) {
216
252
  status.error = 'Docker daemon not running';
217
253
  return status;
218
254
  }
219
-
255
+
220
256
  status.containersRunning = await areContainersRunning();
221
257
  return status;
222
258
  } catch (err) {
@@ -13,6 +13,7 @@ import {
13
13
  isDockerRunning,
14
14
  areContainersRunning,
15
15
  startDockerCompose,
16
+ ensure4RunrStackRunning,
16
17
  waitForHealthy,
17
18
  getDockerStatus
18
19
  } from './docker-manager.js';
@@ -67,21 +68,14 @@ export async function initializeDatabase(logger: any): Promise<DatabaseInitResul
67
68
  return { mode: 'memory', client: null, warnings };
68
69
  }
69
70
 
70
- // Docker is available - proceed with container startup
71
+ // Docker is available - ensure both Postgres and Redis are running
71
72
  try {
72
- const containersRunning = await areContainersRunning();
73
-
74
- if (!containersRunning) {
75
- logger.info('Starting 4Runr Docker containers...');
76
- await startDockerContainers(logger);
77
- logger.info('✓ Docker containers started');
78
- } else {
79
- logger.info('✓ Docker containers already running');
80
- }
81
-
82
- // Wait for containers to be healthy
73
+ logger.info('Ensuring 4Runr Docker containers (Postgres + Redis) are running...');
74
+ await startDockerContainers(logger);
75
+
76
+ // Wait for containers to be healthy (Postgres first slower cold start)
83
77
  logger.info('Waiting for database to be ready...');
84
- await waitForHealthy('4runr-postgres', 60000); // 60s for Postgres (first start slower)
78
+ await waitForHealthy('4runr-postgres', 60000);
85
79
  await waitForHealthy('4runr-redis', 15000);
86
80
  logger.info('✓ Database containers healthy');
87
81
 
@@ -219,8 +213,8 @@ async function startDockerContainers(logger: any): Promise<void> {
219
213
  logger.warn(`Docker Compose template missing; using existing ${composeFilePath}`);
220
214
  }
221
215
 
222
- // Start containers
223
- await startDockerCompose(composeFilePath);
216
+ // Start or restart containers (watchdog stops both when 4r exits)
217
+ await ensure4RunrStackRunning(composeFilePath);
224
218
  }
225
219
 
226
220
  /**