@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,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Write queue system for JoystickDB providing serialized write operations.
|
|
3
|
+
* Ensures write operations are processed sequentially to maintain data consistency and ACID properties.
|
|
4
|
+
* Includes retry logic, backoff strategies, performance monitoring, and graceful shutdown capabilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import create_logger from './logger.js';
|
|
8
|
+
|
|
9
|
+
const { create_context_logger } = create_logger('write_queue');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Write queue class that serializes database write operations to ensure consistency.
|
|
13
|
+
* Provides queuing, retry logic, performance tracking, and graceful shutdown.
|
|
14
|
+
*/
|
|
15
|
+
class WriteQueue {
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new WriteQueue instance.
|
|
18
|
+
* Initializes queue, processing state, statistics, and logging.
|
|
19
|
+
*/
|
|
20
|
+
constructor() {
|
|
21
|
+
/** @type {Array<Object>} Queue of pending write operations */
|
|
22
|
+
this.queue = [];
|
|
23
|
+
|
|
24
|
+
/** @type {boolean} Whether queue is currently processing operations */
|
|
25
|
+
this.processing = false;
|
|
26
|
+
|
|
27
|
+
/** @type {boolean} Whether queue is shutting down */
|
|
28
|
+
this.shutting_down = false;
|
|
29
|
+
|
|
30
|
+
/** @type {Object} Performance and operational statistics */
|
|
31
|
+
this.stats = {
|
|
32
|
+
total_operations: 0,
|
|
33
|
+
completed_operations: 0,
|
|
34
|
+
failed_operations: 0,
|
|
35
|
+
current_queue_depth: 0,
|
|
36
|
+
max_queue_depth: 0,
|
|
37
|
+
total_wait_time_ms: 0,
|
|
38
|
+
total_processing_time_ms: 0
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
this.log = create_context_logger();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enqueues a write operation to be processed sequentially.
|
|
46
|
+
* @param {function} operation_fn - Async function that performs the write operation
|
|
47
|
+
* @param {Object} [context={}] - Additional context for logging and debugging
|
|
48
|
+
* @returns {Promise<*>} Promise that resolves with the operation result
|
|
49
|
+
* @throws {Error} When server is shutting down
|
|
50
|
+
*/
|
|
51
|
+
async enqueue_write_operation(operation_fn, context = {}) {
|
|
52
|
+
if (this.shutting_down) {
|
|
53
|
+
throw new Error('Server shutting down');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
if (this.shutting_down) {
|
|
58
|
+
reject(new Error('Server shutting down'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const queue_item = {
|
|
63
|
+
operation_fn,
|
|
64
|
+
context,
|
|
65
|
+
resolve,
|
|
66
|
+
reject,
|
|
67
|
+
enqueued_at: Date.now(),
|
|
68
|
+
id: this.generate_operation_id()
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
this.queue.push(queue_item);
|
|
72
|
+
this.stats.total_operations++;
|
|
73
|
+
this.stats.current_queue_depth = this.queue.length;
|
|
74
|
+
|
|
75
|
+
if (this.stats.current_queue_depth > this.stats.max_queue_depth) {
|
|
76
|
+
this.stats.max_queue_depth = this.stats.current_queue_depth;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.log.debug('Write operation enqueued', {
|
|
80
|
+
operation_id: queue_item.id,
|
|
81
|
+
queue_depth: this.stats.current_queue_depth,
|
|
82
|
+
context: context
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
this.process_queue();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Processes queued write operations sequentially.
|
|
91
|
+
* Handles timing, error tracking, and statistics updates.
|
|
92
|
+
* @returns {Promise<void>} Promise that resolves when processing is complete
|
|
93
|
+
*/
|
|
94
|
+
async process_queue() {
|
|
95
|
+
if (this.processing || this.queue.length === 0 || this.shutting_down) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.processing = true;
|
|
100
|
+
|
|
101
|
+
while (this.queue.length > 0 && !this.shutting_down) {
|
|
102
|
+
const queue_item = this.queue.shift();
|
|
103
|
+
this.stats.current_queue_depth = this.queue.length;
|
|
104
|
+
|
|
105
|
+
const wait_time_ms = Date.now() - queue_item.enqueued_at;
|
|
106
|
+
this.stats.total_wait_time_ms += wait_time_ms;
|
|
107
|
+
|
|
108
|
+
const processing_start = Date.now();
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
this.log.debug('Processing write operation', {
|
|
112
|
+
operation_id: queue_item.id,
|
|
113
|
+
wait_time_ms,
|
|
114
|
+
context: queue_item.context
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const result = await this.execute_with_retry(queue_item.operation_fn, queue_item.context);
|
|
118
|
+
|
|
119
|
+
const processing_time_ms = Date.now() - processing_start;
|
|
120
|
+
this.stats.total_processing_time_ms += processing_time_ms;
|
|
121
|
+
this.stats.completed_operations++;
|
|
122
|
+
|
|
123
|
+
this.log.debug('Write operation completed', {
|
|
124
|
+
operation_id: queue_item.id,
|
|
125
|
+
wait_time_ms,
|
|
126
|
+
processing_time_ms,
|
|
127
|
+
context: queue_item.context
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
queue_item.resolve(result);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const processing_time_ms = Date.now() - processing_start;
|
|
133
|
+
this.stats.total_processing_time_ms += processing_time_ms;
|
|
134
|
+
this.stats.failed_operations++;
|
|
135
|
+
|
|
136
|
+
this.log.error('Write operation failed', {
|
|
137
|
+
operation_id: queue_item.id,
|
|
138
|
+
wait_time_ms,
|
|
139
|
+
processing_time_ms,
|
|
140
|
+
error: error.message,
|
|
141
|
+
context: queue_item.context
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
queue_item.reject(error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
this.processing = false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Executes an operation with retry logic and exponential backoff.
|
|
153
|
+
* @param {function} operation_fn - Async function to execute
|
|
154
|
+
* @param {Object} context - Context for logging
|
|
155
|
+
* @param {number} [max_retries=3] - Maximum number of retry attempts
|
|
156
|
+
* @returns {Promise<*>} Promise that resolves with operation result
|
|
157
|
+
* @throws {Error} When all retry attempts are exhausted
|
|
158
|
+
*/
|
|
159
|
+
async execute_with_retry(operation_fn, context, max_retries = 3) {
|
|
160
|
+
let last_error = null;
|
|
161
|
+
|
|
162
|
+
for (let attempt = 1; attempt <= max_retries; attempt++) {
|
|
163
|
+
try {
|
|
164
|
+
return await operation_fn();
|
|
165
|
+
} catch (error) {
|
|
166
|
+
last_error = error;
|
|
167
|
+
|
|
168
|
+
if (this.is_retryable_error(error) && attempt < max_retries) {
|
|
169
|
+
const delay_ms = this.calculate_backoff_delay(attempt);
|
|
170
|
+
|
|
171
|
+
this.log.warn('Write operation failed, retrying', {
|
|
172
|
+
attempt,
|
|
173
|
+
max_retries,
|
|
174
|
+
delay_ms,
|
|
175
|
+
error: error.message,
|
|
176
|
+
context
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await this.sleep(delay_ms);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
throw last_error;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Determines if an error is retryable based on error patterns.
|
|
192
|
+
* @param {Error} error - Error to check
|
|
193
|
+
* @returns {boolean} True if error is retryable, false otherwise
|
|
194
|
+
*/
|
|
195
|
+
is_retryable_error(error) {
|
|
196
|
+
const retryable_patterns = [
|
|
197
|
+
'MDB_MAP_FULL',
|
|
198
|
+
'MDB_TXN_FULL',
|
|
199
|
+
'MDB_READERS_FULL',
|
|
200
|
+
'EAGAIN',
|
|
201
|
+
'EBUSY'
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
return retryable_patterns.some(pattern =>
|
|
205
|
+
error.message.includes(pattern) || error.code === pattern
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Calculates exponential backoff delay with jitter for retry attempts.
|
|
211
|
+
* @param {number} attempt - Current attempt number (1-based)
|
|
212
|
+
* @returns {number} Delay in milliseconds
|
|
213
|
+
*/
|
|
214
|
+
calculate_backoff_delay(attempt) {
|
|
215
|
+
const base_delay = 100;
|
|
216
|
+
const max_delay = 5000;
|
|
217
|
+
const exponential_delay = base_delay * Math.pow(2, attempt - 1);
|
|
218
|
+
const jitter = Math.random() * 0.1 * exponential_delay;
|
|
219
|
+
|
|
220
|
+
return Math.min(exponential_delay + jitter, max_delay);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Utility function to sleep for specified milliseconds.
|
|
225
|
+
* @param {number} ms - Milliseconds to sleep
|
|
226
|
+
* @returns {Promise<void>} Promise that resolves after delay
|
|
227
|
+
*/
|
|
228
|
+
sleep(ms) {
|
|
229
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Generates a unique operation ID for tracking.
|
|
234
|
+
* @returns {string} Unique operation identifier
|
|
235
|
+
*/
|
|
236
|
+
generate_operation_id() {
|
|
237
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Gets comprehensive queue statistics including calculated averages.
|
|
242
|
+
* @returns {Object} Statistics object with performance metrics
|
|
243
|
+
* @returns {number} returns.total_operations - Total operations enqueued
|
|
244
|
+
* @returns {number} returns.completed_operations - Successfully completed operations
|
|
245
|
+
* @returns {number} returns.failed_operations - Failed operations
|
|
246
|
+
* @returns {number} returns.current_queue_depth - Current number of queued operations
|
|
247
|
+
* @returns {number} returns.max_queue_depth - Maximum queue depth reached
|
|
248
|
+
* @returns {number} returns.avg_wait_time_ms - Average wait time in milliseconds
|
|
249
|
+
* @returns {number} returns.avg_processing_time_ms - Average processing time in milliseconds
|
|
250
|
+
* @returns {number} returns.success_rate - Success rate as percentage
|
|
251
|
+
*/
|
|
252
|
+
get_stats() {
|
|
253
|
+
const avg_wait_time = this.stats.completed_operations > 0
|
|
254
|
+
? Math.round(this.stats.total_wait_time_ms / this.stats.completed_operations)
|
|
255
|
+
: 0;
|
|
256
|
+
|
|
257
|
+
const avg_processing_time = this.stats.completed_operations > 0
|
|
258
|
+
? Math.round(this.stats.total_processing_time_ms / this.stats.completed_operations)
|
|
259
|
+
: 0;
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
...this.stats,
|
|
263
|
+
avg_wait_time_ms: avg_wait_time,
|
|
264
|
+
avg_processing_time_ms: avg_processing_time,
|
|
265
|
+
success_rate: this.stats.total_operations > 0
|
|
266
|
+
? Math.round((this.stats.completed_operations / this.stats.total_operations) * 100)
|
|
267
|
+
: 100
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Clears all statistics while preserving current queue depth.
|
|
273
|
+
*/
|
|
274
|
+
clear_stats() {
|
|
275
|
+
this.stats = {
|
|
276
|
+
total_operations: 0,
|
|
277
|
+
completed_operations: 0,
|
|
278
|
+
failed_operations: 0,
|
|
279
|
+
current_queue_depth: this.queue.length,
|
|
280
|
+
max_queue_depth: 0,
|
|
281
|
+
total_wait_time_ms: 0,
|
|
282
|
+
total_processing_time_ms: 0
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Gracefully shuts down the write queue.
|
|
288
|
+
* Waits for current operation to complete and rejects all pending operations.
|
|
289
|
+
* @returns {Promise<void>} Promise that resolves when shutdown is complete
|
|
290
|
+
*/
|
|
291
|
+
async shutdown() {
|
|
292
|
+
this.log.info('Shutting down write queue', {
|
|
293
|
+
pending_operations: this.queue.length,
|
|
294
|
+
currently_processing: this.processing
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
this.shutting_down = true;
|
|
298
|
+
|
|
299
|
+
while (this.processing) {
|
|
300
|
+
await this.sleep(50);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
this.queue.forEach(queue_item => {
|
|
304
|
+
queue_item.reject(new Error('Server shutting down'));
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
this.queue = [];
|
|
308
|
+
this.processing = false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** @type {WriteQueue|null} Singleton instance of the write queue */
|
|
313
|
+
let write_queue_instance = null;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Gets the singleton write queue instance, creating it if it doesn't exist.
|
|
317
|
+
* @returns {WriteQueue} The write queue instance
|
|
318
|
+
*/
|
|
319
|
+
export const get_write_queue = () => {
|
|
320
|
+
if (!write_queue_instance) {
|
|
321
|
+
write_queue_instance = new WriteQueue();
|
|
322
|
+
}
|
|
323
|
+
return write_queue_instance;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Shuts down the write queue and clears the singleton instance.
|
|
328
|
+
* @returns {Promise<void>} Promise that resolves when shutdown is complete
|
|
329
|
+
*/
|
|
330
|
+
export const shutdown_write_queue = async () => {
|
|
331
|
+
if (write_queue_instance) {
|
|
332
|
+
await write_queue_instance.shutdown();
|
|
333
|
+
write_queue_instance = null;
|
|
334
|
+
}
|
|
335
|
+
};
|
|
Binary file
|
|
Binary file
|