@joystick.js/db-canary 0.0.0-canary.2275 → 0.0.0-canary.2276

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,202 +0,0 @@
1
- import test from 'ava';
2
- import { get_replication_manager, initialize_replication_manager, shutdown_replication_manager } from '../../../src/server/lib/replication_manager.js';
3
-
4
- test.beforeEach(async () => {
5
- // Clean up any existing replication manager
6
- await shutdown_replication_manager();
7
- });
8
-
9
- test.afterEach(async () => {
10
- // Clean up after each test
11
- await shutdown_replication_manager();
12
- });
13
-
14
- test('replication manager singleton', t => {
15
- const manager1 = get_replication_manager();
16
- const manager2 = get_replication_manager();
17
-
18
- t.is(manager1, manager2, 'Should return same instance');
19
- });
20
-
21
- test('replication manager initialization without settings', t => {
22
- const manager = get_replication_manager();
23
-
24
- // Should not throw when no settings are available
25
- t.notThrows(() => {
26
- manager.initialize();
27
- });
28
-
29
- t.false(manager.enabled, 'Should be disabled without settings');
30
- });
31
-
32
- test('replication manager default configuration', t => {
33
- const manager = get_replication_manager();
34
-
35
- t.false(manager.enabled, 'Should be disabled by default');
36
- t.is(manager.mode, 'async', 'Should default to async mode');
37
- t.is(manager.timeout_ms, 5000, 'Should have default timeout');
38
- t.is(manager.retry_attempts, 3, 'Should have default retry attempts');
39
- t.is(manager.batch_size, 100, 'Should have default batch size');
40
- });
41
-
42
- test('replication manager queue operation when disabled', t => {
43
- const manager = get_replication_manager();
44
-
45
- // Should not throw when queuing operations while disabled
46
- t.notThrows(() => {
47
- manager.queue_replication('insert_one', 'test_collection', { document: { name: 'test' } });
48
- });
49
-
50
- t.is(manager.replication_queue.length, 0, 'Should not queue when disabled');
51
- });
52
-
53
- test('replication manager get status when disabled', t => {
54
- const manager = get_replication_manager();
55
-
56
- const status = manager.get_replication_status();
57
-
58
- t.false(status.enabled, 'Should report as disabled');
59
- t.is(status.connected_secondaries, 0, 'Should have no connected secondaries');
60
- t.is(status.queue_length, 0, 'Should have empty queue');
61
- t.false(status.processing, 'Should not be processing');
62
- t.is(status.secondaries.length, 0, 'Should have no secondaries');
63
- });
64
-
65
- test('replication manager get secondary health when disabled', t => {
66
- const manager = get_replication_manager();
67
-
68
- const health = manager.get_secondary_health();
69
-
70
- t.is(health.total_secondaries, 0, 'Should have no secondaries');
71
- t.is(health.healthy_secondaries, 0, 'Should have no healthy secondaries');
72
- t.is(health.secondaries.length, 0, 'Should have empty secondaries array');
73
- });
74
-
75
- test('replication manager add secondary when disabled', async t => {
76
- const manager = get_replication_manager();
77
-
78
- const secondary = {
79
- id: 'test-secondary',
80
- ip: '127.0.0.1',
81
- port: 1984,
82
- private_key: Buffer.from('test-key').toString('base64'),
83
- enabled: true
84
- };
85
-
86
- // Should not throw but won't actually connect
87
- const result = await manager.add_secondary(secondary);
88
-
89
- t.true(result.success, 'Should return success');
90
- t.is(result.secondary_id, 'test-secondary', 'Should return secondary ID');
91
- });
92
-
93
- test('replication manager remove non-existent secondary', t => {
94
- const manager = get_replication_manager();
95
-
96
- const error = t.throws(() => {
97
- manager.remove_secondary('non-existent');
98
- });
99
-
100
- t.true(error.message.includes('not found'), 'Should throw not found error');
101
- });
102
-
103
- test('replication manager sync when disabled', async t => {
104
- const manager = get_replication_manager();
105
-
106
- const error = await t.throwsAsync(async () => {
107
- await manager.sync_secondaries();
108
- });
109
-
110
- t.true(error.message.includes('not enabled'), 'Should throw not enabled error');
111
- });
112
-
113
- test('replication manager shutdown', async t => {
114
- const manager = get_replication_manager();
115
-
116
- // Should not throw when shutting down
117
- await t.notThrowsAsync(async () => {
118
- await manager.shutdown();
119
- });
120
-
121
- t.false(manager.enabled, 'Should be disabled after shutdown');
122
- t.false(manager.processing_replication, 'Should not be processing after shutdown');
123
- t.is(manager.secondary_connections.size, 0, 'Should have no connections after shutdown');
124
- t.is(manager.replication_queue.length, 0, 'Should have empty queue after shutdown');
125
- });
126
-
127
- test('replication manager statistics tracking', t => {
128
- const manager = get_replication_manager();
129
-
130
- const initialStats = manager.stats;
131
-
132
- t.is(initialStats.total_operations_replicated, 0, 'Should start with zero operations');
133
- t.is(initialStats.successful_replications, 0, 'Should start with zero successful replications');
134
- t.is(initialStats.failed_replications, 0, 'Should start with zero failed replications');
135
- t.is(initialStats.connected_secondaries, 0, 'Should start with zero connected secondaries');
136
- t.is(initialStats.avg_replication_latency_ms, 0, 'Should start with zero average latency');
137
- });
138
-
139
- test('replication manager sequence number generation', t => {
140
- const manager = get_replication_manager();
141
-
142
- const initialSequence = manager.sequence_number;
143
-
144
- // Enable manager temporarily to test sequence generation
145
- manager.enabled = true;
146
- manager.secondary_connections.set('test', { authenticated: true });
147
-
148
- manager.queue_replication('insert_one', 'test', { document: { name: 'test1' } });
149
- manager.queue_replication('insert_one', 'test', { document: { name: 'test2' } });
150
-
151
- t.is(manager.sequence_number, initialSequence + 2, 'Should increment sequence number for each operation');
152
- t.true(manager.sequence_number > initialSequence, 'Should generate increasing sequence numbers');
153
-
154
- // Clean up
155
- manager.enabled = false;
156
- manager.secondary_connections.clear();
157
- manager.replication_queue = [];
158
- });
159
-
160
- test('replication manager sequence number increment', t => {
161
- const manager = get_replication_manager();
162
-
163
- const initialSequence = manager.sequence_number;
164
-
165
- // Enable manager temporarily to test queue operation
166
- manager.enabled = true;
167
- manager.secondary_connections.set('test', { authenticated: true });
168
-
169
- manager.queue_replication('insert_one', 'test', { document: { name: 'test' } });
170
-
171
- t.is(manager.sequence_number, initialSequence + 1, 'Should increment sequence number');
172
-
173
- // Clean up
174
- manager.enabled = false;
175
- manager.secondary_connections.clear();
176
- manager.replication_queue = [];
177
- });
178
-
179
- test('replication manager batch processing preparation', t => {
180
- const manager = get_replication_manager();
181
-
182
- // Enable manager and add mock secondary
183
- manager.enabled = true;
184
- manager.secondary_connections.set('test', {
185
- authenticated: true,
186
- socket: { write: () => {} },
187
- pending_operations: new Map()
188
- });
189
-
190
- // Add multiple operations to queue
191
- for (let i = 0; i < 5; i++) {
192
- manager.queue_replication('insert_one', 'test', { document: { id: i } });
193
- }
194
-
195
- t.is(manager.replication_queue.length, 5, 'Should queue all operations');
196
- t.is(manager.stats.total_operations_replicated, 5, 'Should track total operations');
197
-
198
- // Clean up
199
- manager.enabled = false;
200
- manager.secondary_connections.clear();
201
- manager.replication_queue = [];
202
- });
@@ -1,258 +0,0 @@
1
- import test from 'ava';
2
- import { get_write_forwarder, initialize_write_forwarder, shutdown_write_forwarder } from '../../../src/server/lib/write_forwarder.js';
3
-
4
- test.beforeEach(async () => {
5
- // Clean up any existing write forwarder
6
- await shutdown_write_forwarder();
7
- });
8
-
9
- test.afterEach(async () => {
10
- // Clean up after each test
11
- await shutdown_write_forwarder();
12
- });
13
-
14
- test('write forwarder singleton', t => {
15
- const forwarder1 = get_write_forwarder();
16
- const forwarder2 = get_write_forwarder();
17
-
18
- t.is(forwarder1, forwarder2, 'Should return same instance');
19
- });
20
-
21
- test('write forwarder initialization without settings', t => {
22
- const forwarder = get_write_forwarder();
23
-
24
- // Should not throw when no settings are available
25
- t.notThrows(() => {
26
- forwarder.initialize();
27
- });
28
-
29
- t.false(forwarder.is_secondary_mode, 'Should not be in secondary mode without settings');
30
- });
31
-
32
- test('write forwarder default configuration', t => {
33
- const forwarder = get_write_forwarder();
34
-
35
- t.false(forwarder.is_secondary_mode, 'Should not be in secondary mode by default');
36
- t.is(forwarder.primary_config, null, 'Should have no primary config by default');
37
- t.is(forwarder.pending_forwards.size, 0, 'Should have no pending forwards');
38
- t.is(forwarder.forward_timeout_ms, 10000, 'Should have default timeout');
39
- t.is(forwarder.reconnect_delay_ms, 5000, 'Should have default reconnect delay');
40
- });
41
-
42
- test('write forwarder should forward operation check', t => {
43
- const forwarder = get_write_forwarder();
44
-
45
- // Not in secondary mode
46
- t.false(forwarder.should_forward_operation('insert_one'), 'Should not forward when not in secondary mode');
47
-
48
- // Enable secondary mode
49
- forwarder.is_secondary_mode = true;
50
-
51
- // Test write operations
52
- t.true(forwarder.should_forward_operation('insert_one'), 'Should forward insert_one');
53
- t.true(forwarder.should_forward_operation('update_one'), 'Should forward update_one');
54
- t.true(forwarder.should_forward_operation('delete_one'), 'Should forward delete_one');
55
- t.true(forwarder.should_forward_operation('bulk_write'), 'Should forward bulk_write');
56
- t.true(forwarder.should_forward_operation('create_index'), 'Should forward create_index');
57
- t.true(forwarder.should_forward_operation('drop_index'), 'Should forward drop_index');
58
-
59
- // Test read operations
60
- t.false(forwarder.should_forward_operation('find_one'), 'Should not forward find_one');
61
- t.false(forwarder.should_forward_operation('find'), 'Should not forward find');
62
- t.false(forwarder.should_forward_operation('get_indexes'), 'Should not forward get_indexes');
63
-
64
- // Clean up
65
- forwarder.is_secondary_mode = false;
66
- });
67
-
68
- test('write forwarder forward operation when not in secondary mode', async t => {
69
- const forwarder = get_write_forwarder();
70
- const mockSocket = { id: 'test-socket' };
71
-
72
- const forwarded = await forwarder.forward_operation(mockSocket, 'insert_one', { collection: 'test' });
73
-
74
- t.false(forwarded, 'Should not forward when not in secondary mode');
75
- });
76
-
77
- test('write forwarder forward operation when not connected', async t => {
78
- const forwarder = get_write_forwarder();
79
- const mockSocket = {
80
- id: 'test-socket',
81
- write: () => {}
82
- };
83
-
84
- // Enable secondary mode but no connection
85
- forwarder.is_secondary_mode = true;
86
- forwarder.primary_connection = null;
87
-
88
- const forwarded = await forwarder.forward_operation(mockSocket, 'insert_one', { collection: 'test' });
89
-
90
- t.true(forwarded, 'Should handle forward attempt');
91
-
92
- // Clean up
93
- forwarder.is_secondary_mode = false;
94
- });
95
-
96
- test('write forwarder generate forward ID', t => {
97
- const forwarder = get_write_forwarder();
98
-
99
- const id1 = forwarder.generate_forward_id();
100
- const id2 = forwarder.generate_forward_id();
101
-
102
- t.is(typeof id1, 'string', 'Should return string ID');
103
- t.is(typeof id2, 'string', 'Should return string ID');
104
- t.not(id1, id2, 'Should generate unique IDs');
105
- t.true(id1.startsWith('fwd_'), 'Should start with fwd_ prefix');
106
- });
107
-
108
- test('write forwarder get status when disabled', t => {
109
- const forwarder = get_write_forwarder();
110
-
111
- const status = forwarder.get_forwarder_status();
112
-
113
- t.false(status.enabled, 'Should report as disabled');
114
- t.false(status.connected_to_primary, 'Should not be connected to primary');
115
- t.is(status.primary_config, null, 'Should have no primary config');
116
- t.is(status.pending_forwards, 0, 'Should have no pending forwards');
117
- t.is(status.stats.total_forwards, 0, 'Should have zero total forwards');
118
- });
119
-
120
- test('write forwarder statistics tracking', t => {
121
- const forwarder = get_write_forwarder();
122
-
123
- const initialStats = forwarder.stats;
124
-
125
- t.is(initialStats.total_forwards, 0, 'Should start with zero forwards');
126
- t.is(initialStats.successful_forwards, 0, 'Should start with zero successful forwards');
127
- t.is(initialStats.failed_forwards, 0, 'Should start with zero failed forwards');
128
- t.is(initialStats.avg_forward_latency_ms, 0, 'Should start with zero average latency');
129
- t.is(initialStats.connection_attempts, 0, 'Should start with zero connection attempts');
130
- t.is(initialStats.last_connection_attempt, null, 'Should have no last connection attempt');
131
- });
132
-
133
- test('write forwarder handle forward timeout', t => {
134
- const forwarder = get_write_forwarder();
135
- const forwardId = 'test-forward-id';
136
-
137
- // Add a pending forward
138
- forwarder.pending_forwards.set(forwardId, {
139
- client_socket: { write: () => {} },
140
- operation: 'insert_one',
141
- data: { collection: 'test' },
142
- sent_at: Date.now(),
143
- timeout: null
144
- });
145
-
146
- const initialFailed = forwarder.stats.failed_forwards;
147
-
148
- forwarder.handle_forward_timeout(forwardId);
149
-
150
- t.false(forwarder.pending_forwards.has(forwardId), 'Should remove pending forward');
151
- t.is(forwarder.stats.failed_forwards, initialFailed + 1, 'Should increment failed forwards');
152
- });
153
-
154
- test('write forwarder fail pending forwards', t => {
155
- const forwarder = get_write_forwarder();
156
-
157
- // Add multiple pending forwards
158
- for (let i = 0; i < 3; i++) {
159
- forwarder.pending_forwards.set(`forward-${i}`, {
160
- client_socket: { write: () => {} },
161
- operation: 'insert_one',
162
- data: { collection: 'test' },
163
- sent_at: Date.now(),
164
- timeout: null
165
- });
166
- }
167
-
168
- const initialFailed = forwarder.stats.failed_forwards;
169
- const pendingCount = forwarder.pending_forwards.size;
170
-
171
- forwarder.fail_pending_forwards('Test reason');
172
-
173
- t.is(forwarder.pending_forwards.size, 0, 'Should clear all pending forwards');
174
- t.is(forwarder.stats.failed_forwards, initialFailed + pendingCount, 'Should increment failed forwards by pending count');
175
- });
176
-
177
- test('write forwarder shutdown', async t => {
178
- const forwarder = get_write_forwarder();
179
-
180
- // Add some pending forwards
181
- forwarder.pending_forwards.set('test-forward', {
182
- client_socket: { write: () => {} },
183
- operation: 'insert_one',
184
- data: { collection: 'test' },
185
- sent_at: Date.now(),
186
- timeout: null
187
- });
188
-
189
- forwarder.is_secondary_mode = true;
190
-
191
- // Should not throw when shutting down
192
- await t.notThrowsAsync(async () => {
193
- await forwarder.shutdown();
194
- });
195
-
196
- t.false(forwarder.is_secondary_mode, 'Should disable secondary mode after shutdown');
197
- t.is(forwarder.pending_forwards.size, 0, 'Should clear pending forwards after shutdown');
198
- t.is(forwarder.primary_connection, null, 'Should clear primary connection after shutdown');
199
- });
200
-
201
- test('write forwarder handle primary response with unknown forward', t => {
202
- const forwarder = get_write_forwarder();
203
-
204
- // Set up primary connection
205
- forwarder.primary_connection = {
206
- authenticated: true,
207
- last_ping: Date.now()
208
- };
209
-
210
- const response = {
211
- forward_id: 'unknown-forward-id',
212
- ok: 1,
213
- result: 'success'
214
- };
215
-
216
- // Should not throw when handling unknown forward response
217
- t.notThrows(() => {
218
- forwarder.handle_forward_response(response);
219
- });
220
- });
221
-
222
- test('write forwarder handle authentication success', t => {
223
- const forwarder = get_write_forwarder();
224
-
225
- // Set up primary connection
226
- forwarder.primary_connection = {
227
- authenticated: false,
228
- last_ping: Date.now()
229
- };
230
-
231
- const authResponse = {
232
- ok: 1,
233
- message: 'Authentication successful'
234
- };
235
-
236
- forwarder.handle_primary_response(authResponse);
237
-
238
- t.true(forwarder.primary_connection.authenticated, 'Should set authenticated to true');
239
- });
240
-
241
- test('write forwarder handle ping response', t => {
242
- const forwarder = get_write_forwarder();
243
-
244
- // Set up primary connection
245
- const initialPing = Date.now() - 1000;
246
- forwarder.primary_connection = {
247
- authenticated: true,
248
- last_ping: initialPing
249
- };
250
-
251
- const pingResponse = {
252
- ok: 1
253
- };
254
-
255
- forwarder.handle_primary_response(pingResponse);
256
-
257
- t.true(forwarder.primary_connection.last_ping > initialPing, 'Should update last ping time');
258
- });