Add Edge Broker service and rename 'rows' column to 'terminal_rows' in Edge Gateway schema
This commit is contained in:
@@ -80,6 +80,16 @@ services:
|
||||
retries: 10
|
||||
start_period: 20s
|
||||
|
||||
edge-broker:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: services/edge-broker/Dockerfile
|
||||
container_name: edge-broker
|
||||
environment:
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
ports:
|
||||
- "4300:4300"
|
||||
|
||||
caddy:
|
||||
image: caddy:2.7.6-alpine
|
||||
container_name: caddy
|
||||
@@ -196,11 +206,14 @@ services:
|
||||
container_name: php1
|
||||
depends_on:
|
||||
- redis
|
||||
- edge-broker
|
||||
command: ["php-fpm"]
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "true"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
@@ -213,11 +226,14 @@ services:
|
||||
container_name: php2
|
||||
depends_on:
|
||||
- redis
|
||||
- edge-broker
|
||||
command: ["php-fpm"]
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "false"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
@@ -230,11 +246,14 @@ services:
|
||||
container_name: php3
|
||||
depends_on:
|
||||
- redis
|
||||
- edge-broker
|
||||
command: ["php-fpm"]
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "false"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
@@ -247,11 +266,14 @@ services:
|
||||
container_name: php4
|
||||
depends_on:
|
||||
- redis
|
||||
- edge-broker
|
||||
command: ["php-fpm"]
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "false"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
@@ -264,11 +286,14 @@ services:
|
||||
container_name: php5
|
||||
depends_on:
|
||||
- redis
|
||||
- edge-broker
|
||||
command: ["php-fpm"]
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "false"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
@@ -281,11 +306,14 @@ services:
|
||||
container_name: php-staging
|
||||
depends_on:
|
||||
- redis-staging
|
||||
- edge-broker
|
||||
command: ["php-fpm"]
|
||||
env_file:
|
||||
- .env.staging
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "false"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
@@ -298,11 +326,14 @@ services:
|
||||
container_name: php-cron
|
||||
depends_on:
|
||||
- redis
|
||||
- edge-broker
|
||||
command: ["sh", "-c", "while true; do php index.php run cron; sleep 60; done"]
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTO_COMPOSER_INSTALL: "false"
|
||||
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
|
||||
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
|
||||
volumes:
|
||||
- ./services/nginx/app:/var/www/html
|
||||
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
|
||||
|
||||
@@ -20,6 +20,17 @@ const traefikSource = [
|
||||
readRequiredSource("services", "traefik", "traefik.prod.yml"),
|
||||
].join("\n");
|
||||
|
||||
function readComposeServiceBlock(composeSource, serviceName) {
|
||||
const escapedServiceName = serviceName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const servicePattern = new RegExp(
|
||||
`^\\s{2}${escapedServiceName}:\\n([\\s\\S]*?)(?=^\\s{2}[A-Za-z0-9_-]+:|^volumes:|^networks:|\\Z)`,
|
||||
"m"
|
||||
);
|
||||
const match = composeSource.match(servicePattern);
|
||||
assert.ok(match, `Expected docker compose service block for ${serviceName}`);
|
||||
return match[0];
|
||||
}
|
||||
|
||||
test("traefik does not expose a dedicated public edge broker port", () => {
|
||||
assert.doesNotMatch(traefikSource, /edge-broker:\s*\n\s*address:\s*":4300"/);
|
||||
});
|
||||
@@ -40,3 +51,12 @@ test("php services receive broker websocket environment defaults", () => {
|
||||
assert.match(composeSource, /EDGE_BROKER_SHARED_SECRET:\s*\$\{EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev\}/);
|
||||
}
|
||||
});
|
||||
|
||||
test("base docker compose wires the broker into each php worker", () => {
|
||||
for (const serviceName of ["php1", "php2", "php3", "php4", "php5", "php-staging", "php-cron"]) {
|
||||
const serviceBlock = readComposeServiceBlock(baseComposeSource, serviceName);
|
||||
assert.match(serviceBlock, /\n\s+depends_on:\s*\n[\s\S]*?\n\s+- edge-broker/);
|
||||
assert.match(serviceBlock, /EDGE_BROKER_URL:\s*\$\{EDGE_BROKER_URL:-http:\/\/edge-broker:4300\}/);
|
||||
assert.match(serviceBlock, /EDGE_BROKER_SHARED_SECRET:\s*\$\{EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev\}/);
|
||||
}
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1690,7 +1690,7 @@ BASH;
|
||||
'shell_command' => null,
|
||||
'shell_args_json' => [],
|
||||
'cols' => $cols,
|
||||
'rows' => $rows,
|
||||
'terminal_rows' => $rows,
|
||||
'transcript' => null,
|
||||
'metadata_json' => [
|
||||
'root_dir' => self::DEFAULT_INSTALL_DIR,
|
||||
|
||||
@@ -211,7 +211,7 @@ class edge_gateway_schema_bootstrap
|
||||
shell_command VARCHAR(255) NULL,
|
||||
shell_args_json JSON NULL,
|
||||
cols INT NULL,
|
||||
rows INT NULL,
|
||||
terminal_rows INT NULL,
|
||||
transcript LONGTEXT NULL,
|
||||
metadata_json JSON NULL,
|
||||
expires_at DATETIME NULL,
|
||||
@@ -278,8 +278,9 @@ class edge_gateway_schema_bootstrap
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'shell_command', 'VARCHAR(255) NULL AFTER cwd');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'shell_args_json', 'JSON NULL AFTER shell_command');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'cols', 'INT NULL AFTER shell_args_json');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'rows', 'INT NULL AFTER cols');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'transcript', 'LONGTEXT NULL AFTER rows');
|
||||
self::renameColumnIfPresent('edge_gateway_shell_sessions', 'rows', 'terminal_rows', 'INT NULL', 'cols');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'terminal_rows', 'INT NULL AFTER cols');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'transcript', 'LONGTEXT NULL AFTER terminal_rows');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'metadata_json', 'JSON NULL AFTER transcript');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'expires_at', 'DATETIME NULL AFTER metadata_json');
|
||||
self::ensureColumn('edge_gateway_shell_sessions', 'approved_at', 'DATETIME NULL AFTER expires_at');
|
||||
@@ -311,6 +312,34 @@ class edge_gateway_schema_bootstrap
|
||||
);
|
||||
}
|
||||
|
||||
private static function renameColumnIfPresent(
|
||||
string $table,
|
||||
string $from,
|
||||
string $to,
|
||||
string $definition,
|
||||
?string $afterColumn = null
|
||||
): void {
|
||||
global $db;
|
||||
|
||||
if (!self::tableHasColumn($table, $from) || self::tableHasColumn($table, $to)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!preg_match('/^[A-Za-z0-9_]+$/', $table)
|
||||
|| !preg_match('/^[A-Za-z0-9_]+$/', $from)
|
||||
|| !preg_match('/^[A-Za-z0-9_]+$/', $to)
|
||||
|| ($afterColumn !== null && !preg_match('/^[A-Za-z0-9_]+$/', $afterColumn))) {
|
||||
throw new \RuntimeException('Invalid schema bootstrap identifier');
|
||||
}
|
||||
|
||||
$positionClause = $afterColumn === null ? '' : " AFTER `$afterColumn`";
|
||||
|
||||
$db->query(
|
||||
"ALTER TABLE `$table`
|
||||
CHANGE COLUMN `$from` `$to` $definition$positionClause"
|
||||
);
|
||||
}
|
||||
|
||||
private static function tableHasColumn(string $table, string $column): bool
|
||||
{
|
||||
global $db;
|
||||
|
||||
@@ -52,7 +52,7 @@ class edge_gateway_shell_sessions_o extends db
|
||||
$this->shell_command = new object_property($this->table, $this->id, 'shell_command', 'string', false);
|
||||
$this->shell_args_json = new object_property($this->table, $this->id, 'shell_args_json', 'json', false);
|
||||
$this->cols = new object_property($this->table, $this->id, 'cols', 'int', false);
|
||||
$this->rows = new object_property($this->table, $this->id, 'rows', 'int', false);
|
||||
$this->rows = new object_property($this->table, $this->id, 'terminal_rows', 'int', false);
|
||||
$this->transcript = new object_property($this->table, $this->id, 'transcript', 'text', false);
|
||||
$this->metadata_json = new object_property($this->table, $this->id, 'metadata_json', 'json', false);
|
||||
$this->expires_at = new object_property($this->table, $this->id, 'expires_at', 'string', false);
|
||||
|
||||
@@ -45,4 +45,6 @@ it('stores operation metadata and event timelines for management workflows', fun
|
||||
expect($bootstrapContent)->toContain('summary_json JSON NULL');
|
||||
expect($bootstrapContent)->toContain('context_json JSON NULL');
|
||||
expect($bootstrapContent)->toContain('session_token_hash CHAR(64) NOT NULL');
|
||||
expect($bootstrapContent)->toContain('terminal_rows INT NULL');
|
||||
expect($bootstrapContent)->toContain("renameColumnIfPresent('edge_gateway_shell_sessions', 'rows', 'terminal_rows', 'INT NULL', 'cols')");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user