fix: register current synchronous service dependencies and guard callback boundaries

This commit is contained in:
2026-10-12 20:58:16 +08:00
parent d782b2cd24
commit d4dc4f875a
2 changed files with 84 additions and 16 deletions
@@ -33,6 +33,7 @@ const expectedOnlineEdges = [
'iam-service->warehouse-service',
'lastleg-service->file-service',
'lastleg-service->finance-service',
'lastleg-service->firstleg-service',
'lastleg-service->iam-service',
'lastleg-service->print-service',
'lastleg-service->warehouse-overseas-service',
@@ -41,12 +42,15 @@ const expectedOnlineEdges = [
'order-service->finance-service',
'order-service->firstleg-service',
'order-service->iam-service',
'order-service->lastleg-service',
'order-service->warehouse-service',
'warehouse-overseas-service->print-service',
'warehouse-overseas-service->warehouse-service'
]
const expectedBackgroundEdges = [
'integration-service->lastleg-service',
'lastleg-service->integration-service',
'file-service->finance-service',
'file-service->firstleg-service',
'file-service->iam-service',
@@ -103,7 +107,7 @@ test('all Feign clients have reviewed context, access and idempotency metadata',
const reviewed = SYNCHRONOUS_CLIENTS.filter(client => client.transport === 'FEIGN')
.map(({ path, source, target }) => ({ path, source, target }))
.sort((left, right) => left.path.localeCompare(right.path))
assert.equal(reviewed.length, 72)
assert.equal(reviewed.length, 77)
assert.deepEqual(await discoverFeignEdges(), reviewed)
})
@@ -119,7 +123,7 @@ test('all raw HTTP transports have reviewed context, access and idempotency meta
}
const reviewed = SYNCHRONOUS_CLIENTS.filter(client => client.transport === 'HTTP')
.map(client => client.path).sort()
assert.equal(reviewed.length, 25)
assert.equal(reviewed.length, 28)
assert.deepEqual(discovered.sort(), reviewed)
})
@@ -194,14 +198,14 @@ test('REQUEST, BACKGROUND and full graphs remain separate executable baselines',
])
assert.deepEqual(stronglyConnectedComponents(graphEdges('REQUEST')), [
['auth-service', 'iam-service'],
['finance-service', 'firstleg-service', 'order-service']
['finance-service', 'firstleg-service', 'lastleg-service', 'order-service']
])
assert.deepEqual(stronglyConnectedComponents(graphEdges('BACKGROUND')), [[
'finance-service', 'firstleg-service', 'lastleg-service', 'order-service'
'finance-service', 'firstleg-service', 'integration-service', 'lastleg-service', 'order-service'
]])
assert.deepEqual(stronglyConnectedComponents(graphEdges('ALL')), [[
'auth-service', 'file-service', 'finance-service',
'firstleg-service', 'iam-service', 'lastleg-service', 'order-service'
'firstleg-service', 'iam-service', 'integration-service', 'lastleg-service', 'order-service'
]])
})
@@ -222,7 +226,7 @@ test('unified authority checks remain infrastructure edges and direct events rem
assert.ok(!SYNCHRONOUS_CLIENTS.some(client => ['event-bridge-service','gateway-overseas'].includes(client.source) || ['event-bridge-service','gateway-overseas'].includes(client.target)))
})
test('Order, Firstleg and Finance form the reviewed REQUEST SCC', () => {
test('Order, Firstleg, Finance and Lastleg form the reviewed REQUEST SCC', () => {
const requestClients = SYNCHRONOUS_CLIENTS.filter(client => client.contexts.includes('REQUEST'))
const orderToFirstleg = requestClients.filter(client =>
client.source === 'order-service' && client.target === 'firstleg-service')
@@ -260,17 +264,17 @@ test('known user entries expose every longest simple REQUEST path over the two-h
'iam-service->auth-service',
'iam-service->warehouse-service'
] },
'order-service': { hops: 5, paths: [
'order-service->finance-service->firstleg-service->file-service->iam-service->auth-service',
'order-service->finance-service->firstleg-service->file-service->iam-service->warehouse-service'
'order-service': { hops: 6, paths: [
'order-service->lastleg-service->finance-service->firstleg-service->file-service->iam-service->auth-service',
'order-service->lastleg-service->finance-service->firstleg-service->file-service->iam-service->warehouse-service'
] },
'firstleg-service': { hops: 5, paths: [
'firstleg-service->order-service->finance-service->file-service->iam-service->auth-service',
'firstleg-service->order-service->finance-service->file-service->iam-service->warehouse-service'
'firstleg-service': { hops: 6, paths: [
'firstleg-service->order-service->lastleg-service->finance-service->file-service->iam-service->auth-service',
'firstleg-service->order-service->lastleg-service->finance-service->file-service->iam-service->warehouse-service'
] },
'finance-service': { hops: 5, paths: [
'finance-service->firstleg-service->order-service->file-service->iam-service->auth-service',
'finance-service->firstleg-service->order-service->file-service->iam-service->warehouse-service'
'finance-service': { hops: 6, paths: [
'finance-service->firstleg-service->order-service->lastleg-service->file-service->iam-service->auth-service',
'finance-service->firstleg-service->order-service->lastleg-service->file-service->iam-service->warehouse-service'
] },
'file-service': { hops: 2, paths: [
'file-service->iam-service->auth-service',
@@ -278,7 +282,9 @@ test('known user entries expose every longest simple REQUEST path over the two-h
] },
'lastleg-service': { hops: 6, paths: [
'lastleg-service->finance-service->firstleg-service->order-service->file-service->iam-service->auth-service',
'lastleg-service->finance-service->firstleg-service->order-service->file-service->iam-service->warehouse-service'
'lastleg-service->finance-service->firstleg-service->order-service->file-service->iam-service->warehouse-service',
'lastleg-service->firstleg-service->order-service->finance-service->file-service->iam-service->auth-service',
'lastleg-service->firstleg-service->order-service->finance-service->file-service->iam-service->warehouse-service'
] },
'warehouse-service': { hops: 0, paths: ['warehouse-service'] },
'warehouse-overseas-service': { hops: 1, paths: [
@@ -292,6 +298,44 @@ test('known user entries expose every longest simple REQUEST path over the two-h
}
})
test('self-operated collection and quota callbacks stay outside the REQUEST graph', async () => {
const find = suffix => SYNCHRONOUS_CLIENTS.find(client => client.path.endsWith(suffix))
const collection = find('/selfoperated/analytics/client/RestLingxingAnalyticsClient.java')
const authority = find('/provider/lingxing/LingxingHttpBudgetAuthority.java')
const supplier = find('/provider/lingxing/LingxingWmsClient.java')
assert.deepEqual([collection.contexts, collection.access, collection.idempotency], [['BACKGROUND'], 'READ', 'NONE'])
assert.deepEqual([authority.contexts, authority.access, authority.idempotency], [['BACKGROUND'], 'READ_WRITE', 'MIXED'])
assert.deepEqual([supplier.contexts, supplier.access, supplier.idempotency], [['EXTERNAL'], 'READ', 'NONE'])
assert.equal(graphEdges('REQUEST').includes('lastleg-service->integration-service'), false)
assert.equal(graphEdges('REQUEST').includes('integration-service->lastleg-service'), false)
// The background service graph is bidirectional; the permit callback must not re-enter collection.
const egress = await readFile(path.join(root,
'lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/request/SelfopEgressService.java'), 'utf8')
assert.doesNotMatch(egress, /RestLingxingAnalyticsClient|LingxingAnalyticsClient|SelfopExecutionService/)
const callback = await readFile(path.join(root, authority.path), 'utf8')
assert.match(callback, /followRedirects\(HttpClient\.Redirect\.NEVER\)/)
assert.match(callback, /timeout\(Duration\.ofSeconds\(5\)\)/)
assert.doesNotMatch(callback, /RetryTemplate|Retryer|@Retryable|\.retry\(/)
})
test('new domain reference clients are exact readonly internal dependencies', async () => {
const reviewed = [
['lastleg-service/src/main/java/com/baiyue/lastleg/appointmentplanning/AppointmentForecastClient.java', 'firstleg-service', '/internal/firstleg/appointment-forecasts/batch'],
['lastleg-service/src/main/java/com/baiyue/lastleg/appointmentplanning/AppointmentWarehouseClient.java', 'warehouse-service', '/internal/warehouses/order-catalog'],
['lastleg-service/src/main/java/com/baiyue/lastleg/service/reference/ReturnCustomerReferenceClient.java', 'iam-service', '/internal/iam/finance-customers'],
['lastleg-service/src/main/java/com/baiyue/lastleg/transfer/gateway/TransferWarehouseCatalogClient.java', 'warehouse-service', '/internal/warehouses/order-catalog'],
['order/src/main/java/com/baiyue/order/client/LastlegOrderProgressClient.java', 'lastleg-service', '/internal/lastleg/v1/customer-order-progress']
]
for (const [file, target, endpoint] of reviewed) {
const client = SYNCHRONOUS_CLIENTS.find(row => row.path === file)
assert.deepEqual([client.target, client.contexts, client.access, client.idempotency], [target, ['REQUEST'], 'READ', 'SAFE_READ'])
const source = await readFile(path.join(root, file), 'utf8')
assert.ok(source.includes(endpoint))
assert.ok(source.includes('X-Internal-Service-Token'))
assert.doesNotMatch(source, /@(?:PutMapping|DeleteMapping|PatchMapping)/)
}
})
test('delivery fee coverage is a single readonly Finance hop and cannot write financial state', async () => {
const client = await readFile(path.join(root, 'lastleg-service/src/main/java/com/baiyue/lastleg/client/FinanceFeeCoverageClient.java'), 'utf8')
const service = await readFile(path.join(root, 'finance/src/main/java/com/baiyue/finance/service/DeliveryFeeCoverageQueryService.java'), 'utf8')