@joystick.js/db-canary 0.0.0-canary.2209
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.
- package/.build/getFilesToBuild.js +26 -0
- package/.build/getPlatformSafeFilePath.js +6 -0
- package/.build/getPlatformSafePath.js +6 -0
- package/.build/index.js +88 -0
- package/.build/isWindows.js +3 -0
- package/API_KEY +1 -0
- package/README.md +1821 -0
- package/data/data.mdb +0 -0
- package/data/lock.mdb +0 -0
- package/dist/client/database.js +1 -0
- package/dist/client/index.js +1 -0
- package/dist/server/cluster/index.js +1 -0
- package/dist/server/cluster/master.js +20 -0
- package/dist/server/cluster/worker.js +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/lib/api_key_manager.js +9 -0
- package/dist/server/lib/auth_manager.js +1 -0
- package/dist/server/lib/auto_index_manager.js +1 -0
- package/dist/server/lib/backup_manager.js +1 -0
- package/dist/server/lib/connection_manager.js +1 -0
- package/dist/server/lib/disk_utils.js +2 -0
- package/dist/server/lib/http_server.js +405 -0
- package/dist/server/lib/index_manager.js +1 -0
- package/dist/server/lib/load_settings.js +1 -0
- package/dist/server/lib/logger.js +1 -0
- package/dist/server/lib/op_types.js +1 -0
- package/dist/server/lib/operation_dispatcher.js +1 -0
- package/dist/server/lib/operations/admin.js +1 -0
- package/dist/server/lib/operations/bulk_write.js +1 -0
- package/dist/server/lib/operations/create_index.js +1 -0
- package/dist/server/lib/operations/delete_one.js +1 -0
- package/dist/server/lib/operations/drop_index.js +1 -0
- package/dist/server/lib/operations/find.js +1 -0
- package/dist/server/lib/operations/find_one.js +1 -0
- package/dist/server/lib/operations/get_indexes.js +1 -0
- package/dist/server/lib/operations/insert_one.js +1 -0
- package/dist/server/lib/operations/update_one.js +1 -0
- package/dist/server/lib/performance_monitor.js +1 -0
- package/dist/server/lib/query_engine.js +1 -0
- package/dist/server/lib/recovery_manager.js +1 -0
- package/dist/server/lib/replication_manager.js +1 -0
- package/dist/server/lib/safe_json_parse.js +1 -0
- package/dist/server/lib/send_response.js +1 -0
- package/dist/server/lib/tcp_protocol.js +1 -0
- package/dist/server/lib/write_forwarder.js +1 -0
- package/dist/server/lib/write_queue.js +1 -0
- package/increment_version.js +3 -0
- package/logs/.013e15b54597d05db4b4b53ecc37b10c92a72927-audit.json +20 -0
- package/logs/.02de550a67ea0f5961faa2dfd458a4d06f59ebd1-audit.json +20 -0
- package/logs/.03494ba24eb3c72214b4068a77d54b8993bee651-audit.json +20 -0
- package/logs/.06309ec60b339be1259a7993dd09c732f8907fbc-audit.json +20 -0
- package/logs/.0663a04dcfa17285661e5e1b8cfa51f41523b210-audit.json +20 -0
- package/logs/.0f06e6c4c9b824622729e13927587479e5060391-audit.json +20 -0
- package/logs/.16ccf58682ecb22b3e3ec63f0da1b7fe9be56528-audit.json +20 -0
- package/logs/.1fa1a5d02f496474b1ab473524c65c984146a9ad-audit.json +20 -0
- package/logs/.2223c0ae3bea6f0d62c62b1d319cc8634856abb7-audit.json +20 -0
- package/logs/.23dc79ffda3e083665e6f5993f59397adcbf4a46-audit.json +20 -0
- package/logs/.28104f49b03906b189eefd1cd462cb46c3c0af22-audit.json +20 -0
- package/logs/.29cdbf13808abe6a0ce70ee2f2efdd680ce3fd8e-audit.json +20 -0
- package/logs/.2a9889afd071f77f41f5170d08703a0afca866b7-audit.json +20 -0
- package/logs/.2acec3d1940a2bbed487528b703ee5948959a599-audit.json +20 -0
- package/logs/.2fb60ff326338c02bfedbcd0e936444e4a216750-audit.json +20 -0
- package/logs/.318fc7a19530d76a345f030f7cad00dda15300e7-audit.json +20 -0
- package/logs/.3cf27043e19085f908cedc7701e6d013463208ee-audit.json +25 -0
- package/logs/.3d90d785415817fc443402843b7c95f8371adc9b-audit.json +20 -0
- package/logs/.4074bca620375f72966fc52dfd439577727671e5-audit.json +20 -0
- package/logs/.40eecf018417ea80a70ea8ec7a3cc9406bc6334b-audit.json +20 -0
- package/logs/.50e974f1ef7c365fca6a1251b2e2c2252914cb5e-audit.json +20 -0
- package/logs/.52cb7d9e4223cf26ba36006ac26b949a97c7923c-audit.json +20 -0
- package/logs/.54befcdb84c15aad980705a31bcc9f555c3577ab-audit.json +20 -0
- package/logs/.57dfb70e22eddb84db2e3c0ceeefac5c0b9baffa-audit.json +20 -0
- package/logs/.5f0b24705a1eaad4eca4968f2d86f91b3f9be683-audit.json +20 -0
- package/logs/.61ba98fdda7db58576b382fee07904e5db1169d6-audit.json +20 -0
- package/logs/.6235017727ef6b199d569a99d6aa8c8e80a1b475-audit.json +20 -0
- package/logs/.63db16193699219489d218a1ddea5dde3750cae4-audit.json +20 -0
- package/logs/.64fb67dfe14149c9eef728d79bf30a54da809c60-audit.json +20 -0
- package/logs/.669137453368987c1f311b5345342527afb54e50-audit.json +20 -0
- package/logs/.7a71f8c89ea28ae266d356aeff6306e876a30fbb-audit.json +20 -0
- package/logs/.7afbaa90fe9dc3a7d682676f9bb79f9a1b1fd9a6-audit.json +20 -0
- package/logs/.7ca29e322cd05327035de850099e7610864f2347-audit.json +20 -0
- package/logs/.83335ab3347e449dae03455a110aaf7f120d4802-audit.json +20 -0
- package/logs/.8c2487b5fd445d2c8e5c483c80b9fa99bbf1ca58-audit.json +20 -0
- package/logs/.8c8b9dc386922c9f3b4c13251af7052aac1d24c0-audit.json +20 -0
- package/logs/.8d6155d94640c4863301ae0fee5e4e7372a21446-audit.json +20 -0
- package/logs/.944a3119a243deea7c8270d5d9e582bb1d0eaa10-audit.json +20 -0
- package/logs/.9816a845c30fb2909f3b26a23eeb3538ebcad5db-audit.json +20 -0
- package/logs/.9dc08784e38b865488177c26d4af5934555e0323-audit.json +20 -0
- package/logs/.9dd27d2e0e454ac0a37600206d1cac5493b0d7ee-audit.json +20 -0
- package/logs/.a3d486feeac7654c59b547de96600e8849a06d4f-audit.json +20 -0
- package/logs/.a5b811f4def22250f86cc18870d7c4573625df22-audit.json +20 -0
- package/logs/.a61648eb5f830e0b6f508ac35e4f8f629d2ad4c7-audit.json +20 -0
- package/logs/.a89016d507045771b4b5a65656944a9c0f1e528b-audit.json +20 -0
- package/logs/.a99bee160a1c590be959af46bacc02724803f691-audit.json +20 -0
- package/logs/.ada7906d6243fd7da802f03d86c4ae5dd9df6236-audit.json +20 -0
- package/logs/.b518339ee942143b6af983af167f5bbb6983b4de-audit.json +20 -0
- package/logs/.b51b124b166d53c9519017856ea610d61d65fabe-audit.json +20 -0
- package/logs/.b7a6aee19f58e55633d5e4a3709041c47dfff975-audit.json +20 -0
- package/logs/.bd7a8a6ba9c55d557a4867ab53f02e3ec2e1553d-audit.json +20 -0
- package/logs/.c1435dafe453b169d6392b25065f3cf4ab6fbb21-audit.json +20 -0
- package/logs/.c17e1ce043109f77dc2f0e2aa290a9d1ed842c03-audit.json +20 -0
- package/logs/.ca62637ce9540e5a38a2fbedb2115febb6ad308a-audit.json +15 -0
- package/logs/.ccee67b9c176967f8977071409a41f5cb5cd6ad4-audit.json +20 -0
- package/logs/.db24043417ea79a6f14cd947476399e53930b48d-audit.json +20 -0
- package/logs/.e0f12acccb57829f5f33712bb2e2607ecd808147-audit.json +20 -0
- package/logs/.e9b6cc33d0bbd2e644c4e2bf44d177f850016557-audit.json +20 -0
- package/logs/.f15291d434808e3bdca7963ccd2e73893be027e6-audit.json +20 -0
- package/logs/.f4bdf9e21ef84f8a3fae3ffb32bbc39275991351-audit.json +15 -0
- package/logs/.fbac3aefac1e81b4230df5aa50667cb90d51024f-audit.json +20 -0
- package/logs/.fcfd495c0a9169db243f4a4f21878ee02b76413c-audit.json +20 -0
- package/logs/admin-2025-09-12.log +580 -0
- package/logs/admin-2025-09-15.log +283 -0
- package/logs/admin-error-2025-09-12.log +22 -0
- package/logs/admin-error-2025-09-15.log +10 -0
- package/logs/api_key_manager-2025-09-12.log +658 -0
- package/logs/api_key_manager-2025-09-15.log +295 -0
- package/logs/api_key_manager-error-2025-09-12.log +0 -0
- package/logs/api_key_manager-error-2025-09-15.log +0 -0
- package/logs/auth_manager-2025-09-12.log +4432 -0
- package/logs/auth_manager-2025-09-15.log +2000 -0
- package/logs/auth_manager-error-2025-09-12.log +11 -0
- package/logs/auth_manager-error-2025-09-15.log +5 -0
- package/logs/auto_index_manager-2025-09-12.log +84 -0
- package/logs/auto_index_manager-2025-09-15.log +45 -0
- package/logs/auto_index_manager-error-2025-09-12.log +6 -0
- package/logs/auto_index_manager-error-2025-09-15.log +0 -0
- package/logs/backup_manager-2025-09-12.log +198 -0
- package/logs/backup_manager-2025-09-15.log +90 -0
- package/logs/backup_manager-error-2025-09-12.log +198 -0
- package/logs/backup_manager-error-2025-09-15.log +90 -0
- package/logs/bulk_write-2025-09-12.log +66 -0
- package/logs/bulk_write-2025-09-15.log +38 -0
- package/logs/bulk_write-error-2025-09-12.log +0 -0
- package/logs/bulk_write-error-2025-09-15.log +0 -0
- package/logs/connection_manager-2025-09-12.log +2412 -0
- package/logs/connection_manager-2025-09-15.log +1132 -0
- package/logs/connection_manager-error-2025-09-12.log +0 -0
- package/logs/connection_manager-error-2025-09-15.log +0 -0
- package/logs/create_index-2025-09-12.log +302 -0
- package/logs/create_index-2025-09-15.log +158 -0
- package/logs/create_index-error-2025-09-12.log +30 -0
- package/logs/create_index-error-2025-09-15.log +13 -0
- package/logs/delete_one-2025-09-12.log +73 -0
- package/logs/delete_one-2025-09-15.log +43 -0
- package/logs/delete_one-error-2025-09-12.log +0 -0
- package/logs/delete_one-error-2025-09-15.log +0 -0
- package/logs/disk_utils-2025-09-12.log +4954 -0
- package/logs/disk_utils-2025-09-15.log +2446 -0
- package/logs/disk_utils-error-2025-09-12.log +0 -0
- package/logs/disk_utils-error-2025-09-15.log +0 -0
- package/logs/drop_index-2025-09-12.log +41 -0
- package/logs/drop_index-2025-09-15.log +23 -0
- package/logs/drop_index-error-2025-09-12.log +11 -0
- package/logs/drop_index-error-2025-09-15.log +5 -0
- package/logs/find-2025-09-12.log +1050 -0
- package/logs/find-2025-09-15.log +592 -0
- package/logs/find-error-2025-09-12.log +1 -0
- package/logs/find-error-2025-09-15.log +0 -0
- package/logs/find_one-2025-09-12.log +425 -0
- package/logs/find_one-2025-09-15.log +264 -0
- package/logs/find_one-error-2025-09-12.log +5 -0
- package/logs/find_one-error-2025-09-15.log +0 -0
- package/logs/get_indexes-2025-09-12.log +84 -0
- package/logs/get_indexes-2025-09-15.log +56 -0
- package/logs/get_indexes-error-2025-09-12.log +6 -0
- package/logs/get_indexes-error-2025-09-15.log +0 -0
- package/logs/http_server-2025-09-12.log +2772 -0
- package/logs/http_server-2025-09-15.log +1276 -0
- package/logs/http_server-error-2025-09-12.log +212 -0
- package/logs/http_server-error-2025-09-15.log +44 -0
- package/logs/index_manager-2025-09-12.log +5031 -0
- package/logs/index_manager-2025-09-15.log +2909 -0
- package/logs/index_manager-error-2025-09-12.log +80 -0
- package/logs/index_manager-error-2025-09-15.log +38 -0
- package/logs/insert_one-2025-09-12.log +2181 -0
- package/logs/insert_one-2025-09-15.log +1293 -0
- package/logs/insert_one-error-2025-09-12.log +0 -0
- package/logs/insert_one-error-2025-09-15.log +0 -0
- package/logs/master-2025-09-12.log +1882 -0
- package/logs/master-2025-09-15.log +910 -0
- package/logs/master-error-2025-09-12.log +80 -0
- package/logs/master-error-2025-09-15.log +0 -0
- package/logs/operation_dispatcher-2025-09-12.log +751 -0
- package/logs/operation_dispatcher-2025-09-15.log +359 -0
- package/logs/operation_dispatcher-error-2025-09-12.log +33 -0
- package/logs/operation_dispatcher-error-2025-09-15.log +11 -0
- package/logs/performance_monitor-2025-09-12.log +14889 -0
- package/logs/performance_monitor-2025-09-15.log +6803 -0
- package/logs/performance_monitor-error-2025-09-12.log +0 -0
- package/logs/performance_monitor-error-2025-09-15.log +0 -0
- package/logs/query_engine-2025-09-12.log +5310 -0
- package/logs/query_engine-2025-09-15.log +2639 -0
- package/logs/query_engine-error-2025-09-12.log +0 -0
- package/logs/query_engine-error-2025-09-15.log +0 -0
- package/logs/recovery_manager-2025-09-12.log +462 -0
- package/logs/recovery_manager-2025-09-15.log +210 -0
- package/logs/recovery_manager-error-2025-09-12.log +22 -0
- package/logs/recovery_manager-error-2025-09-15.log +10 -0
- package/logs/replication-2025-09-12.log +1923 -0
- package/logs/replication-2025-09-15.log +917 -0
- package/logs/replication-error-2025-09-12.log +33 -0
- package/logs/replication-error-2025-09-15.log +15 -0
- package/logs/server-2025-09-12.log +2601 -0
- package/logs/server-2025-09-15.log +1191 -0
- package/logs/server-error-2025-09-12.log +0 -0
- package/logs/server-error-2025-09-15.log +0 -0
- package/logs/tcp_protocol-2025-09-12.log +22 -0
- package/logs/tcp_protocol-2025-09-15.log +10 -0
- package/logs/tcp_protocol-error-2025-09-12.log +22 -0
- package/logs/tcp_protocol-error-2025-09-15.log +10 -0
- package/logs/test-2025-09-12.log +0 -0
- package/logs/test-2025-09-15.log +0 -0
- package/logs/test-error-2025-09-12.log +0 -0
- package/logs/test-error-2025-09-15.log +0 -0
- package/logs/update_one-2025-09-12.log +173 -0
- package/logs/update_one-2025-09-15.log +118 -0
- package/logs/update_one-error-2025-09-12.log +0 -0
- package/logs/update_one-error-2025-09-15.log +0 -0
- package/logs/worker-2025-09-12.log +1457 -0
- package/logs/worker-2025-09-15.log +695 -0
- package/logs/worker-error-2025-09-12.log +0 -0
- package/logs/worker-error-2025-09-15.log +0 -0
- package/logs/write_forwarder-2025-09-12.log +1956 -0
- package/logs/write_forwarder-2025-09-15.log +932 -0
- package/logs/write_forwarder-error-2025-09-12.log +66 -0
- package/logs/write_forwarder-error-2025-09-15.log +30 -0
- package/logs/write_queue-2025-09-12.log +612 -0
- package/logs/write_queue-2025-09-15.log +301 -0
- package/logs/write_queue-error-2025-09-12.log +184 -0
- package/logs/write_queue-error-2025-09-15.log +83 -0
- package/package.json +48 -0
- package/prompts/01-core-infrastructure.md +56 -0
- package/prompts/02-secondary-indexing.md +65 -0
- package/prompts/03-write-serialization.md +63 -0
- package/prompts/04-enhanced-authentication.md +75 -0
- package/prompts/05-comprehensive-admin-operations.md +75 -0
- package/prompts/06-backup-and-restore-system.md +106 -0
- package/prompts/07-production-safety-features.md +107 -0
- package/prompts/08-tcp-client-library.md +121 -0
- package/prompts/09-api-method-chaining.md +134 -0
- package/prompts/10-automatic-index-creation.md +223 -0
- package/prompts/11-operation-naming-consistency.md +268 -0
- package/prompts/12-tcp-replication-system.md +333 -0
- package/prompts/13-master-read-write-operations.md +57 -0
- package/prompts/14-index-upsert-operations.md +68 -0
- package/prompts/15-client-api-return-types.md +81 -0
- package/prompts/16-server-setup-ui.md +97 -0
- package/prompts/17-emergency-password-change.md +108 -0
- package/prompts/18-joystick-framework-integration.md +116 -0
- package/prompts/19-api-key-authentication-system.md +137 -0
- package/prompts/20-configurable-server-port.md +105 -0
- package/prompts/21-multi-database-support.md +161 -0
- package/prompts/FULL_TEXT_SEARCH.md +293 -0
- package/prompts/PROMPTS.md +158 -0
- package/prompts/README.md +221 -0
- package/prompts/TYPESCRIPT_GENERATION.md +179 -0
- package/src/client/database.js +166 -0
- package/src/client/index.js +752 -0
- package/src/server/cluster/index.js +53 -0
- package/src/server/cluster/master.js +774 -0
- package/src/server/cluster/worker.js +537 -0
- package/src/server/index.js +540 -0
- package/src/server/lib/api_key_manager.js +473 -0
- package/src/server/lib/auth_manager.js +375 -0
- package/src/server/lib/auto_index_manager.js +681 -0
- package/src/server/lib/backup_manager.js +650 -0
- package/src/server/lib/connection_manager.js +218 -0
- package/src/server/lib/disk_utils.js +118 -0
- package/src/server/lib/http_server.js +1165 -0
- package/src/server/lib/index_manager.js +756 -0
- package/src/server/lib/load_settings.js +143 -0
- package/src/server/lib/logger.js +135 -0
- package/src/server/lib/op_types.js +29 -0
- package/src/server/lib/operation_dispatcher.js +268 -0
- package/src/server/lib/operations/admin.js +808 -0
- package/src/server/lib/operations/bulk_write.js +367 -0
- package/src/server/lib/operations/create_index.js +68 -0
- package/src/server/lib/operations/delete_one.js +114 -0
- package/src/server/lib/operations/drop_index.js +58 -0
- package/src/server/lib/operations/find.js +340 -0
- package/src/server/lib/operations/find_one.js +319 -0
- package/src/server/lib/operations/get_indexes.js +52 -0
- package/src/server/lib/operations/insert_one.js +113 -0
- package/src/server/lib/operations/update_one.js +225 -0
- package/src/server/lib/performance_monitor.js +313 -0
- package/src/server/lib/query_engine.js +243 -0
- package/src/server/lib/recovery_manager.js +388 -0
- package/src/server/lib/replication_manager.js +727 -0
- package/src/server/lib/safe_json_parse.js +21 -0
- package/src/server/lib/send_response.js +47 -0
- package/src/server/lib/tcp_protocol.js +130 -0
- package/src/server/lib/write_forwarder.js +636 -0
- package/src/server/lib/write_queue.js +335 -0
- package/test_data/data.mdb +0 -0
- package/test_data/lock.mdb +0 -0
- package/tests/client/index.test.js +1232 -0
- package/tests/server/cluster/cluster.test.js +248 -0
- package/tests/server/cluster/master_read_write_operations.test.js +577 -0
- package/tests/server/index.test.js +651 -0
- package/tests/server/integration/authentication_integration.test.js +294 -0
- package/tests/server/integration/auto_indexing_integration.test.js +268 -0
- package/tests/server/integration/backup_integration.test.js +513 -0
- package/tests/server/integration/indexing_integration.test.js +126 -0
- package/tests/server/integration/production_safety_integration.test.js +358 -0
- package/tests/server/integration/replication_integration.test.js +227 -0
- package/tests/server/integration/write_serialization_integration.test.js +246 -0
- package/tests/server/lib/api_key_manager.test.js +516 -0
- package/tests/server/lib/auth_manager.test.js +317 -0
- package/tests/server/lib/auto_index_manager.test.js +275 -0
- package/tests/server/lib/backup_manager.test.js +238 -0
- package/tests/server/lib/connection_manager.test.js +221 -0
- package/tests/server/lib/disk_utils.test.js +63 -0
- package/tests/server/lib/http_server.test.js +389 -0
- package/tests/server/lib/index_manager.test.js +301 -0
- package/tests/server/lib/load_settings.test.js +107 -0
- package/tests/server/lib/load_settings_port_config.test.js +243 -0
- package/tests/server/lib/logger.test.js +282 -0
- package/tests/server/lib/operations/admin.test.js +638 -0
- package/tests/server/lib/operations/bulk_write.test.js +128 -0
- package/tests/server/lib/operations/create_index.test.js +138 -0
- package/tests/server/lib/operations/delete_one.test.js +52 -0
- package/tests/server/lib/operations/drop_index.test.js +72 -0
- package/tests/server/lib/operations/find.test.js +93 -0
- package/tests/server/lib/operations/find_one.test.js +91 -0
- package/tests/server/lib/operations/get_indexes.test.js +87 -0
- package/tests/server/lib/operations/insert_one.test.js +42 -0
- package/tests/server/lib/operations/update_one.test.js +89 -0
- package/tests/server/lib/performance_monitor.test.js +185 -0
- package/tests/server/lib/query_engine.test.js +46 -0
- package/tests/server/lib/recovery_manager.test.js +414 -0
- package/tests/server/lib/replication_manager.test.js +202 -0
- package/tests/server/lib/safe_json_parse.test.js +45 -0
- package/tests/server/lib/send_response.test.js +155 -0
- package/tests/server/lib/tcp_protocol.test.js +169 -0
- package/tests/server/lib/write_forwarder.test.js +258 -0
- package/tests/server/lib/write_queue.test.js +255 -0
- package/tsconfig.json +30 -0
- package/types/client/index.d.ts +447 -0
- package/types/server/cluster/index.d.ts +28 -0
- package/types/server/cluster/master.d.ts +115 -0
- package/types/server/cluster/worker.d.ts +1 -0
- package/types/server/lib/auth_manager.d.ts +13 -0
- package/types/server/lib/backup_manager.d.ts +43 -0
- package/types/server/lib/connection_manager.d.ts +15 -0
- package/types/server/lib/disk_utils.d.ts +3 -0
- package/types/server/lib/index_manager.d.ts +24 -0
- package/types/server/lib/load_settings.d.ts +4 -0
- package/types/server/lib/logger.d.ts +44 -0
- package/types/server/lib/op_types.d.ts +6 -0
- package/types/server/lib/performance_monitor.d.ts +68 -0
- package/types/server/lib/query_engine.d.ts +10 -0
- package/types/server/lib/safe_json_parse.d.ts +7 -0
- package/types/server/lib/send_response.d.ts +3 -0
- package/types/server/lib/tcp_protocol.d.ts +12 -0
- package/types/server/lib/write_queue.d.ts +2 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { decode as decode_messagepack } from 'msgpackr';
|
|
3
|
+
import { send_success, send_error, send_message } from '../../../src/server/lib/send_response.js';
|
|
4
|
+
|
|
5
|
+
class MockSocket {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.written_data = [];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
write(data) {
|
|
11
|
+
this.written_data.push(data);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get_last_written() {
|
|
15
|
+
return this.written_data[this.written_data.length - 1];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get_decoded_last_written() {
|
|
19
|
+
const last_data = this.get_last_written();
|
|
20
|
+
|
|
21
|
+
if (last_data.length < 4) {
|
|
22
|
+
throw new Error('Invalid message format: too short');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const length = last_data.readUInt32BE(0);
|
|
26
|
+
const payload = last_data.slice(4);
|
|
27
|
+
|
|
28
|
+
if (payload.length !== length) {
|
|
29
|
+
throw new Error(`Invalid message format: expected ${length} bytes, got ${payload.length}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return decode_messagepack(payload);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
test('send_success sends properly formatted success response', (t) => {
|
|
37
|
+
const mock_socket = new MockSocket();
|
|
38
|
+
const test_data = { user_id: 123, name: 'test' };
|
|
39
|
+
|
|
40
|
+
send_success(mock_socket, test_data);
|
|
41
|
+
|
|
42
|
+
const response = mock_socket.get_decoded_last_written();
|
|
43
|
+
|
|
44
|
+
t.is(response.ok, true);
|
|
45
|
+
t.deepEqual(response.data, test_data);
|
|
46
|
+
t.is(response.error, undefined);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('send_success with empty data object', (t) => {
|
|
50
|
+
const mock_socket = new MockSocket();
|
|
51
|
+
|
|
52
|
+
send_success(mock_socket, {});
|
|
53
|
+
|
|
54
|
+
const response = mock_socket.get_decoded_last_written();
|
|
55
|
+
|
|
56
|
+
t.is(response.ok, true);
|
|
57
|
+
t.deepEqual(response.data, {});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('send_success with no data parameter uses empty object', (t) => {
|
|
61
|
+
const mock_socket = new MockSocket();
|
|
62
|
+
|
|
63
|
+
send_success(mock_socket);
|
|
64
|
+
|
|
65
|
+
const response = mock_socket.get_decoded_last_written();
|
|
66
|
+
|
|
67
|
+
t.is(response.ok, true);
|
|
68
|
+
t.deepEqual(response.data, {});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('send_error sends properly formatted error response', (t) => {
|
|
72
|
+
const mock_socket = new MockSocket();
|
|
73
|
+
const test_error = { message: 'Something went wrong', code: 500 };
|
|
74
|
+
|
|
75
|
+
send_error(mock_socket, test_error);
|
|
76
|
+
|
|
77
|
+
const response = mock_socket.get_decoded_last_written();
|
|
78
|
+
|
|
79
|
+
t.is(response.ok, false);
|
|
80
|
+
t.deepEqual(response.error, test_error);
|
|
81
|
+
t.is(response.data, undefined);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('send_error with empty error object', (t) => {
|
|
85
|
+
const mock_socket = new MockSocket();
|
|
86
|
+
|
|
87
|
+
send_error(mock_socket, {});
|
|
88
|
+
|
|
89
|
+
const response = mock_socket.get_decoded_last_written();
|
|
90
|
+
|
|
91
|
+
t.is(response.ok, false);
|
|
92
|
+
t.deepEqual(response.error, {});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('send_error with no error parameter uses empty object', (t) => {
|
|
96
|
+
const mock_socket = new MockSocket();
|
|
97
|
+
|
|
98
|
+
send_error(mock_socket);
|
|
99
|
+
|
|
100
|
+
const response = mock_socket.get_decoded_last_written();
|
|
101
|
+
|
|
102
|
+
t.is(response.ok, false);
|
|
103
|
+
t.deepEqual(response.error, {});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('send_message sends message in data object', (t) => {
|
|
107
|
+
const mock_socket = new MockSocket();
|
|
108
|
+
const test_message = 'Operation completed successfully';
|
|
109
|
+
|
|
110
|
+
send_message(mock_socket, test_message);
|
|
111
|
+
|
|
112
|
+
const response = mock_socket.get_decoded_last_written();
|
|
113
|
+
|
|
114
|
+
t.is(response.ok, true);
|
|
115
|
+
t.deepEqual(response.data, { message: test_message });
|
|
116
|
+
t.is(response.error, undefined);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('send_message with empty string', (t) => {
|
|
120
|
+
const mock_socket = new MockSocket();
|
|
121
|
+
|
|
122
|
+
send_message(mock_socket, '');
|
|
123
|
+
|
|
124
|
+
const response = mock_socket.get_decoded_last_written();
|
|
125
|
+
|
|
126
|
+
t.is(response.ok, true);
|
|
127
|
+
t.deepEqual(response.data, { message: '' });
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('send_message with no message parameter uses empty string', (t) => {
|
|
131
|
+
const mock_socket = new MockSocket();
|
|
132
|
+
|
|
133
|
+
send_message(mock_socket);
|
|
134
|
+
|
|
135
|
+
const response = mock_socket.get_decoded_last_written();
|
|
136
|
+
|
|
137
|
+
t.is(response.ok, true);
|
|
138
|
+
t.deepEqual(response.data, { message: '' });
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('all functions encode responses as messagepack', (t) => {
|
|
142
|
+
const mock_socket = new MockSocket();
|
|
143
|
+
|
|
144
|
+
send_success(mock_socket, { test: 'data' });
|
|
145
|
+
const success_data = mock_socket.get_last_written();
|
|
146
|
+
t.true(Buffer.isBuffer(success_data));
|
|
147
|
+
|
|
148
|
+
send_error(mock_socket, { test: 'error' });
|
|
149
|
+
const error_data = mock_socket.get_last_written();
|
|
150
|
+
t.true(Buffer.isBuffer(error_data));
|
|
151
|
+
|
|
152
|
+
send_message(mock_socket, 'test message');
|
|
153
|
+
const message_data = mock_socket.get_last_written();
|
|
154
|
+
t.true(Buffer.isBuffer(message_data));
|
|
155
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { encode_message, create_message_parser } from '../../../src/server/lib/tcp_protocol.js';
|
|
3
|
+
|
|
4
|
+
test('encode_message - should encode message with length prefix', (t) => {
|
|
5
|
+
const data = { test: 'data', number: 42 };
|
|
6
|
+
const result = encode_message(data);
|
|
7
|
+
|
|
8
|
+
t.true(Buffer.isBuffer(result));
|
|
9
|
+
t.true(result.length > 4);
|
|
10
|
+
|
|
11
|
+
const length = result.readUInt32BE(0);
|
|
12
|
+
const payload = result.slice(4);
|
|
13
|
+
|
|
14
|
+
t.is(payload.length, length);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('encode_message - should handle empty object', (t) => {
|
|
18
|
+
const data = {};
|
|
19
|
+
const result = encode_message(data);
|
|
20
|
+
|
|
21
|
+
t.true(Buffer.isBuffer(result));
|
|
22
|
+
|
|
23
|
+
const length = result.readUInt32BE(0);
|
|
24
|
+
t.true(length > 0);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('encode_message - should handle complex nested data', (t) => {
|
|
28
|
+
const data = {
|
|
29
|
+
nested: {
|
|
30
|
+
array: [1, 2, 3],
|
|
31
|
+
string: 'test',
|
|
32
|
+
boolean: true
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const result = encode_message(data);
|
|
37
|
+
|
|
38
|
+
t.true(Buffer.isBuffer(result));
|
|
39
|
+
t.true(result.length > 4);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('create_message_parser - should parse single complete message', (t) => {
|
|
43
|
+
const parser = create_message_parser();
|
|
44
|
+
const test_data = { op: 'test', data: { value: 123 } };
|
|
45
|
+
const encoded = encode_message(test_data);
|
|
46
|
+
|
|
47
|
+
const messages = parser.parse_messages(encoded);
|
|
48
|
+
|
|
49
|
+
t.is(messages.length, 1);
|
|
50
|
+
t.deepEqual(messages[0], test_data);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('create_message_parser - should parse multiple messages', (t) => {
|
|
54
|
+
const parser = create_message_parser();
|
|
55
|
+
const test_data_1 = { op: 'test1', data: { value: 123 } };
|
|
56
|
+
const test_data_2 = { op: 'test2', data: { value: 456 } };
|
|
57
|
+
|
|
58
|
+
const encoded_1 = encode_message(test_data_1);
|
|
59
|
+
const encoded_2 = encode_message(test_data_2);
|
|
60
|
+
const combined = Buffer.concat([encoded_1, encoded_2]);
|
|
61
|
+
|
|
62
|
+
const messages = parser.parse_messages(combined);
|
|
63
|
+
|
|
64
|
+
t.is(messages.length, 2);
|
|
65
|
+
t.deepEqual(messages[0], test_data_1);
|
|
66
|
+
t.deepEqual(messages[1], test_data_2);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('create_message_parser - should handle partial messages', (t) => {
|
|
70
|
+
const parser = create_message_parser();
|
|
71
|
+
const test_data = { op: 'test', data: { value: 123 } };
|
|
72
|
+
const encoded = encode_message(test_data);
|
|
73
|
+
|
|
74
|
+
const partial_1 = encoded.slice(0, 2);
|
|
75
|
+
const partial_2 = encoded.slice(2);
|
|
76
|
+
|
|
77
|
+
let messages = parser.parse_messages(partial_1);
|
|
78
|
+
t.is(messages.length, 0);
|
|
79
|
+
|
|
80
|
+
messages = parser.parse_messages(partial_2);
|
|
81
|
+
t.is(messages.length, 1);
|
|
82
|
+
t.deepEqual(messages[0], test_data);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('create_message_parser - should handle partial length prefix', (t) => {
|
|
86
|
+
const parser = create_message_parser();
|
|
87
|
+
const test_data = { op: 'test', data: { value: 123 } };
|
|
88
|
+
const encoded = encode_message(test_data);
|
|
89
|
+
|
|
90
|
+
const partial_length = encoded.slice(0, 3);
|
|
91
|
+
const remaining = encoded.slice(3);
|
|
92
|
+
|
|
93
|
+
let messages = parser.parse_messages(partial_length);
|
|
94
|
+
t.is(messages.length, 0);
|
|
95
|
+
|
|
96
|
+
messages = parser.parse_messages(remaining);
|
|
97
|
+
t.is(messages.length, 1);
|
|
98
|
+
t.deepEqual(messages[0], test_data);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('create_message_parser - should handle partial payload', (t) => {
|
|
102
|
+
const parser = create_message_parser();
|
|
103
|
+
const test_data = { op: 'test', data: { value: 123 } };
|
|
104
|
+
const encoded = encode_message(test_data);
|
|
105
|
+
|
|
106
|
+
const length_and_partial = encoded.slice(0, encoded.length - 2);
|
|
107
|
+
const remaining_payload = encoded.slice(encoded.length - 2);
|
|
108
|
+
|
|
109
|
+
let messages = parser.parse_messages(length_and_partial);
|
|
110
|
+
t.is(messages.length, 0);
|
|
111
|
+
|
|
112
|
+
messages = parser.parse_messages(remaining_payload);
|
|
113
|
+
t.is(messages.length, 1);
|
|
114
|
+
t.deepEqual(messages[0], test_data);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('create_message_parser - should throw on invalid messagepack', (t) => {
|
|
118
|
+
const parser = create_message_parser();
|
|
119
|
+
|
|
120
|
+
const invalid_length = Buffer.allocUnsafe(4);
|
|
121
|
+
invalid_length.writeUInt32BE(5, 0);
|
|
122
|
+
const invalid_payload = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
|
|
123
|
+
const invalid_message = Buffer.concat([invalid_length, invalid_payload]);
|
|
124
|
+
|
|
125
|
+
t.throws(
|
|
126
|
+
() => {
|
|
127
|
+
parser.parse_messages(invalid_message);
|
|
128
|
+
},
|
|
129
|
+
{ message: /Invalid message format/ }
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('create_message_parser - reset should clear internal state', (t) => {
|
|
134
|
+
const parser = create_message_parser();
|
|
135
|
+
const test_data = { op: 'test', data: { value: 123 } };
|
|
136
|
+
const encoded = encode_message(test_data);
|
|
137
|
+
|
|
138
|
+
const partial = encoded.slice(0, 2);
|
|
139
|
+
parser.parse_messages(partial);
|
|
140
|
+
|
|
141
|
+
parser.reset();
|
|
142
|
+
|
|
143
|
+
const messages = parser.parse_messages(encoded);
|
|
144
|
+
t.is(messages.length, 1);
|
|
145
|
+
t.deepEqual(messages[0], test_data);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('create_message_parser - should handle empty buffer', (t) => {
|
|
149
|
+
const parser = create_message_parser();
|
|
150
|
+
const empty_buffer = Buffer.alloc(0);
|
|
151
|
+
|
|
152
|
+
const messages = parser.parse_messages(empty_buffer);
|
|
153
|
+
|
|
154
|
+
t.is(messages.length, 0);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('create_message_parser - should handle zero-length message', (t) => {
|
|
158
|
+
const parser = create_message_parser();
|
|
159
|
+
|
|
160
|
+
const zero_length = Buffer.allocUnsafe(4);
|
|
161
|
+
zero_length.writeUInt32BE(0, 0);
|
|
162
|
+
|
|
163
|
+
t.throws(
|
|
164
|
+
() => {
|
|
165
|
+
parser.parse_messages(zero_length);
|
|
166
|
+
},
|
|
167
|
+
{ message: /Invalid message format/ }
|
|
168
|
+
);
|
|
169
|
+
});
|
|
@@ -0,0 +1,258 @@
|
|
|
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
|
+
});
|