rhizome-node/__tests__/run/002-two-nodes-orchestrated.ts
Lentil Hoffman b78985779b
Implement Docker orchestrator and fix test infrastructure
- Add DockerOrchestrator implementation with container management
- Refactor InMemoryOrchestrator to use RhizomeNode directly
- Fix orchestrated test files for single and two-node scenarios
- Update package.json with dockerode dependency
- Clean up old test files and imports
2025-06-19 16:58:06 -05:00

118 lines
3.3 KiB
TypeScript

import Debug from 'debug';
import { createOrchestrator } from '../../src/orchestration';
import type { NodeConfig, NodeHandle } from '../../src/orchestration';
const debug = Debug('test:two-orchestrated');
describe('Run (Two Nodes Orchestrated)', () => {
const orchestrator = createOrchestrator('in-memory');
// Define a type that includes all required methods
type FullNodeHandle = NodeHandle & {
getRequestPort: () => number;
getApiUrl: () => string;
};
const nodes: FullNodeHandle[] = [];
const nodeIds = ['app-002-A', 'app-002-B'];
beforeAll(async () => {
// Start first node
const node1Config: NodeConfig = {
id: nodeIds[0],
};
const node1 = (await orchestrator.startNode(node1Config)) as FullNodeHandle;
// Start second node with first node as bootstrap peer
const node2Config: NodeConfig = {
id: nodeIds[1],
network: {
bootstrapPeers: [`localhost:${node1.getRequestPort()}`],
},
};
const node2 = (await orchestrator.startNode(node2Config)) as FullNodeHandle;
nodes.push(node1, node2);
// Connect the nodes
await orchestrator.connectNodes(node1, node2);
});
afterAll(async () => {
// Stop all nodes in parallel
await Promise.all(nodes.map(node => node && orchestrator.stopNode(node)));
});
it('can create a record on node0 and read it from node1', async () => {
const [node0, node1] = nodes;
const node0Url = node0.getApiUrl();
const node1Url = node1.getApiUrl();
debug(`Node 0 URL: ${node0Url}`);
debug(`Node 1 URL: ${node1Url}`);
// Create a new record on node0
const createResponse = await fetch(`${node0Url}/user`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 'peon-1',
properties: {
name: 'Peon',
age: 741,
},
}),
});
const createdUser = await createResponse.json();
expect(createdUser).toMatchObject({
id: 'peon-1',
properties: {
name: 'Peon',
age: 741,
},
});
// Small delay to allow for synchronization
await new Promise(resolve => setTimeout(resolve, 100));
// Read the record from node1
const getResponse = await fetch(`${node1Url}/user/peon-1`);
const fetchedUser = await getResponse.json();
expect(fetchedUser).toMatchObject({
id: 'peon-1',
properties: {
name: 'Peon',
age: 741,
},
});
});
it('can demonstrate network partitioning', async () => {
// This test shows how we can simulate network partitions
// For now, it's just a placeholder since we'd need to implement
// the actual partitioning logic in the InMemoryOrchestrator
const [node0, node1] = nodes;
// Simulate partition (actual implementation would use orchestrator.partitionNetwork)
debug('Simulating network partition between nodes');
// await orchestrator.partitionNetwork({
// groups: [[node0.id], [node1.id]]
// });
// Test behavior during partition...
// Heal partition
// await orchestrator.partitionNetwork({
// groups: [[node0.id, node1.id]]
// });
// Test behavior after healing...
// Mark test as passed (remove once actual test is implemented)
expect(true).toBe(true);
});
});