fix: register current synchronous service dependencies and guard callback boundaries
This commit is contained in:
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user