test(order): verify warehouse faults and await recovery projection

This commit is contained in:
2026-10-04 00:04:36 +08:00
parent 3f6083ff02
commit e8cf5e70ba
8 changed files with 229 additions and 51 deletions
@@ -24,8 +24,10 @@ from pathlib import Path
ORDER = 'firstleg-test-order'
ENTRYPOINT = ['sh', '-c', 'exec java $JAVA_OPTS org.springframework.boot.loader.launch.JarLauncher']
PROPERTIES = {'IAM': 'baiyue.clients.iam.url', 'FINANCE': 'baiyue.clients.finance.url'}
UPSTREAM_CONTAINERS = {'IAM': 'firstleg-test-iam', 'FINANCE': 'firstleg-test-finance'}
PROPERTIES = {'IAM': 'baiyue.clients.iam.url', 'FINANCE': 'baiyue.clients.finance.url',
'WAREHOUSE': 'baiyue.clients.warehouse.url'}
UPSTREAM_CONTAINERS = {'IAM': 'firstleg-test-iam', 'FINANCE': 'firstleg-test-finance',
'WAREHOUSE': 'firstleg-test-warehouse'}
class NoRedirect(urllib.request.HTTPRedirectHandler):
@@ -63,10 +65,12 @@ def private_write(path, value):
def validate_scope(scope):
if set(scope) != {'marker', 'customerId', 'orderIds', 'planSha256'} or not re.fullmatch(r'[A-Za-z0-9_-]{1,80}', scope['marker']):
if set(scope) != {'marker', 'customerId', 'receivingWarehouseId', 'orderIds', 'planSha256'} or not re.fullmatch(r'[A-Za-z0-9_-]{1,80}', scope['marker']):
raise RuntimeError('INVALID_SCOPE')
if not re.fullmatch(r'[1-9][0-9]{0,19}', scope['customerId']) or set(scope['orderIds']) != {'merchant', 'platform'}:
raise RuntimeError('INVALID_SCOPE')
if not re.fullmatch(r'[1-9][0-9]{0,19}', scope['receivingWarehouseId']):
raise RuntimeError('INVALID_RECEIVING_WAREHOUSE')
if any(not re.fullmatch(r'[1-9][0-9]{0,19}', value) for value in scope['orderIds'].values()) or len(set(scope['orderIds'].values())) != 2:
raise RuntimeError('TWO_DISTINCT_ORDERS_REQUIRED')
if not re.fullmatch(r'[0-9a-f]{64}', scope['planSha256']): raise RuntimeError('INVALID_PLAN_HASH')
@@ -125,7 +129,8 @@ class Runtime:
"""Real authenticated reads, not manufactured business responses. No body/secret is returned."""
customer = self.scope['customerId']; results = {}
targets = {'IAM': '/internal/iam/tenants/' + customer + '/order-eligibility',
'FINANCE': '/internal/finance/v1/wallet/accounts/' + customer}
'FINANCE': '/internal/finance/v1/wallet/accounts/' + customer,
'WAREHOUSE': '/internal/warehouses/0/' + self.scope['receivingWarehouseId'] + '/active'}
for dependency, path in targets.items():
req = urllib.request.Request(state['upstreams'][dependency] + path,
headers={'X-Internal-Service-Token': state['internalToken']})
@@ -136,6 +141,12 @@ class Runtime:
if dependency == 'IAM' and data.get('eligible') is not True: raise RuntimeError('CUSTOMER_NOT_ELIGIBLE')
if dependency == 'FINANCE' and (data.get('actualBalance') is None or float(data['actualBalance']) < 0):
raise RuntimeError('CUSTOMER_BALANCE_NOT_READY')
if dependency == 'WAREHOUSE':
warehouse = data.get('warehouse') or {}
if (str(warehouse.get('id')) != self.scope['receivingWarehouseId']
or str(warehouse.get('tenantId')) != '0' or warehouse.get('status') != 'ACTIVE'
or warehouse.get('warehouseType') != 'DOMESTIC' or not warehouse.get('warehouseName')):
raise RuntimeError('RECEIVING_WAREHOUSE_NOT_READY')
results[dependency] = True
return results
@@ -229,8 +240,9 @@ class Runtime:
proxy = self.directory / 'proxy.py'; proxy.write_bytes(base64.b64decode(config['proxySource'])); os.chmod(proxy, 0o600)
private_write(self.directory / 'proxy-config.json', {k: state[k] for k in
['internalToken', 'controlToken', 'proxyPort', 'controlPort', 'upstreams', 'orderIps']} | {'customerId': self.scope['customerId'],
'receivingWarehouseId': self.scope['receivingWarehouseId'],
'requestIds': ['dep-' + self.scope['marker'] + '-' + dependency + '-' + role
for dependency in ('IAM', 'FINANCE') for role in ('merchant', 'platform')]})
for dependency in PROPERTIES for role in ('merchant', 'platform')]})
state['phase'] = 'PROXY_START_INTENT'; state['proxyLaunchIntent'] = True; self.save(state)
with open(self.directory / 'proxy-output.log', 'ab') as output:
os.chmod(self.directory / 'proxy-output.log', 0o600)
@@ -361,7 +373,7 @@ class Runtime:
if self.config_fingerprint(current, state['routing']) != state['routingSourceSha256']:
raise RuntimeError('NACOS_ROUTE_CONFIGURATION_CHANGED')
checks = self.probes(state)
if checks != {'IAM': True, 'FINANCE': True}: raise RuntimeError('RESTORED_ROUTE_PROBE_INVALID')
if checks != {dependency: True for dependency in PROPERTIES}: raise RuntimeError('RESTORED_ROUTE_PROBE_INVALID')
state['routeReadsVerified'] = checks; self.save(state)
return {'healthy': True, 'originalFingerprint': state['originalFingerprint'], 'currentFingerprint': self.tools['fingerprint'](current),
'originalImageId': state['originalImageId'], 'currentImageId': current['Image'], 'upstreamReads': checks,