/** * EdgeGateway Routing Integration Tests * * Tests the EdgeGateway's ability to route messages between * backbone and local bus using in-memory transports. */ import { describe, it } from 'node:test'; import { strict as assert } from 'node:assert'; import { FederationPeer, ExactInstanceResolver, WIRE_PROFILES, InMemoryFilterBroker, getLegacyIngressTopic, } from '@open-matrix/federation'; describe('EdgeGateway Routing', () => { it('routes inbound request from backbone to local bus', async () => { const REALM = 'test-realm'; // Create in-memory brokers const backbone = new InMemoryFilterBroker(); const localBus = new InMemoryFilterBroker(); // Create EdgeGateway const gateway = new FederationPeer({ localRealm: REALM, profile: WIRE_PROFILES.matrix3, backbone, localBus, }); gateway.start(); // Subscribe to internal topic on local bus (simulating a handler) // Internal topic format: (realm is a transport concern) let receivedRequest: unknown = null; localBus.subscribe(`test.component.accepts.ping`, (topic, payload) => { receivedRequest = JSON.parse(payload); }); // Allow subscriptions to propagate await new Promise(r => setTimeout(r, 50)); // Send request to backbone mailbox using LEGACY format (flat fields) const request = { toRealm: REALM, toPath: 'test.component.accepts.ping', fromRealm: 'client-realm', replyTo: '_reply', // just the path, not an object correlationId: 'test-123', body: { message: 'hello' }, }; backbone.publish(getLegacyIngressTopic(REALM), JSON.stringify(request)); // Wait for message to be routed await new Promise(r => setTimeout(r, 100)); assert.ok(receivedRequest, 'Should receive request on local bus'); assert.strictEqual((receivedRequest as { correlationId: string }).correlationId, 'test-123'); gateway.stop(); }); it('routes reply from local bus back to backbone', async () => { const REALM = 'test-realm'; const CLIENT_REALM = 'client-realm'; const backbone = new InMemoryFilterBroker(); const localBus = new InMemoryFilterBroker(); const gateway = new FederationPeer({ localRealm: REALM, profile: WIRE_PROFILES.matrix3, backbone, localBus, internalTimeoutMs: 5000, }); gateway.start(); // Subscribe to client's mailbox on backbone (where reply should go) let receivedReply: unknown = null; backbone.subscribe(getLegacyIngressTopic(CLIENT_REALM), (topic, payload) => { receivedReply = JSON.parse(payload); }); // Set up handler on local bus that will reply // Internal topic format: (realm is a transport concern) localBus.subscribe(`test.component.accepts.echo`, (topic, payload) => { const req = JSON.parse(payload) as { replyTo: string; correlationId: string; params: unknown }; // Send reply to the replyTo topic localBus.publish(req.replyTo, JSON.stringify({ ok: true, correlationId: req.correlationId, result: { echo: 'hello back' }, })); }); await new Promise(r => setTimeout(r, 50)); // Send request from client using LEGACY format (flat fields) const request = { toRealm: REALM, toPath: 'test.component.accepts.echo', fromRealm: CLIENT_REALM, replyTo: '_reply', // just the path correlationId: 'echo-456', body: { message: 'hello' }, }; backbone.publish(getLegacyIngressTopic(REALM), JSON.stringify(request)); // Wait for round-trip await new Promise(r => setTimeout(r, 200)); assert.ok(receivedReply, 'Should receive reply on backbone'); gateway.stop(); }); it('uses exact mailbox topic (no wildcards)', async () => { const REALM = 'my-realm'; const backbone = new InMemoryFilterBroker(); const localBus = new InMemoryFilterBroker(); // Track what topics are subscribed const subscribedTopics: string[] = []; const originalSubscribe = backbone.subscribe.bind(backbone); backbone.subscribe = (topic: string, handler: (t: string, p: string) => void) => { subscribedTopics.push(topic); return originalSubscribe(topic, handler); }; const gateway = new FederationPeer({ localRealm: REALM, profile: WIRE_PROFILES.matrix3, backbone, localBus, }); gateway.start(); // Verify subscribed topic is exact mailbox, not wildcard const mailboxTopic = getLegacyIngressTopic(REALM); assert.ok( subscribedTopics.includes(mailboxTopic), `Should subscribe to exact mailbox: ${mailboxTopic}` ); assert.ok( !subscribedTopics.some(t => t.includes('#') || t.includes('+')), 'Should NOT use wildcards on backbone subscription' ); gateway.stop(); }); it('metrics track inbound requests', async () => { const REALM = 'metrics-realm'; const backbone = new InMemoryFilterBroker(); const localBus = new InMemoryFilterBroker(); const gateway = new FederationPeer({ localRealm: REALM, profile: WIRE_PROFILES.matrix3, backbone, localBus, }); gateway.start(); // Set up a handler so request completes // Internal topic format: (realm is a transport concern) localBus.subscribe(`test.accepts.cmd`, (topic, payload) => { const req = JSON.parse(payload) as { replyTo: string; correlationId: string }; localBus.publish(req.replyTo, JSON.stringify({ ok: true, correlationId: req.correlationId })); }); await new Promise(r => setTimeout(r, 50)); const initialMetrics = gateway.getMetrics(); // Send a request using LEGACY format (flat fields) const request = { toRealm: REALM, toPath: 'test.accepts.cmd', fromRealm: 'other', replyTo: '_reply', // just the path correlationId: 'metrics-1', body: {}, }; backbone.publish(getLegacyIngressTopic(REALM), JSON.stringify(request)); await new Promise(r => setTimeout(r, 200)); const finalMetrics = gateway.getMetrics(); assert.ok( finalMetrics.inboundRequests > initialMetrics.inboundRequests, 'Inbound requests should increase' ); gateway.stop(); }); });