@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,577 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import net from 'net';
|
|
3
|
+
import cluster from 'cluster';
|
|
4
|
+
import { encode_message, create_message_parser } from '../../../src/server/lib/tcp_protocol.js';
|
|
5
|
+
import { start_cluster } from '../../../src/server/cluster/index.js';
|
|
6
|
+
import { setup_authentication, reset_auth_state } from '../../../src/server/lib/auth_manager.js';
|
|
7
|
+
|
|
8
|
+
const create_test_settings = () => ({
|
|
9
|
+
port: 1983,
|
|
10
|
+
cluster: true,
|
|
11
|
+
worker_count: 2,
|
|
12
|
+
authentication: {},
|
|
13
|
+
backup: { enabled: false },
|
|
14
|
+
replication: { enabled: false, role: "primary" },
|
|
15
|
+
auto_indexing: { enabled: true, threshold: 100 },
|
|
16
|
+
performance: {
|
|
17
|
+
monitoring_enabled: true,
|
|
18
|
+
log_slow_queries: true,
|
|
19
|
+
slow_query_threshold_ms: 1000
|
|
20
|
+
},
|
|
21
|
+
logging: { level: "info", structured: true }
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const cleanup_cluster_state = async () => {
|
|
25
|
+
// Force kill any remaining workers from previous tests
|
|
26
|
+
for (const worker_id in cluster.workers) {
|
|
27
|
+
const worker = cluster.workers[worker_id];
|
|
28
|
+
if (worker && !worker.isDead()) {
|
|
29
|
+
try {
|
|
30
|
+
worker.kill('SIGKILL');
|
|
31
|
+
} catch (error) {
|
|
32
|
+
// Ignore kill errors
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Clear cluster workers map
|
|
38
|
+
for (const worker_id in cluster.workers) {
|
|
39
|
+
delete cluster.workers[worker_id];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Remove all cluster event listeners to prevent cross-test interference
|
|
43
|
+
cluster.removeAllListeners();
|
|
44
|
+
|
|
45
|
+
// Wait longer for cleanup to complete
|
|
46
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
test.beforeEach(async () => {
|
|
50
|
+
reset_auth_state();
|
|
51
|
+
shared_password = null; // Reset shared password for each test
|
|
52
|
+
process.env.JOYSTICK_DB_SETTINGS = JSON.stringify(create_test_settings());
|
|
53
|
+
|
|
54
|
+
// Clean up any lingering cluster state
|
|
55
|
+
await cleanup_cluster_state();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test.afterEach(async () => {
|
|
59
|
+
reset_auth_state();
|
|
60
|
+
shared_password = null; // Reset shared password after each test
|
|
61
|
+
delete process.env.JOYSTICK_DB_SETTINGS;
|
|
62
|
+
|
|
63
|
+
// Clean up cluster state after each test
|
|
64
|
+
await cleanup_cluster_state();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const create_client = (port) => {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const client = net.createConnection(port, 'localhost');
|
|
70
|
+
const parser = create_message_parser();
|
|
71
|
+
|
|
72
|
+
client.on('connect', () => {
|
|
73
|
+
resolve({
|
|
74
|
+
client,
|
|
75
|
+
send: (data) => {
|
|
76
|
+
const encoded = encode_message(data);
|
|
77
|
+
client.write(encoded);
|
|
78
|
+
},
|
|
79
|
+
receive: () => {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const handler = (data) => {
|
|
82
|
+
try {
|
|
83
|
+
const messages = parser.parse_messages(data);
|
|
84
|
+
for (const message of messages) {
|
|
85
|
+
client.off('data', handler);
|
|
86
|
+
client.off('close', close_handler);
|
|
87
|
+
client.off('error', error_handler);
|
|
88
|
+
resolve(message);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Continue listening
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const close_handler = () => {
|
|
97
|
+
client.off('data', handler);
|
|
98
|
+
client.off('error', error_handler);
|
|
99
|
+
reject(new Error('Connection closed before receiving response'));
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const error_handler = (error) => {
|
|
103
|
+
client.off('data', handler);
|
|
104
|
+
client.off('close', close_handler);
|
|
105
|
+
reject(error);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
client.on('data', handler);
|
|
109
|
+
client.on('close', close_handler);
|
|
110
|
+
client.on('error', error_handler);
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
close: () => {
|
|
114
|
+
client.end();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
client.on('error', reject);
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
let shared_password = null;
|
|
124
|
+
|
|
125
|
+
const authenticate_client = async (client) => {
|
|
126
|
+
// Setup authentication only once and reuse the password
|
|
127
|
+
if (!shared_password) {
|
|
128
|
+
shared_password = setup_authentication();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
client.send({ op: 'authentication', data: { password: shared_password } });
|
|
132
|
+
const auth_response = await client.receive();
|
|
133
|
+
|
|
134
|
+
if (auth_response.ok !== 1) {
|
|
135
|
+
throw new Error(`Authentication failed: ${auth_response.error || 'Unknown error'}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return shared_password;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
test.serial('master node handles read operations - find_one', async (t) => {
|
|
142
|
+
process.env.NODE_ENV = 'test';
|
|
143
|
+
|
|
144
|
+
const master = start_cluster({
|
|
145
|
+
worker_count: 1,
|
|
146
|
+
port: 1990
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
let client = null;
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
153
|
+
|
|
154
|
+
client = await create_client(1990);
|
|
155
|
+
|
|
156
|
+
// Authenticate using setup flow
|
|
157
|
+
await authenticate_client(client);
|
|
158
|
+
|
|
159
|
+
// Insert a document first
|
|
160
|
+
client.send({
|
|
161
|
+
op: 'insert_one',
|
|
162
|
+
data: {
|
|
163
|
+
collection: 'test_master_reads',
|
|
164
|
+
document: { name: 'test_doc', value: 42 }
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
const insert_response = await client.receive();
|
|
168
|
+
t.is(insert_response.ok, 1);
|
|
169
|
+
|
|
170
|
+
// Wait a bit before the read operation to ensure write is fully committed
|
|
171
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
172
|
+
|
|
173
|
+
// Test find_one operation (read operation)
|
|
174
|
+
client.send({
|
|
175
|
+
op: 'find_one',
|
|
176
|
+
data: {
|
|
177
|
+
collection: 'test_master_reads',
|
|
178
|
+
filter: { name: 'test_doc' }
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
const find_response = await client.receive();
|
|
182
|
+
t.is(find_response.ok, 1);
|
|
183
|
+
t.truthy(find_response.name, 'Response should have name field');
|
|
184
|
+
t.is(find_response.name, 'test_doc');
|
|
185
|
+
t.is(find_response.value, 42);
|
|
186
|
+
|
|
187
|
+
} finally {
|
|
188
|
+
if (client) {
|
|
189
|
+
try {
|
|
190
|
+
client.close();
|
|
191
|
+
} catch (error) {
|
|
192
|
+
// Ignore cleanup errors
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Wait for any pending operations to complete before shutdown
|
|
197
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
await master.shutdown();
|
|
201
|
+
} catch (error) {
|
|
202
|
+
// Ignore shutdown errors in tests
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
206
|
+
|
|
207
|
+
if (global.gc) {
|
|
208
|
+
global.gc();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test.serial('master node handles read operations - find', async (t) => {
|
|
214
|
+
process.env.NODE_ENV = 'test';
|
|
215
|
+
|
|
216
|
+
const master = start_cluster({
|
|
217
|
+
worker_count: 1,
|
|
218
|
+
port: 1991
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
let client = null;
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
225
|
+
|
|
226
|
+
client = await create_client(1991);
|
|
227
|
+
|
|
228
|
+
// Authenticate using setup flow
|
|
229
|
+
await authenticate_client(client);
|
|
230
|
+
|
|
231
|
+
// Insert multiple documents with longer wait between inserts
|
|
232
|
+
client.send({
|
|
233
|
+
op: 'insert_one',
|
|
234
|
+
data: {
|
|
235
|
+
collection: 'test_master_find',
|
|
236
|
+
document: { category: 'test', value: 1 }
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
const insert1_response = await client.receive();
|
|
240
|
+
t.is(insert1_response.ok, 1);
|
|
241
|
+
|
|
242
|
+
// Wait longer between inserts to ensure proper commit
|
|
243
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
244
|
+
|
|
245
|
+
client.send({
|
|
246
|
+
op: 'insert_one',
|
|
247
|
+
data: {
|
|
248
|
+
collection: 'test_master_find',
|
|
249
|
+
document: { category: 'test', value: 2 }
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
const insert2_response = await client.receive();
|
|
253
|
+
t.is(insert2_response.ok, 1);
|
|
254
|
+
|
|
255
|
+
// Wait longer to ensure both documents are fully committed
|
|
256
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
257
|
+
|
|
258
|
+
// Test find operation (read operation)
|
|
259
|
+
client.send({
|
|
260
|
+
op: 'find',
|
|
261
|
+
data: {
|
|
262
|
+
collection: 'test_master_find',
|
|
263
|
+
filter: { category: 'test' }
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
const find_response = await client.receive();
|
|
267
|
+
t.is(find_response.ok, 1);
|
|
268
|
+
t.is(Array.isArray(find_response.documents), true);
|
|
269
|
+
t.is(find_response.documents.length >= 2, true);
|
|
270
|
+
|
|
271
|
+
} finally {
|
|
272
|
+
if (client) {
|
|
273
|
+
try {
|
|
274
|
+
client.close();
|
|
275
|
+
} catch (error) {
|
|
276
|
+
// Ignore cleanup errors
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Wait for any pending operations to complete before shutdown
|
|
281
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
await master.shutdown();
|
|
285
|
+
} catch (error) {
|
|
286
|
+
// Ignore shutdown errors in tests
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
290
|
+
|
|
291
|
+
if (global.gc) {
|
|
292
|
+
global.gc();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test.serial('master node handles read operations - get_indexes', async (t) => {
|
|
298
|
+
process.env.NODE_ENV = 'test';
|
|
299
|
+
|
|
300
|
+
const master = start_cluster({
|
|
301
|
+
worker_count: 1,
|
|
302
|
+
port: 1992
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
let client = null;
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
309
|
+
|
|
310
|
+
client = await create_client(1992);
|
|
311
|
+
|
|
312
|
+
// Authenticate using setup flow
|
|
313
|
+
await authenticate_client(client);
|
|
314
|
+
|
|
315
|
+
// Create an index first
|
|
316
|
+
client.send({
|
|
317
|
+
op: 'create_index',
|
|
318
|
+
data: {
|
|
319
|
+
collection: 'test_master_indexes',
|
|
320
|
+
field: 'name',
|
|
321
|
+
options: {}
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
const create_index_response = await client.receive();
|
|
325
|
+
t.is(create_index_response.ok, 1);
|
|
326
|
+
|
|
327
|
+
// Test get_indexes operation (read operation)
|
|
328
|
+
client.send({
|
|
329
|
+
op: 'get_indexes',
|
|
330
|
+
data: {
|
|
331
|
+
collection: 'test_master_indexes'
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
const get_indexes_response = await client.receive();
|
|
335
|
+
t.is(get_indexes_response.ok, 1);
|
|
336
|
+
t.is(Array.isArray(get_indexes_response.indexes), true);
|
|
337
|
+
t.is(get_indexes_response.indexes.length, 1);
|
|
338
|
+
t.is(get_indexes_response.indexes[0].field, 'name');
|
|
339
|
+
|
|
340
|
+
} finally {
|
|
341
|
+
if (client) {
|
|
342
|
+
try {
|
|
343
|
+
client.close();
|
|
344
|
+
} catch (error) {
|
|
345
|
+
// Ignore cleanup errors
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Wait for any pending operations to complete before shutdown
|
|
350
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
await master.shutdown();
|
|
354
|
+
} catch (error) {
|
|
355
|
+
// Ignore shutdown errors in tests
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
359
|
+
|
|
360
|
+
if (global.gc) {
|
|
361
|
+
global.gc();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
test.serial('master node handles mixed read and write operations', async (t) => {
|
|
367
|
+
process.env.NODE_ENV = 'test';
|
|
368
|
+
|
|
369
|
+
const master = start_cluster({
|
|
370
|
+
worker_count: 2,
|
|
371
|
+
port: 1993
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
let client = null;
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
378
|
+
|
|
379
|
+
client = await create_client(1993);
|
|
380
|
+
|
|
381
|
+
// Authenticate using setup flow
|
|
382
|
+
await authenticate_client(client);
|
|
383
|
+
|
|
384
|
+
// Mixed operations sequence with proper waits
|
|
385
|
+
|
|
386
|
+
// Use unique document name to avoid conflicts with previous test runs
|
|
387
|
+
const unique_doc_name = `doc1_${Date.now()}`;
|
|
388
|
+
|
|
389
|
+
// 1. Write: Insert document
|
|
390
|
+
client.send({
|
|
391
|
+
op: 'insert_one',
|
|
392
|
+
data: {
|
|
393
|
+
collection: 'test_mixed_ops',
|
|
394
|
+
document: { name: unique_doc_name, status: 'active' }
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
const insert_response = await client.receive();
|
|
398
|
+
t.is(insert_response.ok, 1);
|
|
399
|
+
|
|
400
|
+
// Wait for write to commit
|
|
401
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
402
|
+
|
|
403
|
+
// 2. Read: Find the document
|
|
404
|
+
client.send({
|
|
405
|
+
op: 'find_one',
|
|
406
|
+
data: {
|
|
407
|
+
collection: 'test_mixed_ops',
|
|
408
|
+
filter: { name: unique_doc_name }
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
const find_response = await client.receive();
|
|
412
|
+
t.is(find_response.ok, 1);
|
|
413
|
+
t.is(find_response.name, unique_doc_name);
|
|
414
|
+
t.is(find_response.status, 'active');
|
|
415
|
+
|
|
416
|
+
// 3. Write: Update document
|
|
417
|
+
client.send({
|
|
418
|
+
op: 'update_one',
|
|
419
|
+
data: {
|
|
420
|
+
collection: 'test_mixed_ops',
|
|
421
|
+
filter: { name: unique_doc_name },
|
|
422
|
+
update: { $set: { status: 'updated' } }
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
const update_response = await client.receive();
|
|
426
|
+
t.is(update_response.ok, 1);
|
|
427
|
+
t.is(update_response.modified_count, 1);
|
|
428
|
+
|
|
429
|
+
// Wait for update to commit
|
|
430
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
431
|
+
|
|
432
|
+
// 4. Read: Verify update
|
|
433
|
+
client.send({
|
|
434
|
+
op: 'find_one',
|
|
435
|
+
data: {
|
|
436
|
+
collection: 'test_mixed_ops',
|
|
437
|
+
filter: { name: unique_doc_name }
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
const find_updated_response = await client.receive();
|
|
441
|
+
t.is(find_updated_response.ok, 1);
|
|
442
|
+
t.is(find_updated_response.status, 'updated');
|
|
443
|
+
|
|
444
|
+
// 5. Write: Create index
|
|
445
|
+
client.send({
|
|
446
|
+
op: 'create_index',
|
|
447
|
+
data: {
|
|
448
|
+
collection: 'test_mixed_ops',
|
|
449
|
+
field: 'status',
|
|
450
|
+
options: {}
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
const create_index_response = await client.receive();
|
|
454
|
+
t.is(create_index_response.ok, 1);
|
|
455
|
+
|
|
456
|
+
// 6. Read: Get indexes
|
|
457
|
+
client.send({
|
|
458
|
+
op: 'get_indexes',
|
|
459
|
+
data: {
|
|
460
|
+
collection: 'test_mixed_ops'
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
const get_indexes_response = await client.receive();
|
|
464
|
+
t.is(get_indexes_response.ok, 1);
|
|
465
|
+
t.is(get_indexes_response.indexes.length, 1);
|
|
466
|
+
|
|
467
|
+
} finally {
|
|
468
|
+
if (client) {
|
|
469
|
+
try {
|
|
470
|
+
client.close();
|
|
471
|
+
} catch (error) {
|
|
472
|
+
// Ignore cleanup errors
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Wait for any pending operations to complete before shutdown
|
|
477
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
478
|
+
|
|
479
|
+
try {
|
|
480
|
+
await master.shutdown();
|
|
481
|
+
} catch (error) {
|
|
482
|
+
// Ignore shutdown errors in tests
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
486
|
+
|
|
487
|
+
if (global.gc) {
|
|
488
|
+
global.gc();
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
test.serial('master node handles concurrent read and write operations', async (t) => {
|
|
494
|
+
process.env.NODE_ENV = 'test';
|
|
495
|
+
|
|
496
|
+
const master = start_cluster({
|
|
497
|
+
worker_count: 2,
|
|
498
|
+
port: 1994
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const clients = [];
|
|
502
|
+
|
|
503
|
+
try {
|
|
504
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
505
|
+
|
|
506
|
+
// Create multiple clients and authenticate each one separately
|
|
507
|
+
for (let i = 0; i < 3; i++) {
|
|
508
|
+
const client = await create_client(1994);
|
|
509
|
+
await authenticate_client(client);
|
|
510
|
+
clients.push(client);
|
|
511
|
+
|
|
512
|
+
// Wait between client connections to avoid auth conflicts
|
|
513
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Sequential operations instead of concurrent to avoid auth conflicts
|
|
517
|
+
|
|
518
|
+
// Client 1: Write operation
|
|
519
|
+
clients[0].send({
|
|
520
|
+
op: 'insert_one',
|
|
521
|
+
data: {
|
|
522
|
+
collection: 'test_concurrent',
|
|
523
|
+
document: { id: 1, type: 'write' }
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
const insert_result = await clients[0].receive();
|
|
527
|
+
t.is(insert_result.ok, 1);
|
|
528
|
+
|
|
529
|
+
// Wait for write to commit
|
|
530
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
531
|
+
|
|
532
|
+
// Client 2: Read operation
|
|
533
|
+
clients[1].send({
|
|
534
|
+
op: 'find',
|
|
535
|
+
data: {
|
|
536
|
+
collection: 'test_concurrent',
|
|
537
|
+
filter: {}
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
const find_result = await clients[1].receive();
|
|
541
|
+
t.is(find_result.ok, 1);
|
|
542
|
+
|
|
543
|
+
// Client 3: Index operation
|
|
544
|
+
clients[2].send({
|
|
545
|
+
op: 'get_indexes',
|
|
546
|
+
data: {
|
|
547
|
+
collection: 'test_concurrent'
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
const indexes_result = await clients[2].receive();
|
|
551
|
+
t.is(indexes_result.ok, 1);
|
|
552
|
+
|
|
553
|
+
} finally {
|
|
554
|
+
for (const client of clients) {
|
|
555
|
+
try {
|
|
556
|
+
client.close();
|
|
557
|
+
} catch (error) {
|
|
558
|
+
// Ignore cleanup errors
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// Wait for any pending operations to complete before shutdown
|
|
563
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
564
|
+
|
|
565
|
+
try {
|
|
566
|
+
await master.shutdown();
|
|
567
|
+
} catch (error) {
|
|
568
|
+
// Ignore shutdown errors in tests
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
572
|
+
|
|
573
|
+
if (global.gc) {
|
|
574
|
+
global.gc();
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
});
|