finished actions => handlers refacto, small bux fix in maestro => Test maestro1 OK
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@ import {
|
|||||||
positionAt,
|
positionAt,
|
||||||
needsPrismRefresh,
|
needsPrismRefresh,
|
||||||
advanceAgentSegment,
|
advanceAgentSegment,
|
||||||
} from './actions/arena/worldline.js'
|
} from './handlers/arena/worldline.js'
|
||||||
|
|
||||||
export class gpsServer {
|
export class gpsServer {
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -6,8 +6,8 @@ import {RedisConnexion} from '../redisConnexion.js'
|
|||||||
import { busReplyRoute } from '../bus/publishActionReply.js'
|
import { busReplyRoute } from '../bus/publishActionReply.js'
|
||||||
import {configHelper} from '../configHelper.js'
|
import {configHelper} from '../configHelper.js'
|
||||||
import {gpsServer} from './gpsServer.js'
|
import {gpsServer} from './gpsServer.js'
|
||||||
import * as systemMesh from './actions/system/index.js'
|
import * as systemMesh from './handlers/system/index.js'
|
||||||
import * as arenaMesh from './actions/arena/index.js'
|
import * as arenaMesh from './handlers/arena/index.js'
|
||||||
|
|
||||||
const meshModules = {
|
const meshModules = {
|
||||||
system: systemMesh,
|
system: systemMesh,
|
||||||
|
|||||||
+13
-3
@@ -1,5 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
# shellcheck source=../lib/resolveConfigPath.sh
|
||||||
|
. "$SCRIPT_DIR/../lib/resolveConfigPath.sh"
|
||||||
|
|
||||||
|
CONFIG="$(resolveConfigPath "$SCRIPT_DIR" "${1:-${CONFIG:-../config.json}}")"
|
||||||
|
|
||||||
set -a
|
set -a
|
||||||
. /etc/p42/secrets.env
|
. /etc/p42/secrets.env
|
||||||
set +a
|
set +a
|
||||||
@@ -7,12 +13,16 @@ set +a
|
|||||||
daemon=p42Gps
|
daemon=p42Gps
|
||||||
logfile=gps.log
|
logfile=gps.log
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG" ]; then
|
||||||
|
echo "Config file not found: $CONFIG" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
pid=$(pgrep -f "$daemon")
|
pid=$(pgrep -f "$daemon")
|
||||||
|
|
||||||
if [ -z "$pid" ]
|
if [ -z "$pid" ]
|
||||||
then
|
then
|
||||||
node "${daemon}.js" --debug > "$logfile" 2>&1 &
|
node "${daemon}.js" --config "$CONFIG" --debug > "$logfile" 2>&1 &
|
||||||
pid=$!
|
pid=$!
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -20,16 +30,16 @@ then
|
|||||||
if kill -0 "$pid" 2>/dev/null
|
if kill -0 "$pid" 2>/dev/null
|
||||||
then
|
then
|
||||||
echo ""
|
echo ""
|
||||||
echo "$daemon is now running with PID=$pid"
|
echo "$daemon is now running with PID=$pid (config=$CONFIG)"
|
||||||
echo ""
|
echo ""
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "Failed to start $daemon. Check gps.log"
|
echo "Failed to start $daemon. Check gps.log"
|
||||||
echo ""
|
echo ""
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "$daemon is already running with PID=$pid"
|
echo "$daemon is already running with PID=$pid"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ export class maestroServer {
|
|||||||
|
|
||||||
refreshPrepareQuorum() {
|
refreshPrepareQuorum() {
|
||||||
if(!this.arenaCnx) return
|
if(!this.arenaCnx) return
|
||||||
const { prepareAckChannel, readyTimeoutMs } = this.getMaestroSettings()
|
const { lifecycle, readyTimeoutMs } = this.getMaestroSettings()
|
||||||
this.prepareQuorum = new PrepareQuorum({
|
this.prepareQuorum = new PrepareQuorum({
|
||||||
ackChannel: prepareAckChannel,
|
ackChannel: lifecycle.prepareAckChannel,
|
||||||
timeoutMs: readyTimeoutMs,
|
timeoutMs: readyTimeoutMs,
|
||||||
matchesChan: this.arenaCnx.matchesChan.bind(this.arenaCnx),
|
matchesChan: this.arenaCnx.matchesChan.bind(this.arenaCnx),
|
||||||
debug: this.debug,
|
debug: this.debug,
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { RedisConnexion } from '../redisConnexion.js'
|
|||||||
import { busReplyRoute } from '../bus/publishActionReply.js'
|
import { busReplyRoute } from '../bus/publishActionReply.js'
|
||||||
import { configHelper } from '../configHelper.js'
|
import { configHelper } from '../configHelper.js'
|
||||||
import { maestroServer } from './maestroServer.js'
|
import { maestroServer } from './maestroServer.js'
|
||||||
import * as systemMesh from './actions/system/index.js'
|
import * as systemMesh from './handlers/system/index.js'
|
||||||
import * as arenaMesh from './actions/arena/index.js'
|
import * as arenaMesh from './handlers/arena/index.js'
|
||||||
|
|
||||||
const meshModules = {
|
const meshModules = {
|
||||||
system: systemMesh,
|
system: systemMesh,
|
||||||
|
|||||||
+14
-2
@@ -1,5 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
# shellcheck source=../lib/resolveConfigPath.sh
|
||||||
|
. "$SCRIPT_DIR/../lib/resolveConfigPath.sh"
|
||||||
|
|
||||||
|
CONFIG="$(resolveConfigPath "$SCRIPT_DIR" "${1:-${CONFIG:-../config.json}}")"
|
||||||
|
|
||||||
set -a
|
set -a
|
||||||
. /etc/p42/secrets.env
|
. /etc/p42/secrets.env
|
||||||
set +a
|
set +a
|
||||||
@@ -7,11 +13,16 @@ set +a
|
|||||||
daemon=p42Maestro
|
daemon=p42Maestro
|
||||||
logfile=maestro.log
|
logfile=maestro.log
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG" ]; then
|
||||||
|
echo "Config file not found: $CONFIG" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
pid=$(pgrep -f "$daemon")
|
pid=$(pgrep -f "$daemon")
|
||||||
|
|
||||||
if [ -z "$pid" ]
|
if [ -z "$pid" ]
|
||||||
then
|
then
|
||||||
node "${daemon}.js" --debug > "$logfile" 2>&1 &
|
node "${daemon}.js" --config "$CONFIG" --debug > "$logfile" 2>&1 &
|
||||||
pid=$!
|
pid=$!
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -19,12 +30,13 @@ then
|
|||||||
if kill -0 "$pid" 2>/dev/null
|
if kill -0 "$pid" 2>/dev/null
|
||||||
then
|
then
|
||||||
echo ""
|
echo ""
|
||||||
echo "$daemon is now running with PID=$pid"
|
echo "$daemon is now running with PID=$pid (config=$CONFIG)"
|
||||||
echo ""
|
echo ""
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "Failed to start $daemon. Check maestro.log"
|
echo "Failed to start $daemon. Check maestro.log"
|
||||||
echo ""
|
echo ""
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { positionAt } from '../GPS/actions/arena/worldline.js'
|
import { positionAt } from '../GPS/handlers/arena/worldline.js'
|
||||||
|
|
||||||
export class GpsStorageReader {
|
export class GpsStorageReader {
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { RedisConnexion } from '../redisConnexion.js'
|
|||||||
import { busReplyRoute } from '../bus/publishActionReply.js'
|
import { busReplyRoute } from '../bus/publishActionReply.js'
|
||||||
import { configHelper } from '../configHelper.js'
|
import { configHelper } from '../configHelper.js'
|
||||||
import { observerServer } from './observerServer.js'
|
import { observerServer } from './observerServer.js'
|
||||||
import * as systemMesh from './actions/system/index.js'
|
import * as systemMesh from './handlers/system/index.js'
|
||||||
import * as arenaMesh from './actions/arena/index.js'
|
import * as arenaMesh from './handlers/arena/index.js'
|
||||||
|
|
||||||
const meshModules = {
|
const meshModules = {
|
||||||
system: systemMesh,
|
system: systemMesh,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { positionAt } from '../GPS/actions/arena/worldline.js'
|
import { positionAt } from '../GPS/handlers/arena/worldline.js'
|
||||||
import { Frustum } from './frustum.js'
|
import { Frustum } from './frustum.js'
|
||||||
|
|
||||||
export class RequestorRegistry {
|
export class RequestorRegistry {
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
# shellcheck source=../lib/resolveConfigPath.sh
|
||||||
|
. "$SCRIPT_DIR/../lib/resolveConfigPath.sh"
|
||||||
|
|
||||||
|
CONFIG="$(resolveConfigPath "$SCRIPT_DIR" "${1:-${CONFIG:-../config.json}}")"
|
||||||
|
|
||||||
set -a
|
set -a
|
||||||
. /etc/p42/secrets.env
|
. /etc/p42/secrets.env
|
||||||
set +a
|
set +a
|
||||||
@@ -7,11 +13,16 @@ set +a
|
|||||||
daemon=p42Observer
|
daemon=p42Observer
|
||||||
logfile=observer.log
|
logfile=observer.log
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG" ]; then
|
||||||
|
echo "Config file not found: $CONFIG" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
pid=$(pgrep -f "$daemon")
|
pid=$(pgrep -f "$daemon")
|
||||||
|
|
||||||
if [ -z "$pid" ]
|
if [ -z "$pid" ]
|
||||||
then
|
then
|
||||||
node "${daemon}.js" --debug > "$logfile" 2>&1 &
|
node "${daemon}.js" --config "$CONFIG" --debug > "$logfile" 2>&1 &
|
||||||
pid=$!
|
pid=$!
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -19,12 +30,13 @@ then
|
|||||||
if kill -0 "$pid" 2>/dev/null
|
if kill -0 "$pid" 2>/dev/null
|
||||||
then
|
then
|
||||||
echo ""
|
echo ""
|
||||||
echo "$daemon is now running with PID=$pid"
|
echo "$daemon is now running with PID=$pid (config=$CONFIG)"
|
||||||
echo ""
|
echo ""
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "Failed to start $daemon. Check observer.log"
|
echo "Failed to start $daemon. Check observer.log"
|
||||||
echo ""
|
echo ""
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"accessRights": [
|
||||||
|
{
|
||||||
|
"canDo": [
|
||||||
|
"RELOADCONFIG",
|
||||||
|
"GETCONFIG"
|
||||||
|
],
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"canDo": [
|
||||||
|
"GETAGENTPOSITION",
|
||||||
|
"GETAGENTSINFRUSTUM",
|
||||||
|
"SUBSCRIBEFRUSTUM"
|
||||||
|
],
|
||||||
|
"roles": "*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"canDo": [
|
||||||
|
"STARTSIMULATION",
|
||||||
|
"STOPSIMULATION"
|
||||||
|
],
|
||||||
|
"roles": "*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gps": {
|
||||||
|
"primordialDaemon": true,
|
||||||
|
"gpsActionsChannel": "system:requests:gps",
|
||||||
|
"gpsActionsReply": "system:replies:[UID]",
|
||||||
|
"GPSstorage": {
|
||||||
|
"agentHashKey": "system:gps:agent:[UID]",
|
||||||
|
"agentsIndexKey": "system:gps:agents",
|
||||||
|
"positionsStream": "system:gps:positions",
|
||||||
|
"streamMaxLen": 100000
|
||||||
|
},
|
||||||
|
"agentVectorChangeChannel": "arena:agents:*",
|
||||||
|
"collisionsChannel": "arena:agents:[UID]",
|
||||||
|
"lifecycle": {
|
||||||
|
"arenaChannel": "arena:lifecycle",
|
||||||
|
"godsReadyChannel": "arena:gods:ready"
|
||||||
|
},
|
||||||
|
"arenaStorage": {
|
||||||
|
"agentHashKey": "arena:agents:[UID]",
|
||||||
|
"agentsIndexKey": "arena:agents"
|
||||||
|
},
|
||||||
|
"senderId": "gps",
|
||||||
|
"nearMissDistance": 1,
|
||||||
|
"prismTimeHeight": 60,
|
||||||
|
"collisionTickMs": 100,
|
||||||
|
"prismRefreshLeadSeconds": 1
|
||||||
|
},
|
||||||
|
"maestro": {
|
||||||
|
"maestroActionsChannel": "system:requests:maestro",
|
||||||
|
"maestroActionsReply": "system:replies:[UID]",
|
||||||
|
"senderId": "maestro",
|
||||||
|
"lifecycle": {
|
||||||
|
"arenaChannel": "arena:lifecycle",
|
||||||
|
"godsReadyChannel": "arena:gods:ready"
|
||||||
|
},
|
||||||
|
"readyTimeoutMs": 30000
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"socketPath": "/var/run/mysqld/mysqld.sock",
|
||||||
|
"guiDatabase": "test_p42GUI",
|
||||||
|
"simDatabase": "test_p42SIM"
|
||||||
|
},
|
||||||
|
"observer": {
|
||||||
|
"primordialDaemon": false,
|
||||||
|
"observerActionsChannel": "system:requests:observer",
|
||||||
|
"observerActionsReply": "system:replies:[UID]",
|
||||||
|
"senderId": "observer",
|
||||||
|
"scanIntervalMs": 300,
|
||||||
|
"lifecycle": {
|
||||||
|
"arenaChannel": "arena:lifecycle",
|
||||||
|
"godsReadyChannel": "arena:gods:ready"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systemMesh": {
|
||||||
|
"redis": [
|
||||||
|
{
|
||||||
|
"redisId": "SYS_1",
|
||||||
|
"role": "primary",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"tls": false,
|
||||||
|
"port": 6380,
|
||||||
|
"user": "",
|
||||||
|
"pass": "",
|
||||||
|
"chansNamespace": "system:",
|
||||||
|
"basePrefix": "messageBus:"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"arenaMesh": {
|
||||||
|
"redis": [
|
||||||
|
{
|
||||||
|
"redisId": "ARN_1",
|
||||||
|
"role": "primary",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"tls": false,
|
||||||
|
"port": 6379,
|
||||||
|
"user": "",
|
||||||
|
"pass": "",
|
||||||
|
"chansNamespace": "arena:",
|
||||||
|
"basePrefix": "messageBus:"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# resolveConfigPath BASE PATH
|
||||||
|
# Turn PATH into an absolute path; relative segments are resolved from BASE.
|
||||||
|
resolveConfigPath() {
|
||||||
|
_base=$1
|
||||||
|
_path=$2
|
||||||
|
|
||||||
|
case "$_path" in
|
||||||
|
/*)
|
||||||
|
printf '%s\n' "$_path"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_dir=$(dirname "$_path")
|
||||||
|
_name=$(basename "$_path")
|
||||||
|
if [ "$_dir" = . ]; then
|
||||||
|
printf '%s\n' "$_base/$_name"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$(cd "$_base/$_dir" && pwd)/$_name"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
Executable
+75
@@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
GOD_FOLDERS="Maestro GPS Observer"
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# shellcheck source=lib/resolveConfigPath.sh
|
||||||
|
. "$ROOT/lib/resolveConfigPath.sh"
|
||||||
|
|
||||||
|
CONFIG="config.json"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $(basename "$0") [-c|--config PATH]" >&2
|
||||||
|
echo " PATH is relative to $ROOT unless absolute." >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-c|--config)
|
||||||
|
if [ -z "${2:-}" ]; then
|
||||||
|
echo "Missing value for $1" >&2
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
CONFIG="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
CONFIG="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
CONFIG="$(resolveConfigPath "$ROOT" "$CONFIG")"
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG" ]; then
|
||||||
|
echo "Config file not found: $CONFIG" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
failed=0
|
||||||
|
|
||||||
|
for folder in $GOD_FOLDERS; do
|
||||||
|
dir="$ROOT/$folder"
|
||||||
|
if [ ! -d "$dir" ]; then
|
||||||
|
echo "Missing daemon folder: $dir" >&2
|
||||||
|
failed=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
scripts=("$dir"/start*.sh)
|
||||||
|
shopt -u nullglob
|
||||||
|
|
||||||
|
if [ ${#scripts[@]} -eq 0 ]; then
|
||||||
|
echo "No start script in $dir" >&2
|
||||||
|
failed=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ ${#scripts[@]} -gt 1 ]; then
|
||||||
|
echo "Multiple start scripts in $dir, using ${scripts[0]}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Starting $folder (config=$CONFIG) ==="
|
||||||
|
(cd "$dir" && bash "${scripts[0]}" "$CONFIG") || {
|
||||||
|
echo "Failed to start $folder" >&2
|
||||||
|
failed=1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $failed
|
||||||
Executable
+38
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
GOD_FOLDERS="Maestro GPS Observer"
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
failed=0
|
||||||
|
|
||||||
|
read -ra folders <<< "$GOD_FOLDERS"
|
||||||
|
for((i=${#folders[@]}-1; i>=0; i--)); do
|
||||||
|
folder="${folders[i]}"
|
||||||
|
dir="$ROOT/$folder"
|
||||||
|
if [ ! -d "$dir" ]; then
|
||||||
|
echo "Missing daemon folder: $dir" >&2
|
||||||
|
failed=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
scripts=("$dir"/stop*.sh)
|
||||||
|
shopt -u nullglob
|
||||||
|
|
||||||
|
if [ ${#scripts[@]} -eq 0 ]; then
|
||||||
|
echo "No stop script in $dir" >&2
|
||||||
|
failed=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ ${#scripts[@]} -gt 1 ]; then
|
||||||
|
echo "Multiple stop scripts in $dir, using ${scripts[0]}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Stopping $folder ==="
|
||||||
|
(cd "$dir" && bash "${scripts[0]}") || {
|
||||||
|
echo "Failed to stop $folder" >&2
|
||||||
|
failed=1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $failed
|
||||||
+10
-3
@@ -1,4 +1,11 @@
|
|||||||
clear; node test.js --guiDatabase test_p42GUI --simDatabase test_p42SIM maestro1 --userUuid a4f33373-6adf-4d2d-9a6d-7fa0abf8b01f --simulationUuid 0x019ec742e12175c685a97bf9300b6b49
|
# Test DBs: point all gods at the same config (or edit config.json mysql section).
|
||||||
|
# Example:
|
||||||
|
# ./startAllGods.sh --config /opt/p42GodDaemons/config.json
|
||||||
|
# ./Maestro/startMaestro.sh /opt/p42GodDaemons/config.json
|
||||||
|
|
||||||
|
clear; node test.js maestro1 \
|
||||||
|
--config ../config.json \
|
||||||
|
--guiDatabase test_p42GUI --simDatabase test_p42SIM \
|
||||||
|
--fakeAgentsReady --fakeGpsReady \
|
||||||
|
--userUuid a4f33373-6adf-4d2d-9a6d-7fa0abf8b01f \
|
||||||
|
--simulationUuid 0x019ec742e12175c685a97bf9300b6b49
|
||||||
|
|||||||
+78
-11
@@ -64,6 +64,54 @@ async function findSimulationFixture(ctx) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function godsReadyChannel(config) {
|
||||||
|
return(config.maestro?.lifecycle?.godsReadyChannel
|
||||||
|
?? config.gps?.lifecycle?.godsReadyChannel
|
||||||
|
?? 'arena:gods:ready')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function publishFakeReadyToStart(ctx, { sender, simulationId, agentIds }) {
|
||||||
|
const { arenaCnx } = ctx
|
||||||
|
const payload = {
|
||||||
|
success: true,
|
||||||
|
simulationId,
|
||||||
|
err: null,
|
||||||
|
}
|
||||||
|
if(agentIds) payload.agentIds = agentIds
|
||||||
|
|
||||||
|
await arenaCnx.redisPublish(godsReadyChannel(ctx.config), {
|
||||||
|
eventType: 'readyToStart',
|
||||||
|
sender,
|
||||||
|
payload,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function publishFakeReadies(ctx, simulationId, agentIds) {
|
||||||
|
const { argv, config, log } = ctx
|
||||||
|
|
||||||
|
if(argv.fakeGpsReady) {
|
||||||
|
const senderId = config.gps?.senderId ?? 'gps'
|
||||||
|
log('action', `Faking GPS readyToStart (sender=${senderId})...`)
|
||||||
|
await publishFakeReadyToStart(ctx, {
|
||||||
|
sender: senderId,
|
||||||
|
simulationId,
|
||||||
|
agentIds,
|
||||||
|
})
|
||||||
|
log('success', 'Published fake GPS readyToStart')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argv.fakeAgentsReady) {
|
||||||
|
log('action', `Faking readyToStart for ${agentIds.length} agent(s)...`)
|
||||||
|
for(const agentId of agentIds) {
|
||||||
|
await publishFakeReadyToStart(ctx, {
|
||||||
|
sender: agentId,
|
||||||
|
simulationId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
log('success', `Published fake readyToStart for ${agentIds.length} agent(s)`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function waitForLifecycleEvent(ctx, eventType, timeoutMs) {
|
function waitForLifecycleEvent(ctx, eventType, timeoutMs) {
|
||||||
return(new Promise((resolve, reject) => {
|
return(new Promise((resolve, reject) => {
|
||||||
const lifecyclePattern = ctx.config.maestro.lifecycle.arenaChannel
|
const lifecyclePattern = ctx.config.maestro.lifecycle.arenaChannel
|
||||||
@@ -99,6 +147,16 @@ export function configureYargs(yargsBuilder) {
|
|||||||
default: 15000,
|
default: 15000,
|
||||||
type: 'number',
|
type: 'number',
|
||||||
},
|
},
|
||||||
|
fakeAgentsReady: {
|
||||||
|
describe: 'After onYourMarks, publish fake readyToStart for each seeded agent',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
fakeGpsReady: {
|
||||||
|
describe: 'After onYourMarks, publish fake GPS readyToStart',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,24 +221,29 @@ export async function run(ctx) {
|
|||||||
|
|
||||||
log('success', `Received onYourMarks for simulationId=${payload.simulationId}`)
|
log('success', `Received onYourMarks for simulationId=${payload.simulationId}`)
|
||||||
|
|
||||||
log('action', 'Reading arena store...')
|
const expectedIds = [...expectedById.keys()]
|
||||||
const indexIds = await arenaCnx.redisSmembers(arenaStorage.agentsIndexKey)
|
if(argv.fakeAgentsReady || argv.fakeGpsReady) {
|
||||||
const expectedIds = [...expectedById.keys()].sort()
|
await publishFakeReadies(ctx, payload.simulationId, expectedIds)
|
||||||
const actualIds = [...indexIds].sort()
|
|
||||||
|
|
||||||
if(actualIds.length !== expectedIds.length) {
|
|
||||||
throw(new Error(`Agent index count mismatch: expected ${expectedIds.length}, got ${actualIds.length}`))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let i = 0; i < expectedIds.length; i++) {
|
log('action', 'Reading arena store...')
|
||||||
if(actualIds[i] !== expectedIds[i]) {
|
const indexIds = await arenaCnx.redisSmembers(arenaStorage.agentsIndexKey)
|
||||||
throw(new Error(`Agent index mismatch at ${i}: expected ${expectedIds[i]}, got ${actualIds[i]}`))
|
const sortedExpectedIds = [...expectedIds].sort()
|
||||||
|
const actualIds = [...indexIds].sort()
|
||||||
|
|
||||||
|
if(actualIds.length !== sortedExpectedIds.length) {
|
||||||
|
throw(new Error(`Agent index count mismatch: expected ${sortedExpectedIds.length}, got ${actualIds.length}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let i = 0; i < sortedExpectedIds.length; i++) {
|
||||||
|
if(actualIds[i] !== sortedExpectedIds[i]) {
|
||||||
|
throw(new Error(`Agent index mismatch at ${i}: expected ${sortedExpectedIds[i]}, got ${actualIds[i]}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log('success', `Arena agents index contains ${actualIds.length} agent(s)`)
|
log('success', `Arena agents index contains ${actualIds.length} agent(s)`)
|
||||||
|
|
||||||
for(const agentId of expectedIds) {
|
for(const agentId of sortedExpectedIds) {
|
||||||
const key = agentHashKey(arenaStorage.agentHashKey, agentId)
|
const key = agentHashKey(arenaStorage.agentHashKey, agentId)
|
||||||
const hash = await arenaCnx.redisHgetall(key)
|
const hash = await arenaCnx.redisHgetall(key)
|
||||||
const expected = expectedById.get(agentId)
|
const expected = expectedById.get(agentId)
|
||||||
@@ -218,5 +281,9 @@ export async function run(ctx) {
|
|||||||
log('success', `Agent ${agentId}: position, vector, and store values match MySQL`)
|
log('success', `Agent ${agentId}: position, vector, and store values match MySQL`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(argv.fakeAgentsReady || argv.fakeGpsReady) {
|
||||||
|
log('success', 'Arena store seeded correctly from MySQL; fake prepare acks published')
|
||||||
|
} else {
|
||||||
log('success', 'Arena store seeded correctly from MySQL (Maestro will wait for agent + primordial daemon readyToStart until timeout)')
|
log('success', 'Arena store seeded correctly from MySQL (Maestro will wait for agent + primordial daemon readyToStart until timeout)')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user