fix(shadow): align outbound predicates with site data for v3.3
Use the business project and captured site predicates, validate single-stock proposals, and skip unsupported scopes without changing Legacy. Add the guarded V3.3 SQL upgrade, CMD operations, regression tests and deployment runbook.
This commit is contained in:
@@ -9,24 +9,32 @@ set "SQL_SERVER=%~1"
|
||||
set "DATABASE=%~2"
|
||||
set "MODE=%~3"
|
||||
set "SQL_FILE="
|
||||
set "V33_FILE=%~dp0..\fortucky-algorithm\src\main\resources\db\sqlserver\upgrade-shadow-v3-to-v33.sql"
|
||||
|
||||
if /I "%~3"=="upgrade" set "SQL_FILE=%~dp0..\fortucky-algorithm\src\main\resources\db\sqlserver\upgrade-shadow-v2-to-v3.sql"
|
||||
if /I "%~3"=="clean" set "SQL_FILE=%~dp0..\fortucky-algorithm\src\main\resources\db\sqlserver\install-shadow.sql"
|
||||
if not defined SQL_FILE (call :fail "mode must be upgrade or clean" & exit /b 1)
|
||||
if /I "%~3"=="v33" set "SQL_FILE=%V33_FILE%"
|
||||
if not defined SQL_FILE (call :fail "mode must be upgrade, clean or v33" & exit /b 1)
|
||||
if not exist "%SQL_FILE%" (call :fail "SQL package file is missing" & exit /b 1)
|
||||
if not exist "%V33_FILE%" (call :fail "V3.3 SQL package file is missing" & exit /b 1)
|
||||
|
||||
where sqlcmd >nul 2>nul
|
||||
if errorlevel 1 (call :fail "sqlcmd is not available on PATH" & exit /b 1)
|
||||
|
||||
echo Installing FT546WMS shadow v3 in %MODE% mode...
|
||||
echo WARNING: stop the WMS shadow-enabled JVM and wait over 120 seconds first.
|
||||
echo Installing FT546WMS shadow V3.3 in %MODE% mode...
|
||||
sqlcmd -S "%SQL_SERVER%" -d "%DATABASE%" -E -b -r1 -i "%SQL_FILE%"
|
||||
if errorlevel 1 exit /b 1
|
||||
if /I "%MODE%"=="v33" goto :installed
|
||||
sqlcmd -S "%SQL_SERVER%" -d "%DATABASE%" -E -b -r1 -i "%V33_FILE%"
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
:installed
|
||||
echo INSTALL_OK mode=%MODE%
|
||||
exit /b 0
|
||||
|
||||
:usage
|
||||
echo Usage: %~nx0 SQL_SERVER DATABASE upgrade^|clean 1>&2
|
||||
echo Usage: %~nx0 SQL_SERVER DATABASE upgrade^|clean^|v33 1>&2
|
||||
exit /b 2
|
||||
|
||||
:fail
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@echo off
|
||||
setlocal EnableExtensions DisableDelayedExpansion
|
||||
set "PREFLIGHT_PUSHED="
|
||||
|
||||
if "%~1"=="" goto :usage
|
||||
if "%~2"=="" goto :usage
|
||||
@@ -23,6 +24,7 @@ if not exist "%REPO_ROOT%\.git" (call :fail "REPO_ROOT is not a Git repository"
|
||||
|
||||
pushd "%REPO_ROOT%" >nul
|
||||
if errorlevel 1 (call :fail "cannot enter REPO_ROOT" & exit /b 1)
|
||||
set "PREFLIGHT_PUSHED=1"
|
||||
|
||||
git rev-parse --is-inside-work-tree >nul 2>nul
|
||||
if errorlevel 1 (call :fail "REPO_ROOT is not a Git worktree" & exit /b 1)
|
||||
@@ -42,6 +44,7 @@ if defined DIRTY (call :fail "Git worktree is not clean" & exit /b 1)
|
||||
git merge-base --is-ancestor %MAIN_COMMIT% HEAD
|
||||
if errorlevel 1 (call :fail "required main commit is not an ancestor" & exit /b 1)
|
||||
popd >nul
|
||||
set "PREFLIGHT_PUSHED="
|
||||
|
||||
set "WMS_PROCESS_COUNT=0"
|
||||
jps -lv >nul 2>nul
|
||||
@@ -49,7 +52,7 @@ if errorlevel 1 (call :fail "jps could not inspect running JVMs" & exit /b 1)
|
||||
for /f %%I in ('jps -lv 2^>nul ^| findstr /R /I /C:"^[0-9][0-9]* com\.ruoyi\.RuoYiApplication" ^| find /C /V ""') do set "WMS_PROCESS_COUNT=%%I"
|
||||
if %WMS_PROCESS_COUNT% GTR 1 (call :fail "more than one FT546WMS JVM is running" & exit /b 1)
|
||||
|
||||
set "PREFLIGHT_SQL=SET NOCOUNT ON; IF SCHEMA_ID(N'alg') IS NULL SELECT N'CLEAN_INSTALL_ELIGIBLE' AS package_state; ELSE BEGIN IF OBJECT_ID(N'alg.shadow_package_manifest', N'U') IS NULL BEGIN; THROW 51050, 'shadow manifest is missing', 1; END; IF NOT EXISTS (SELECT 1 FROM alg.shadow_package_manifest WHERE package_id='FT546WMS_SHADOW_ONLY' AND package_version IN ('2026-08-12-1','2026-09-03-3')) BEGIN; THROW 51051, 'shadow manifest is not a supported version', 1; END; IF EXISTS (SELECT 1 FROM alg.shadow_package_manifest WHERE package_id='FT546WMS_SHADOW_ONLY' AND package_version='2026-09-03-3') BEGIN IF OBJECT_ID(N'alg.shadow_snapshot_state', N'U') IS NULL BEGIN; THROW 51052, 'snapshot state is missing', 1; END; IF OBJECT_ID(N'alg.shadow_instance_heartbeat', N'U') IS NULL BEGIN; THROW 51055, 'shadow instance heartbeat is missing', 1; END; IF NOT EXISTS (SELECT 1 FROM alg.shadow_snapshot_state WHERE warehouse_id='01' AND snapshot_generation>0 AND snapshot_status='PUBLISHED' AND synchronized_at IS NOT NULL AND DATEDIFF(SECOND,synchronized_at,SYSUTCDATETIME()) BETWEEN 0 AND 300 AND source_signature IS NOT NULL AND last_error IS NULL) BEGIN; THROW 51053, 'published warehouse 01 snapshot is unusable', 1; END; IF EXISTS (SELECT 1 FROM alg.shadow_instance_heartbeat WHERE warehouse_id='01' AND ((DATEDIFF(SECOND,last_seen_at,SYSUTCDATETIME()) BETWEEN 0 AND 120) OR (DATEDIFF(SECOND,claimed_at,SYSUTCDATETIME()) BETWEEN 0 AND 120))) BEGIN; THROW 51054, 'a recent shadow instance heartbeat or claim exists', 1; END; END; SELECT package_id, package_version, installed_at FROM alg.shadow_package_manifest; IF OBJECT_ID(N'alg.shadow_snapshot_state', N'U') IS NOT NULL SELECT warehouse_id, snapshot_generation, snapshot_status, synchronized_at, CONVERT(varchar(64), source_signature, 2) AS source_signature, last_error FROM alg.shadow_snapshot_state; END"
|
||||
set "PREFLIGHT_SQL=SET NOCOUNT ON; IF SCHEMA_ID(N'alg') IS NULL SELECT N'CLEAN_INSTALL_ELIGIBLE' AS package_state; ELSE BEGIN IF OBJECT_ID(N'alg.shadow_package_manifest', N'U') IS NULL BEGIN; THROW 51050, 'shadow manifest is missing', 1; END; IF (SELECT COUNT(*) FROM alg.shadow_package_manifest) <> 1 OR NOT EXISTS (SELECT 1 FROM alg.shadow_package_manifest WHERE package_id='FT546WMS_SHADOW_ONLY' AND package_version IN ('2026-08-12-1','2026-09-03-3','2026-09-07-33')) BEGIN; THROW 51051, 'shadow manifest is not a supported version', 1; END; IF EXISTS (SELECT 1 FROM alg.shadow_package_manifest WHERE package_id='FT546WMS_SHADOW_ONLY' AND package_version IN ('2026-09-03-3','2026-09-07-33')) BEGIN IF OBJECT_ID(N'alg.shadow_snapshot_state', N'U') IS NULL BEGIN; THROW 51052, 'snapshot state is missing', 1; END; IF OBJECT_ID(N'alg.shadow_instance_heartbeat', N'U') IS NULL BEGIN; THROW 51055, 'shadow instance heartbeat is missing', 1; END; IF NOT EXISTS (SELECT 1 FROM alg.shadow_snapshot_state WHERE warehouse_id='01' AND snapshot_generation>0 AND snapshot_status='PUBLISHED' AND synchronized_at IS NOT NULL AND DATEDIFF(SECOND,synchronized_at,SYSUTCDATETIME()) BETWEEN 0 AND 300 AND source_signature IS NOT NULL AND last_error IS NULL) BEGIN; THROW 51053, 'published warehouse 01 snapshot is unusable', 1; END; IF EXISTS (SELECT 1 FROM alg.shadow_instance_heartbeat WHERE warehouse_id='01' AND ((DATEDIFF(SECOND,last_seen_at,SYSUTCDATETIME()) BETWEEN 0 AND 120) OR (DATEDIFF(SECOND,claimed_at,SYSUTCDATETIME()) BETWEEN 0 AND 120))) BEGIN; THROW 51054, 'a recent shadow instance heartbeat or claim exists', 1; END; END; SELECT package_id, package_version, installed_at FROM alg.shadow_package_manifest; IF OBJECT_ID(N'alg.shadow_snapshot_state', N'U') IS NOT NULL SELECT warehouse_id, snapshot_generation, snapshot_status, synchronized_at, CONVERT(varchar(64), source_signature, 2) AS source_signature, last_error FROM alg.shadow_snapshot_state; END"
|
||||
sqlcmd -S "%SQL_SERVER%" -d "%DATABASE%" -E -b -r1 -Q "%PREFLIGHT_SQL%"
|
||||
if errorlevel 1 (call :fail "SQL connectivity or shadow package validation failed" & exit /b 1)
|
||||
|
||||
@@ -62,5 +65,5 @@ exit /b 2
|
||||
|
||||
:fail
|
||||
echo PREFLIGHT_FAILED %~1 1>&2
|
||||
popd >nul 2>nul
|
||||
if defined PREFLIGHT_PUSHED popd >nul 2>nul
|
||||
exit /b 1
|
||||
|
||||
@@ -15,7 +15,7 @@ where sqlcmd >nul 2>nul
|
||||
if errorlevel 1 (call :fail "sqlcmd is not available on PATH" & exit /b 1)
|
||||
|
||||
echo WARNING: export all alg.* evidence before uninstalling.
|
||||
echo The shadow application must be stopped and the stable service restored first.
|
||||
echo The shadow-enabled WMS must be stopped and the stable WMS instance restored first.
|
||||
sqlcmd -S "%SQL_SERVER%" -d "%DATABASE%" -E -b -r1 -i "%SQL_FILE%"
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user