@futdevpro/nts-dynamo 1.15.55 → 1.15.57
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/.c8rc.json +26 -26
- package/.copilot/patterns.json +7 -7
- package/.cursor/rules/__assistant_guide.mdc +30 -30
- package/.cursor/rules/_ag_backend-structure.mdc +85 -85
- package/.cursor/rules/_ag_backend.mdc +16 -16
- package/.cursor/rules/_ag_frontend-structure.mdc +86 -86
- package/.cursor/rules/_ag_frontend.mdc +39 -39
- package/.cursor/rules/_ag_import-rules.mdc +44 -44
- package/.cursor/rules/_ag_naming.mdc +115 -115
- package/.cursor/rules/_ag_should-be.mdc +6 -6
- package/.cursor/rules/ai_development_guide.md +60 -60
- package/.cursor/rules/cursor-rules.md +160 -160
- package/.cursor/rules/default-command.mdc +464 -464
- package/.cursor/rules/error_code_pattern.md +39 -39
- package/.cursor/rules/saved rule mcp server use.md +15 -15
- package/.dynamo/logs/cicd-pipeline/output.log +4691 -0
- package/.dynamo/logs/cicd-pipeline/status.json +396 -0
- package/.github/workflows/main.yml +432 -432
- package/.vscode/settings.json +10 -10
- package/HOWTO.md +15 -15
- package/LICENSE +21 -21
- package/__documentations/2026-06-15-fr193-memory-guard.md +73 -0
- package/__documentations/nts-integration-tests-2026-03-17.md +26 -26
- package/_specifications/BACKLOG.md +92 -92
- package/_specifications/TODO.md +15 -15
- package/_specifications/agent.md +138 -138
- package/build/_collections/global-settings.const.d.ts.map +1 -1
- package/build/_collections/global-settings.const.js +11 -0
- package/build/_collections/global-settings.const.js.map +1 -1
- package/build/_models/interfaces/global-settings.interface.d.ts +21 -0
- package/build/_models/interfaces/global-settings.interface.d.ts.map +1 -1
- package/build/_services/core/memory-guard.service.d.ts +111 -0
- package/build/_services/core/memory-guard.service.d.ts.map +1 -0
- package/build/_services/core/memory-guard.service.js +198 -0
- package/build/_services/core/memory-guard.service.js.map +1 -0
- package/build/_services/server/app.server.d.ts.map +1 -1
- package/build/_services/server/app.server.js +13 -0
- package/build/_services/server/app.server.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/eslint.config.js +3 -3
- package/nodemon.json +24 -24
- package/package.json +361 -361
- package/pnpm-workspace.yaml +4 -4
- package/scripts/run-coverage-tests.js +28 -28
- package/spec/support/helpers/spec-reporter-loader.js +359 -359
- package/spec/support/helpers/ts-node-helper.js +93 -93
- package/spec/support/jasmine.coverage.json +24 -24
- package/spec/support/jasmine.json +24 -24
- package/src/_collections/archive.util.spec.ts +57 -57
- package/src/_collections/archive.util.ts +18 -18
- package/src/_collections/atlas-default-db-options.const.ts +9 -9
- package/src/_collections/default-fallback-cache-max-age.const.spec.ts +11 -11
- package/src/_collections/default-fallback-cache-max-age.const.ts +2 -2
- package/src/_collections/default-not-found-page.const.spec.ts +19 -19
- package/src/_collections/default-not-found-page.const.ts +22 -22
- package/src/_collections/default-socket-path.const.spec.ts +12 -12
- package/src/_collections/default-socket-path.const.ts +2 -2
- package/src/_collections/get-environment-settings.util.spec.ts +210 -210
- package/src/_collections/get-environment-settings.util.ts +48 -48
- package/src/_collections/global-settings.const.ts +82 -70
- package/src/_collections/sample.env +21 -21
- package/src/_collections/star.controller.spec.ts +224 -224
- package/src/_collections/star.controller.ts +129 -129
- package/src/_enums/data-model-type.enum.ts +14 -14
- package/src/_enums/data-service-function.enum.ts +24 -24
- package/src/_enums/predefined-data-types.enum.ts +16 -16
- package/src/_enums/route-security.enum.ts +12 -12
- package/src/_models/control-models/api-call-params.control-model.spec.ts +152 -152
- package/src/_models/control-models/api-call-params.control-model.ts +142 -142
- package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -52
- package/src/_models/control-models/app-ext-system-controls.control-model.ts +9 -9
- package/src/_models/control-models/app-params.control-model.spec.ts +225 -225
- package/src/_models/control-models/app-params.control-model.ts +136 -136
- package/src/_models/control-models/app-system-controls.control-model.spec.ts +31 -31
- package/src/_models/control-models/app-system-controls.control-model.ts +9 -9
- package/src/_models/control-models/endpoint-params.control-model.spec.ts +627 -627
- package/src/_models/control-models/endpoint-params.control-model.ts +627 -627
- package/src/_models/control-models/http-settings.control-model.spec.ts +77 -77
- package/src/_models/control-models/http-settings.control-model.ts +37 -37
- package/src/_models/control-models/system-control.control-model.spec.ts +27 -27
- package/src/_models/control-models/system-control.control-model.ts +12 -12
- package/src/_models/interfaces/certification-settings.interface.ts +7 -7
- package/src/_models/interfaces/environment-settings.interface.ts +59 -59
- package/src/_models/interfaces/global-log-settings.interface.ts +171 -171
- package/src/_models/interfaces/global-service-settings.interface.ts +47 -47
- package/src/_models/interfaces/global-settings.interface.ts +23 -1
- package/src/_models/interfaces/routing-module-settings.interface.ts +21 -21
- package/src/_models/interfaces/static-client-settings.interface.spec.ts +29 -29
- package/src/_models/interfaces/static-client-settings.interface.ts +28 -28
- package/src/_models/types/db-update.type.ts +100 -100
- package/src/_modules/ai/_models/ai-input-interfaces.ts +117 -117
- package/src/_modules/ai/_models/ai-test-generation-result.interface.ts +16 -16
- package/src/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.ts +138 -138
- package/src/_modules/ai/_modules/anthropic/index.ts +5 -5
- package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -242
- package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.ts +639 -639
- package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -209
- package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.ts +85 -85
- package/src/_modules/ai/_modules/document-ai/_enums/dai-compare-result-type.enum.ts +7 -7
- package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-doc-chunk.data-model.ts +146 -146
- package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-doc-page.data-model.ts +162 -162
- package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-document.data-model.ts +99 -99
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-doc-chunk-compare-result.interface.ts +18 -18
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-doc-page-compare-result.interface.ts +19 -19
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-document-compare-result.interface.ts +25 -25
- package/src/_modules/ai/_modules/document-ai/index.ts +28 -28
- package/src/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.ts +189 -189
- package/src/_modules/ai/_modules/fdp-ai/index.ts +5 -5
- package/src/_modules/ai/_modules/open-ai/_collections/oai-global-settings.const.ts +9 -9
- package/src/_modules/ai/_modules/open-ai/_collections/oai-llm-predefined-requests-hu.conts.ts +82 -82
- package/src/_modules/ai/_modules/open-ai/_collections/oai-llm-predefined-requests.conts.ts +75 -75
- package/src/_modules/ai/_modules/open-ai/_enums/oai-gpt-message-role.enum.ts +45 -45
- package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-global-settings.interface.ts +7 -7
- package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-gpt-message.interface.ts +7 -7
- package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-llm-predefined-requests.interface.ts +57 -57
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-doc-chunk-data.service.ts +292 -292
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -342
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -550
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.ts +630 -630
- package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +332 -332
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -462
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.ts +634 -634
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +489 -489
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.tools.spec.ts +173 -173
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.ts +1033 -1033
- package/src/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.ts +157 -157
- package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -98
- package/src/_modules/ai/_services/ai-embedding.service-base.ts +48 -48
- package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -229
- package/src/_modules/ai/_services/ai-llm-chat.service-base.ts +68 -68
- package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -250
- package/src/_modules/ai/_services/ai-llm.service-base.ts +519 -519
- package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +158 -158
- package/src/_modules/ai/_services/ai-user-key.service-base.ts +59 -59
- package/src/_modules/ai/index.ts +13 -13
- package/src/_modules/assistant/_collections/ass-global-settings.const.ts +13 -13
- package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -176
- package/src/_modules/assistant/_collections/ass.util.ts +50 -50
- package/src/_modules/assistant/_models/ass-global-settings.interface.ts +15 -15
- package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -140
- package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -192
- package/src/_modules/assistant/_services/ass-main.control-service.ts +107 -107
- package/src/_modules/bot/_collections/bot-default-commands.const.ts +12 -12
- package/src/_modules/bot/_collections/bot-global-settings.const.ts +39 -39
- package/src/_modules/bot/_models/bot-channel-wrapper.interface.ts +62 -62
- package/src/_modules/bot/_models/bot-command.interface.ts +8 -8
- package/src/_modules/bot/_models/bot-global-settings.interface.ts +96 -96
- package/src/_modules/bot/_models/bot-last-mention-date.interface.ts +6 -6
- package/src/_modules/bot/_models/bot-last-message-date.interface.ts +5 -5
- package/src/_modules/bot/_models/bot-user-wrapper.interface.ts +41 -41
- package/src/_modules/bot/_modules/discord-bot/_models/dib-platform.types.ts +9 -9
- package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -431
- package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -160
- package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.ts +55 -55
- package/src/_modules/bot/_modules/dynamo-bot/_models/dyb-platform.types.ts +15 -15
- package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -374
- package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.ts +447 -447
- package/src/_modules/bot/_modules/dynamo-bot/index.ts +15 -15
- package/src/_modules/bot/_modules/slack-bot/_models/slb-platform.types.ts +9 -9
- package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -344
- package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.ts +197 -197
- package/src/_modules/bot/_modules/teams-bot/_models/teb-platform.types.ts +9 -9
- package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -345
- package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.ts +197 -197
- package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -116
- package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -285
- package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -208
- package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -349
- package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -111
- package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -49
- package/src/_modules/custom-data/custom-data.controller.ts +67 -67
- package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -54
- package/src/_modules/custom-data/custom-data.data-service.ts +21 -21
- package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -28
- package/src/_modules/custom-data/get-custom-data-routing-module.util.ts +24 -24
- package/src/_modules/custom-data/index.ts +9 -9
- package/src/_modules/defaults/_collections/default-endpoints.util.ts +487 -487
- package/src/_modules/defaults/_models/default-user.data-model.ts +72 -72
- package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -269
- package/src/_modules/defaults/_services/default-auth.service.ts +177 -177
- package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -42
- package/src/_modules/defaults/_services/default-socket-events.service.ts +61 -61
- package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -187
- package/src/_modules/defaults/_services/default-user.data-service.ts +98 -98
- package/src/_modules/defaults/index.ts +17 -17
- package/src/_modules/discord-assistant/_collections/dias-global-settings.const.ts +19 -19
- package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -366
- package/src/_modules/discord-assistant/_collections/dias.util.ts +132 -132
- package/src/_modules/discord-assistant/_models/dias-global-settings.interface.ts +19 -19
- package/src/_modules/discord-assistant/_models/dias-knowledge.data-model.ts +52 -52
- package/src/_modules/discord-assistant/_services/dias-chunk.data-service.ts +177 -177
- package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -108
- package/src/_modules/discord-assistant/_services/dias-io.control-service.ts +69 -69
- package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -22
- package/src/_modules/discord-assistant/_services/dias-main.control-service.ts +27 -27
- package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -195
- package/src/_modules/discord-assistant/_services/dias.service-base.ts +76 -76
- package/src/_modules/discord-assistant/index.ts +38 -38
- package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -34
- package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.ts +11 -11
- package/src/_modules/discord-assistant-voiced/index.ts +36 -36
- package/src/_modules/discord-bot/_collections/dibo-default-commands.const.ts +16 -16
- package/src/_modules/discord-bot/_collections/dibo-global-settings.conts.ts +55 -55
- package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -214
- package/src/_modules/discord-bot/_collections/dibo-operations.util.ts +387 -387
- package/src/_modules/discord-bot/_models/dibo-command.interface.ts +12 -12
- package/src/_modules/discord-bot/_models/dibo-global-settings.interface.ts +98 -98
- package/src/_modules/discord-bot/_models/dibo-last-mention-date.inteface.ts +7 -7
- package/src/_modules/discord-bot/_models/dibo-last-message-date.interface.ts +6 -6
- package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -154
- package/src/_modules/discord-bot/_services/dibo-commands.control-service.ts +153 -153
- package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -264
- package/src/_modules/discord-bot/_services/dibo-io.control-service.ts +306 -306
- package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -408
- package/src/_modules/discord-bot/_services/dibo-main.control-service.ts +487 -487
- package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -105
- package/src/_modules/discord-bot/index.ts +36 -36
- package/src/_modules/local-vector-search/_enums/lvs-search-mode.enum.ts +35 -35
- package/src/_modules/local-vector-search/_models/lvs-search-result.interface.ts +17 -17
- package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -418
- package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.ts +276 -276
- package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +480 -480
- package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.ts +416 -416
- package/src/_modules/local-vector-search/_services/lvs-vector-pool.control-service.spec.ts +393 -393
- package/src/_modules/local-vector-search/_services/lvs-vector-pool.control-service.ts +220 -220
- package/src/_modules/local-vector-search/index.ts +11 -11
- package/src/_modules/logs/index.ts +11 -11
- package/src/_modules/messaging/README.md +354 -354
- package/src/_modules/messaging/_collections/get-messaging-routing-module.util.ts +26 -26
- package/src/_modules/messaging/_collections/msg-global-settings.const.ts +22 -22
- package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -226
- package/src/_modules/messaging/_models/msg-global-settings.interface.ts +37 -37
- package/src/_modules/messaging/_services/msg-conversation.data-service.ts +146 -146
- package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -219
- package/src/_modules/messaging/_services/msg-events.service.ts +267 -267
- package/src/_modules/messaging/_services/msg-integration.control-service.ts +179 -179
- package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -147
- package/src/_modules/messaging/_services/msg-main.control-service.ts +571 -571
- package/src/_modules/messaging/_services/msg-message.data-service.ts +129 -129
- package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -201
- package/src/_modules/messaging/index.ts +30 -30
- package/src/_modules/mock/app-extended-server.mock.ts +201 -201
- package/src/_modules/mock/app-integration-test.mock.ts +51 -51
- package/src/_modules/mock/app-params.mock.spec.ts +21 -21
- package/src/_modules/mock/app-params.mock.ts +9 -9
- package/src/_modules/mock/app-server.mock.ts +188 -188
- package/src/_modules/mock/auth-service.mock.spec.ts +47 -47
- package/src/_modules/mock/auth-service.mock.ts +28 -28
- package/src/_modules/mock/controller.mock.spec.ts +26 -26
- package/src/_modules/mock/controller.mock.ts +16 -16
- package/src/_modules/mock/data-model.mock.spec.ts +111 -111
- package/src/_modules/mock/data-model.mock.ts +82 -82
- package/src/_modules/mock/email-service-collection.mock.spec.ts +24 -24
- package/src/_modules/mock/email-service-collection.mock.ts +15 -15
- package/src/_modules/mock/email-service.mock.spec.ts +17 -17
- package/src/_modules/mock/email-service.mock.ts +20 -20
- package/src/_modules/mock/email-template.mock.html +14 -14
- package/src/_modules/mock/endpoint.mock.ts +91 -91
- package/src/_modules/mock/socket-client.mock.spec.ts +40 -40
- package/src/_modules/mock/socket-client.mock.ts +45 -45
- package/src/_modules/mock/socket-server.mock.spec.ts +44 -44
- package/src/_modules/mock/socket-server.mock.ts +46 -46
- package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -107
- package/src/_modules/oauth2/_routes/oauth2.controller.ts +98 -98
- package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -254
- package/src/_modules/oauth2/_services/oauth2.auth-service.ts +232 -232
- package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -585
- package/src/_modules/oauth2/_services/oauth2.control-service.ts +653 -653
- package/src/_modules/oauth2/index.ts +17 -17
- package/src/_modules/server/errors/errors.control-service.spec.ts +238 -238
- package/src/_modules/server/errors/errors.control-service.ts +85 -85
- package/src/_modules/server/errors/errors.controller.spec.ts +241 -241
- package/src/_modules/server/errors/errors.controller.ts +431 -431
- package/src/_modules/server/errors/errors.data-service.spec.ts +361 -361
- package/src/_modules/server/index.ts +30 -30
- package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -70
- package/src/_modules/server/server-status/server-status-snapshot.control-service.ts +17 -17
- package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -77
- package/src/_modules/server/server-status/server-status-snapshot.data-service.ts +37 -37
- package/src/_modules/server/server-status/server-status.control-service.spec.ts +576 -576
- package/src/_modules/server/server-status/server-status.control-service.ts +396 -396
- package/src/_modules/server/server-status/server-status.controller.spec.ts +240 -240
- package/src/_modules/server/server-status/server-status.controller.ts +253 -253
- package/src/_modules/socket/_enums/socket-security.enum.ts +11 -11
- package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +32 -32
- package/src/_modules/socket/_models/socket-client-service-params.control-model.ts +22 -22
- package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -164
- package/src/_modules/socket/_models/socket-presence.control-model.ts +210 -210
- package/src/_modules/socket/_models/socket-server-service-params.control-model.spec.ts +46 -46
- package/src/_modules/socket/_models/socket-server-service-params.control-model.ts +22 -22
- package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -15
- package/src/_modules/socket/_services/socket-client.service.ts +260 -260
- package/src/_modules/socket/_services/socket-server.service.spec.ts +11 -11
- package/src/_modules/socket/app-extended.integration.spec.ts +85 -85
- package/src/_modules/socket/app-extended.server.ts +630 -630
- package/src/_modules/socket/index.ts +42 -42
- package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -28
- package/src/_modules/test/get-test-routing-module.util.ts +23 -23
- package/src/_modules/test/index.ts +11 -11
- package/src/_modules/test/test.controller.spec.ts +72 -72
- package/src/_modules/test/test.controller.ts +115 -115
- package/src/_modules/usage/get-usage-routing-module.util.ts +22 -22
- package/src/_modules/usage/index.ts +15 -15
- package/src/_modules/usage/usage.controller.spec.ts +81 -81
- package/src/_modules/usage/usage.controller.ts +126 -126
- package/src/_modules/usage/usage.data-service.spec.ts +332 -332
- package/src/_modules/usage/usage.data-service.ts +185 -185
- package/src/_services/base/api.service-base.spec.ts +125 -125
- package/src/_services/base/api.service-base.ts +74 -74
- package/src/_services/base/archive-data.service.spec.ts +196 -196
- package/src/_services/base/archive-data.service.ts +216 -216
- package/src/_services/base/data.service.spec.ts +674 -674
- package/src/_services/base/data.service.ts +2719 -2719
- package/src/_services/base/db.service.spec.ts +73 -73
- package/src/_services/base/db.service.ts +1575 -1575
- package/src/_services/base/singleton.service-base.spec.ts +28 -28
- package/src/_services/base/singleton.service-base.ts +24 -24
- package/src/_services/base/singleton.service.spec.ts +114 -114
- package/src/_services/base/singleton.service.ts +38 -38
- package/src/_services/core/api.service.spec.ts +140 -140
- package/src/_services/core/auth.service.spec.ts +159 -159
- package/src/_services/core/auth.service.ts +174 -174
- package/src/_services/core/email.service.spec.ts +85 -85
- package/src/_services/core/email.service.ts +742 -742
- package/src/_services/core/global.service.spec.ts +275 -275
- package/src/_services/core/global.service.ts +461 -461
- package/src/_services/core/memory-guard.service.spec.ts +165 -0
- package/src/_services/core/memory-guard.service.ts +281 -0
- package/src/_services/core/service-collection.service.spec.ts +46 -46
- package/src/_services/core/service-collection.service.ts +6 -6
- package/src/_services/route/controller.service.spec.ts +53 -53
- package/src/_services/route/controller.service.ts +148 -148
- package/src/_services/route/routing-module.service.spec.ts +98 -98
- package/src/_services/route/routing-module.service.ts +330 -330
- package/src/_services/server/app.server.ts +1726 -1713
- package/src/_services/shared.static-service.spec.ts +99 -99
- package/src/_services/shared.static-service.ts +78 -78
- package/src/index.ts +96 -95
- package/tsconfig.app.json +12 -12
- package/tsconfig.json +42 -42
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { DyNTS_global_settings } from '../../_collections/global-settings.const';
|
|
2
|
+
import { DyNTS_GlobalService } from './global.service';
|
|
3
|
+
import { DyNTS_MemoryGuard } from './memory-guard.service';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* FR-193 — a bedrock heap-watchdog spec-je. A `poll()`-t KÖZVETLENÜL hívjuk (nem
|
|
7
|
+
* az intervallumra várunk), mockolt heap-plafonnal + `process.memoryUsage`-dzsel,
|
|
8
|
+
* így determinisztikusan teszteljük a hiszterézis-állapotgépet + a tartós rögzítést.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const MB: number = 1024 * 1024;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A privát `getHeapLimitBytes` + `process.memoryUsage` mockolása adott heap-%-hoz.
|
|
15
|
+
* Visszaadja a memoryUsage-spy-t, hogy a hívó később átállíthassa (recovery-teszt).
|
|
16
|
+
* `process as any`: a `MemoryUsageFn` típus egy `.rss()` submetódust is hordoz, amit
|
|
17
|
+
* egy egyszerű return-value mock nem elégít ki — a cast kikerüli ezt a teszt-zajt.
|
|
18
|
+
*/
|
|
19
|
+
const mockHeap = (guard: DyNTS_MemoryGuard, limitMb: number, usedMb: number): jasmine.Spy => {
|
|
20
|
+
spyOn(guard as any, 'getHeapLimitBytes').and.returnValue(limitMb * MB);
|
|
21
|
+
return spyOn(process as any, 'memoryUsage').and.returnValue({
|
|
22
|
+
heapUsed: usedMb * MB,
|
|
23
|
+
heapTotal: usedMb * MB,
|
|
24
|
+
rss: (usedMb + 100) * MB,
|
|
25
|
+
external: 10 * MB,
|
|
26
|
+
arrayBuffers: 0,
|
|
27
|
+
} as NodeJS.MemoryUsage);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Egy poll-ciklus kézi kiváltása. */
|
|
31
|
+
const poll = (guard: DyNTS_MemoryGuard): void => { (guard as any).poll(); };
|
|
32
|
+
|
|
33
|
+
describe('| DyNTS_MemoryGuard (FR-193)', (): void => {
|
|
34
|
+
|
|
35
|
+
let guard: DyNTS_MemoryGuard;
|
|
36
|
+
let sinkSpy: jasmine.Spy;
|
|
37
|
+
let originalSink: typeof DyNTS_GlobalService.globalErrorHandler;
|
|
38
|
+
let originalSettings: typeof DyNTS_global_settings.memoryGuard;
|
|
39
|
+
|
|
40
|
+
beforeEach((): void => {
|
|
41
|
+
guard = DyNTS_MemoryGuard.getInstance();
|
|
42
|
+
guard._teardownForTesting();
|
|
43
|
+
|
|
44
|
+
originalSettings = DyNTS_global_settings.memoryGuard;
|
|
45
|
+
DyNTS_global_settings.memoryGuard = {
|
|
46
|
+
enabled: true,
|
|
47
|
+
pollIntervalMs: 999999, // ne tüzeljen az intervallum a teszt alatt
|
|
48
|
+
heapWarningThreshold: 85,
|
|
49
|
+
heapCriticalThreshold: 95,
|
|
50
|
+
recoveryMargin: 10,
|
|
51
|
+
maxHistoryCount: 100,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
originalSink = DyNTS_GlobalService.globalErrorHandler;
|
|
55
|
+
sinkSpy = jasmine.createSpy('globalErrorHandler');
|
|
56
|
+
(DyNTS_GlobalService as any).globalErrorHandler = sinkSpy;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach((): void => {
|
|
60
|
+
guard._teardownForTesting();
|
|
61
|
+
(DyNTS_GlobalService as any).globalErrorHandler = originalSink;
|
|
62
|
+
DyNTS_global_settings.memoryGuard = originalSettings;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('| install() idempotens — második hívás no-op', (): void => {
|
|
66
|
+
guard.install();
|
|
67
|
+
expect(guard.isInstalled()).toBe(true);
|
|
68
|
+
guard.install(); // nem dob, nem indít új timert
|
|
69
|
+
expect(guard.isInstalled()).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('| install() SOHA nem dob, akkor sem ha a settings hiányos', (): void => {
|
|
73
|
+
DyNTS_global_settings.memoryGuard = undefined as any;
|
|
74
|
+
expect((): void => guard.install()).not.toThrow();
|
|
75
|
+
expect(guard.isInstalled()).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('| warning küszöb alatt NINCS esemény', (): void => {
|
|
79
|
+
guard.install();
|
|
80
|
+
mockHeap(guard, 1000, 800); // 80% < 85
|
|
81
|
+
poll(guard);
|
|
82
|
+
expect(guard.getHistory().length).toBe(0);
|
|
83
|
+
expect(sinkSpy).not.toHaveBeenCalled();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('| warning küszöb átlépése → 1 warning esemény + tartós error-sink (level warning)', (): void => {
|
|
87
|
+
guard.install();
|
|
88
|
+
mockHeap(guard, 1000, 880); // 88% ∈ [85, 95)
|
|
89
|
+
poll(guard);
|
|
90
|
+
|
|
91
|
+
const hist: ReturnType<typeof guard.getHistory> = guard.getHistory();
|
|
92
|
+
expect(hist.length).toBe(1);
|
|
93
|
+
expect(hist[0].level).toBe('warning');
|
|
94
|
+
expect(hist[0].heapPct).toBe(88);
|
|
95
|
+
expect(sinkSpy).toHaveBeenCalledTimes(1);
|
|
96
|
+
expect(guard.getStatus().state).toBe('warning');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('| warning-sávban maradva NINCS re-emit (hiszterézis)', (): void => {
|
|
100
|
+
guard.install();
|
|
101
|
+
mockHeap(guard, 1000, 880); // 88% → warning
|
|
102
|
+
poll(guard);
|
|
103
|
+
poll(guard); // még mindig 88% (ugyanaz a mock) → nincs új esemény
|
|
104
|
+
expect(guard.getHistory().length).toBe(1);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('| critical küszöb átlépése → critical esemény + onCritical hook', (): void => {
|
|
108
|
+
const onCritical: jasmine.Spy = jasmine.createSpy('onCritical');
|
|
109
|
+
guard.install({ onCritical: onCritical });
|
|
110
|
+
mockHeap(guard, 1000, 970); // 97% ≥ 95
|
|
111
|
+
poll(guard);
|
|
112
|
+
|
|
113
|
+
const hist: ReturnType<typeof guard.getHistory> = guard.getHistory();
|
|
114
|
+
expect(hist[hist.length - 1].level).toBe('critical');
|
|
115
|
+
expect(onCritical).toHaveBeenCalledTimes(1);
|
|
116
|
+
expect(guard.getStatus().state).toBe('critical');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('| helyreállás: a warning-margó alá esve → recovered esemény (sink NÉLKÜL)', (): void => {
|
|
120
|
+
guard.install();
|
|
121
|
+
|
|
122
|
+
const muSpy: jasmine.Spy = mockHeap(guard, 1000, 880); // 88% → warning
|
|
123
|
+
poll(guard);
|
|
124
|
+
sinkSpy.calls.reset();
|
|
125
|
+
muSpy.and.returnValue({
|
|
126
|
+
heapUsed: 700 * MB, heapTotal: 700 * MB, rss: 800 * MB, external: 10 * MB, arrayBuffers: 0,
|
|
127
|
+
} as NodeJS.MemoryUsage); // 70% ≤ 85 - 10
|
|
128
|
+
poll(guard);
|
|
129
|
+
|
|
130
|
+
const hist: ReturnType<typeof guard.getHistory> = guard.getHistory();
|
|
131
|
+
expect(hist[hist.length - 1].level).toBe('recovered');
|
|
132
|
+
expect(guard.getStatus().state).toBe('normal');
|
|
133
|
+
expect(sinkSpy).not.toHaveBeenCalled(); // recovered NEM ír az error-sinkbe
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('| history ring-buffer a maxHistoryCount-ra van kapva', (): void => {
|
|
137
|
+
DyNTS_global_settings.memoryGuard!.maxHistoryCount = 3;
|
|
138
|
+
guard.install();
|
|
139
|
+
spyOn(guard as any, 'getHeapLimitBytes').and.returnValue(1000 * MB);
|
|
140
|
+
const high: NodeJS.MemoryUsage =
|
|
141
|
+
{ heapUsed: 880 * MB, heapTotal: 880 * MB, rss: 980 * MB, external: 0, arrayBuffers: 0 } as NodeJS.MemoryUsage;
|
|
142
|
+
const low: NodeJS.MemoryUsage =
|
|
143
|
+
{ heapUsed: 700 * MB, heapTotal: 700 * MB, rss: 800 * MB, external: 0, arrayBuffers: 0 } as NodeJS.MemoryUsage;
|
|
144
|
+
let tick: number = 0;
|
|
145
|
+
// warning ↔ recovered oszcilláció: páros tick=high (warning), páratlan=low (recovered)
|
|
146
|
+
spyOn(process as any, 'memoryUsage').and.callFake((): NodeJS.MemoryUsage => (tick++ % 2 === 0 ? high : low));
|
|
147
|
+
for (let k: number = 0; k < 8; k++) { poll(guard); } // 8 állapot-váltás, csak 3 marad
|
|
148
|
+
expect(guard.getHistory().length).toBe(3);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('| poll() SOHA nem dob (heap limit 0 → no-op)', (): void => {
|
|
152
|
+
guard.install();
|
|
153
|
+
spyOn(guard as any, 'getHeapLimitBytes').and.returnValue(0);
|
|
154
|
+
expect((): void => poll(guard)).not.toThrow();
|
|
155
|
+
expect(guard.getHistory().length).toBe(0);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('| getStatus a csúcsokat is követi', (): void => {
|
|
159
|
+
guard.install();
|
|
160
|
+
mockHeap(guard, 1000, 920); // 92%
|
|
161
|
+
poll(guard);
|
|
162
|
+
expect(guard.getStatus().peakHeapPct).toBe(92);
|
|
163
|
+
expect(guard.getStatus().peakRssMb).toBeGreaterThan(0);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import * as v8 from 'v8';
|
|
2
|
+
|
|
3
|
+
import { DyFM_Error, DyFM_ErrorLevel, DyFM_Log } from '@futdevpro/fsm-dynamo';
|
|
4
|
+
|
|
5
|
+
import { DyNTS_global_settings } from '../../_collections/global-settings.const';
|
|
6
|
+
import { DyNTS_SingletonServiceBase } from '../base/singleton.service-base';
|
|
7
|
+
import { DyNTS_GlobalService } from './global.service';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* FR-193 (2026-06-15) — bedrock OOM korai-figyelmeztető heap-watchdog.
|
|
11
|
+
*
|
|
12
|
+
* MIÉRT: a Node heap-OOM (`--max-old-space-size` túllépés, pl. egy óriási JSON.parse)
|
|
13
|
+
* a process-t AZONNAL megöli — `process.on('uncaughtException')` NEM kapja el, így a
|
|
14
|
+
* crash pillanatában már nincs mód a hibát rögzíteni. Az EGYETLEN megbízható idő a
|
|
15
|
+
* rögzítésre a crash ELŐTT van. E watchdog periodikusan figyeli a heap-kihasználtságot,
|
|
16
|
+
* és amikor egy konfigurálható küszöböt átlép, TARTÓS rekordot hagy (DyFM_Log +
|
|
17
|
+
* `DyNTS_GlobalService.globalErrorHandler` → az Errors-sink, amit minden szerver megkap)
|
|
18
|
+
* — így egy OOM-hajlamos szerver NYOMOT hagy mielőtt elszáll, és a kuszob-atlepés
|
|
19
|
+
* lathato a dashboard-on / Discord-on.
|
|
20
|
+
*
|
|
21
|
+
* MIT NEM csinál: NEM állítja le/újraindítja a process-t (az a konténer-szintű
|
|
22
|
+
* `restart:` policy dolga), és NEM próbálja elkapni a fatal OOM-ot (nem lehet). Tisztán
|
|
23
|
+
* MEGFIGYELÉS + RÖGZÍTÉS + opcionális `onCritical` hook (amivel a fogyasztó terhet dobhat).
|
|
24
|
+
*
|
|
25
|
+
* Hiszterézis: a küszöböket CSAK állapot-VÁLTÁSkor jelzi (normal→warning→critical), és
|
|
26
|
+
* a `recoveryMargin`-nyit a warning ALÁ esve jelez 'recovered'-et — így nem spamel a
|
|
27
|
+
* küszöb körül oszcilláló heap.
|
|
28
|
+
*
|
|
29
|
+
* Használat (opt-in, mint a `DyNTS_Logs_Service`):
|
|
30
|
+
* DyNTS_MemoryGuard.getInstance().install(); // default settings
|
|
31
|
+
* DyNTS_MemoryGuard.getInstance().install({ onCritical }); // custom hook
|
|
32
|
+
* VAGY automatikusan: a base `App` startup feltelepíti, ha
|
|
33
|
+
* `DyNTS_global_settings.memoryGuard.enabled === true` (alapértelmezés szerint igen).
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** Egy MemoryGuard esemény — küszöb-átlépés vagy helyreállás. */
|
|
37
|
+
export interface DyNTS_MemoryGuard_Event {
|
|
38
|
+
/** `warning` / `critical` küszöb-átlépés, vagy `recovered` (vissza normal-ba). */
|
|
39
|
+
level: 'warning' | 'critical' | 'recovered';
|
|
40
|
+
/** Heap használat MB-ban (`process.memoryUsage().heapUsed`). */
|
|
41
|
+
heapUsedMb: number;
|
|
42
|
+
/** Heap plafon MB-ban (`v8.getHeapStatistics().heap_size_limit` — a `--max-old-space-size`). */
|
|
43
|
+
heapLimitMb: number;
|
|
44
|
+
/** heapUsed / heapLimit * 100 (egész %-ra kerekítve). */
|
|
45
|
+
heapPct: number;
|
|
46
|
+
/** Resident Set Size MB-ban (teljes process-memória, heap + non-heap). */
|
|
47
|
+
rssMb: number;
|
|
48
|
+
/** External (C++ / Buffer) memória MB-ban. */
|
|
49
|
+
externalMb: number;
|
|
50
|
+
/** Esemény időbélyege (ISO). */
|
|
51
|
+
at: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** `install()` opcionális override-jai (a `DyNTS_global_settings.memoryGuard` FÖLÉ). */
|
|
55
|
+
export interface DyNTS_MemoryGuard_Config {
|
|
56
|
+
/** Poll-intervallum ms-ben. Default: 10000. */
|
|
57
|
+
pollIntervalMs?: number;
|
|
58
|
+
/** Warning küszöb a heap-plafon %-ában. Default: 85. */
|
|
59
|
+
heapWarningThreshold?: number;
|
|
60
|
+
/** Critical küszöb a heap-plafon %-ában. Default: 95. */
|
|
61
|
+
heapCriticalThreshold?: number;
|
|
62
|
+
/** A warning küszöb ALATTI margó %-ban a 'recovered'-hez (hiszterézis). Default: 10. */
|
|
63
|
+
recoveryMargin?: number;
|
|
64
|
+
/** Megőrzött események max száma (ring-buffer). Default: 100. */
|
|
65
|
+
maxHistoryCount?: number;
|
|
66
|
+
/** Hook, amit a `critical` küszöb átlépésekor hívunk (pl. terhelés-dobás). */
|
|
67
|
+
onCritical?: (event: DyNTS_MemoryGuard_Event) => void;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type DyNTS_MemoryGuard_State = 'normal' | 'warning' | 'critical';
|
|
71
|
+
|
|
72
|
+
const BYTES_PER_MB: number = 1024 * 1024;
|
|
73
|
+
|
|
74
|
+
export class DyNTS_MemoryGuard extends DyNTS_SingletonServiceBase {
|
|
75
|
+
|
|
76
|
+
static getInstance(): DyNTS_MemoryGuard {
|
|
77
|
+
return DyNTS_MemoryGuard.getSingletonInstance() as DyNTS_MemoryGuard;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private timer: ReturnType<typeof setInterval> | null = null;
|
|
81
|
+
private installed: boolean = false;
|
|
82
|
+
private state: DyNTS_MemoryGuard_State = 'normal';
|
|
83
|
+
|
|
84
|
+
// Feloldott (effektív) konfiguráció — install()-kor töltjük.
|
|
85
|
+
private pollIntervalMs: number = 10000;
|
|
86
|
+
private warnPct: number = 85;
|
|
87
|
+
private critPct: number = 95;
|
|
88
|
+
private recoveryMargin: number = 10;
|
|
89
|
+
private maxHistoryCount: number = 100;
|
|
90
|
+
private onCritical?: (event: DyNTS_MemoryGuard_Event) => void;
|
|
91
|
+
|
|
92
|
+
private readonly history: DyNTS_MemoryGuard_Event[] = [];
|
|
93
|
+
private peakHeapPct: number = 0;
|
|
94
|
+
private peakRssMb: number = 0;
|
|
95
|
+
|
|
96
|
+
protected constructor() {
|
|
97
|
+
super();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Elindítja a heap-watchdogot. Idempotens (többszöri hívás no-op). A `config`
|
|
102
|
+
* felülírja a `DyNTS_global_settings.memoryGuard` értékeit, ami a beépített
|
|
103
|
+
* defaultokat írja felül. SOHA nem dob — egy figyelő-réteg nem dönthet be egy
|
|
104
|
+
* szervert (minden hiba try/catch-elt + descriptive-en logolt).
|
|
105
|
+
*/
|
|
106
|
+
install(config?: DyNTS_MemoryGuard_Config): void {
|
|
107
|
+
if (this.installed) { return; }
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const g: NonNullable<typeof DyNTS_global_settings.memoryGuard> =
|
|
111
|
+
DyNTS_global_settings.memoryGuard ?? { enabled: true };
|
|
112
|
+
|
|
113
|
+
this.pollIntervalMs = config?.pollIntervalMs ?? g.pollIntervalMs ?? 10000;
|
|
114
|
+
this.warnPct = config?.heapWarningThreshold ?? g.heapWarningThreshold ?? 85;
|
|
115
|
+
this.critPct = config?.heapCriticalThreshold ?? g.heapCriticalThreshold ?? 95;
|
|
116
|
+
this.recoveryMargin = config?.recoveryMargin ?? g.recoveryMargin ?? 10;
|
|
117
|
+
this.maxHistoryCount = config?.maxHistoryCount ?? g.maxHistoryCount ?? 100;
|
|
118
|
+
this.onCritical = config?.onCritical;
|
|
119
|
+
|
|
120
|
+
this.installed = true;
|
|
121
|
+
this.timer = setInterval((): void => { this.poll(); }, this.pollIntervalMs);
|
|
122
|
+
// unref(): a watchdog-timer NE tartsa életben a process-t önmagában (graceful
|
|
123
|
+
// exit-kor a Node ki tud lépni a függő interval ellenére is).
|
|
124
|
+
if (typeof this.timer.unref === 'function') { this.timer.unref(); }
|
|
125
|
+
|
|
126
|
+
DyFM_Log.info(
|
|
127
|
+
`[DyNTS_MemoryGuard] installed — poll ${this.pollIntervalMs}ms, ` +
|
|
128
|
+
`warn ${this.warnPct}%, crit ${this.critPct}% (heap limit ` +
|
|
129
|
+
`${Math.round(this.getHeapLimitBytes() / BYTES_PER_MB)}MB)`,
|
|
130
|
+
);
|
|
131
|
+
} catch (err: unknown) {
|
|
132
|
+
// Telepítési hiba SEM lehet fatal — a guard hiánya nem ér annyit, hogy a
|
|
133
|
+
// szerver-indulást megakassza.
|
|
134
|
+
DyFM_Log.warn('[DyNTS_MemoryGuard] install failed (non-fatal):', err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** A heap-plafon byte-ban (`--max-old-space-size`). Külön metódus a spec-mockoláshoz. */
|
|
139
|
+
private getHeapLimitBytes(): number {
|
|
140
|
+
return v8.getHeapStatistics().heap_size_limit;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Egy poll-ciklus: kiolvassa a heap-kihasználtságot, frissíti a csúcsokat, és a
|
|
145
|
+
* hiszterézis-állapotgép szerint esemény-átlépéskor rögzít + logol. SOHA nem dob.
|
|
146
|
+
*/
|
|
147
|
+
private poll(): void {
|
|
148
|
+
try {
|
|
149
|
+
const limitBytes: number = this.getHeapLimitBytes();
|
|
150
|
+
if (!limitBytes || limitBytes <= 0) { return; }
|
|
151
|
+
|
|
152
|
+
const mu: NodeJS.MemoryUsage = process.memoryUsage();
|
|
153
|
+
const pct: number = (mu.heapUsed / limitBytes) * 100;
|
|
154
|
+
|
|
155
|
+
const rssMb: number = mu.rss / BYTES_PER_MB;
|
|
156
|
+
if (pct > this.peakHeapPct) { this.peakHeapPct = pct; }
|
|
157
|
+
if (rssMb > this.peakRssMb) { this.peakRssMb = rssMb; }
|
|
158
|
+
|
|
159
|
+
// Hiszterézis-állapotgép — esemény CSAK állapot-váltáskor.
|
|
160
|
+
const prev: DyNTS_MemoryGuard_State = this.state;
|
|
161
|
+
let next: DyNTS_MemoryGuard_State = prev;
|
|
162
|
+
|
|
163
|
+
if (pct >= this.critPct) {
|
|
164
|
+
next = 'critical';
|
|
165
|
+
} else if (pct >= this.warnPct && prev === 'normal') {
|
|
166
|
+
next = 'warning';
|
|
167
|
+
} else if (pct <= this.warnPct - this.recoveryMargin) {
|
|
168
|
+
next = 'normal';
|
|
169
|
+
}
|
|
170
|
+
// Egyébként marad a jelenlegi állapot (hiszterézis-sáv) — nincs re-emit.
|
|
171
|
+
|
|
172
|
+
if (next === prev) { return; }
|
|
173
|
+
this.state = next;
|
|
174
|
+
|
|
175
|
+
const event: DyNTS_MemoryGuard_Event = {
|
|
176
|
+
level: next === 'normal' ? 'recovered' : next,
|
|
177
|
+
heapUsedMb: Math.round(mu.heapUsed / BYTES_PER_MB),
|
|
178
|
+
heapLimitMb: Math.round(limitBytes / BYTES_PER_MB),
|
|
179
|
+
heapPct: Math.round(pct),
|
|
180
|
+
rssMb: Math.round(rssMb),
|
|
181
|
+
externalMb: Math.round((mu.external ?? 0) / BYTES_PER_MB),
|
|
182
|
+
at: new Date().toISOString(),
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
this.recordEvent(event);
|
|
186
|
+
} catch (err: unknown) {
|
|
187
|
+
// Poll-hiba sosem fatal — a következő tick újrapróbálja.
|
|
188
|
+
DyFM_Log.warn('[DyNTS_MemoryGuard] poll error (non-fatal):', err);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Esemény ring-bufferbe + log + (warning/critical esetén) tartós error-sink. */
|
|
193
|
+
private recordEvent(event: DyNTS_MemoryGuard_Event): void {
|
|
194
|
+
this.history.push(event);
|
|
195
|
+
while (this.history.length > this.maxHistoryCount) { this.history.shift(); }
|
|
196
|
+
|
|
197
|
+
const summary: string =
|
|
198
|
+
`heap ${event.heapPct}% (${event.heapUsedMb}/${event.heapLimitMb}MB), rss ${event.rssMb}MB`;
|
|
199
|
+
|
|
200
|
+
if (event.level === 'recovered') {
|
|
201
|
+
DyFM_Log.success(`[DyNTS_MemoryGuard] RECOVERED — ${summary}`);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (event.level === 'critical') {
|
|
206
|
+
DyFM_Log.H_error(`[DyNTS_MemoryGuard] CRITICAL heap pressure — ${summary} — OOM imminent`);
|
|
207
|
+
} else {
|
|
208
|
+
DyFM_Log.warn(`[DyNTS_MemoryGuard] WARNING heap pressure — ${summary}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Tartós rögzítés a központi error-sinkbe (Errors-rendszer + Discord, ha bekötve).
|
|
212
|
+
try {
|
|
213
|
+
DyNTS_GlobalService.globalErrorHandler?.(
|
|
214
|
+
new DyFM_Error({
|
|
215
|
+
errorCode:
|
|
216
|
+
`${DyNTS_global_settings.systemShortCodeName ?? 'DyNTS'}|DyNTS-MG0-HEAP-${event.level.toUpperCase()}`,
|
|
217
|
+
message:
|
|
218
|
+
`Heap pressure ${event.level.toUpperCase()}: ${summary}. ` +
|
|
219
|
+
`Process approaching the --max-old-space-size ceiling — OOM crash risk.`,
|
|
220
|
+
additionalContent: { memoryGuardEvent: event, peakHeapPct: Math.round(this.peakHeapPct) },
|
|
221
|
+
systemVersion: DyNTS_global_settings.systemVersion,
|
|
222
|
+
level: event.level === 'critical' ? DyFM_ErrorLevel.critical : DyFM_ErrorLevel.warning,
|
|
223
|
+
}),
|
|
224
|
+
);
|
|
225
|
+
} catch (sinkErr: unknown) {
|
|
226
|
+
DyFM_Log.warn('[DyNTS_MemoryGuard] error-sink record failed (non-fatal):', sinkErr);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (event.level === 'critical' && this.onCritical) {
|
|
230
|
+
try {
|
|
231
|
+
this.onCritical(event);
|
|
232
|
+
} catch (hookErr: unknown) {
|
|
233
|
+
DyFM_Log.warn('[DyNTS_MemoryGuard] onCritical hook threw (non-fatal):', hookErr);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** A megőrzött események (legrégebbi → legújabb). Csak olvasásra. */
|
|
239
|
+
getHistory(): DyNTS_MemoryGuard_Event[] {
|
|
240
|
+
return this.history.slice();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Pillanatnyi állapot + csúcsok diagnosztikához (pl. egy status-endpoint). */
|
|
244
|
+
getStatus(): {
|
|
245
|
+
installed: boolean;
|
|
246
|
+
state: DyNTS_MemoryGuard_State;
|
|
247
|
+
peakHeapPct: number;
|
|
248
|
+
peakRssMb: number;
|
|
249
|
+
eventCount: number;
|
|
250
|
+
} {
|
|
251
|
+
return {
|
|
252
|
+
installed: this.installed,
|
|
253
|
+
state: this.state,
|
|
254
|
+
peakHeapPct: Math.round(this.peakHeapPct),
|
|
255
|
+
peakRssMb: Math.round(this.peakRssMb),
|
|
256
|
+
eventCount: this.history.length,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Telepítve van-e a watchdog. */
|
|
261
|
+
isInstalled(): boolean {
|
|
262
|
+
return this.installed;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Leállítja a watchdogot + visszaállítja az állapotot. Graceful shutdown-hoz ÉS a
|
|
267
|
+
* spec-ek `afterEach`-éhez (a singleton-state ne szivárogjon a tesztek közt).
|
|
268
|
+
*/
|
|
269
|
+
_teardownForTesting(): void {
|
|
270
|
+
if (this.timer) {
|
|
271
|
+
clearInterval(this.timer);
|
|
272
|
+
this.timer = null;
|
|
273
|
+
}
|
|
274
|
+
this.installed = false;
|
|
275
|
+
this.state = 'normal';
|
|
276
|
+
this.history.length = 0;
|
|
277
|
+
this.peakHeapPct = 0;
|
|
278
|
+
this.peakRssMb = 0;
|
|
279
|
+
this.onCritical = undefined;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
import { DyNTS_Service_Collection } from './service-collection.service';
|
|
3
|
-
|
|
4
|
-
class TestService {
|
|
5
|
-
name: string;
|
|
6
|
-
constructor(name: string) {
|
|
7
|
-
this.name = name;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
describe('| DyNTS_Service_Collection', () => {
|
|
12
|
-
it('| should be a singleton instance', () => {
|
|
13
|
-
class TestCollection extends DyNTS_Service_Collection<TestService> {
|
|
14
|
-
static getInstance(): TestCollection {
|
|
15
|
-
return TestCollection.getSingletonInstance();
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const instance1 = TestCollection.getInstance();
|
|
20
|
-
const instance2 = TestCollection.getInstance();
|
|
21
|
-
|
|
22
|
-
expect(instance1).toBe(instance2);
|
|
23
|
-
expect(instance1).toBeInstanceOf(TestCollection);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('| should allow dynamic property assignment', () => {
|
|
27
|
-
class TestCollection extends DyNTS_Service_Collection<TestService> {
|
|
28
|
-
static getInstance(): TestCollection {
|
|
29
|
-
return TestCollection.getSingletonInstance();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const collection = TestCollection.getInstance();
|
|
34
|
-
const service1 = new TestService('service1');
|
|
35
|
-
const service2 = new TestService('service2');
|
|
36
|
-
|
|
37
|
-
collection['service1'] = service1;
|
|
38
|
-
collection['service2'] = service2;
|
|
39
|
-
|
|
40
|
-
expect(collection['service1']).toBe(service1);
|
|
41
|
-
expect(collection['service2']).toBe(service2);
|
|
42
|
-
expect(collection['service1'].name).toBe('service1');
|
|
43
|
-
expect(collection['service2'].name).toBe('service2');
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
1
|
+
|
|
2
|
+
import { DyNTS_Service_Collection } from './service-collection.service';
|
|
3
|
+
|
|
4
|
+
class TestService {
|
|
5
|
+
name: string;
|
|
6
|
+
constructor(name: string) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe('| DyNTS_Service_Collection', () => {
|
|
12
|
+
it('| should be a singleton instance', () => {
|
|
13
|
+
class TestCollection extends DyNTS_Service_Collection<TestService> {
|
|
14
|
+
static getInstance(): TestCollection {
|
|
15
|
+
return TestCollection.getSingletonInstance();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const instance1 = TestCollection.getInstance();
|
|
20
|
+
const instance2 = TestCollection.getInstance();
|
|
21
|
+
|
|
22
|
+
expect(instance1).toBe(instance2);
|
|
23
|
+
expect(instance1).toBeInstanceOf(TestCollection);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('| should allow dynamic property assignment', () => {
|
|
27
|
+
class TestCollection extends DyNTS_Service_Collection<TestService> {
|
|
28
|
+
static getInstance(): TestCollection {
|
|
29
|
+
return TestCollection.getSingletonInstance();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const collection = TestCollection.getInstance();
|
|
34
|
+
const service1 = new TestService('service1');
|
|
35
|
+
const service2 = new TestService('service2');
|
|
36
|
+
|
|
37
|
+
collection['service1'] = service1;
|
|
38
|
+
collection['service2'] = service2;
|
|
39
|
+
|
|
40
|
+
expect(collection['service1']).toBe(service1);
|
|
41
|
+
expect(collection['service2']).toBe(service2);
|
|
42
|
+
expect(collection['service1'].name).toBe('service1');
|
|
43
|
+
expect(collection['service2'].name).toBe('service2');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { DyNTS_SingletonServiceBase } from '../base/singleton.service-base';
|
|
3
|
-
|
|
4
|
-
export class DyNTS_Service_Collection<T> extends DyNTS_SingletonServiceBase {
|
|
5
|
-
[service: string]: T;
|
|
6
|
-
}
|
|
1
|
+
|
|
2
|
+
import { DyNTS_SingletonServiceBase } from '../base/singleton.service-base';
|
|
3
|
+
|
|
4
|
+
export class DyNTS_Service_Collection<T> extends DyNTS_SingletonServiceBase {
|
|
5
|
+
[service: string]: T;
|
|
6
|
+
}
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
import { DyFM_HttpCallType } from '@futdevpro/fsm-dynamo';
|
|
3
|
-
|
|
4
|
-
import { DyNTS_Endpoint_Params } from '../../_models/control-models/endpoint-params.control-model';
|
|
5
|
-
import { DyNTS_Controller } from './controller.service';
|
|
6
|
-
|
|
7
|
-
class TestController extends DyNTS_Controller {
|
|
8
|
-
setupEndpoints(): void {
|
|
9
|
-
this.endpoints = [
|
|
10
|
-
new DyNTS_Endpoint_Params({
|
|
11
|
-
name: 'testEndpoint',
|
|
12
|
-
type: DyFM_HttpCallType.get,
|
|
13
|
-
endpoint: '/test-endpoint',
|
|
14
|
-
preProcesses: [],
|
|
15
|
-
tasks: [
|
|
16
|
-
async (req: any, res: any) => {
|
|
17
|
-
res.send({ message: 'Test successful' });
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
}),
|
|
21
|
-
];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static getInstance(): TestController {
|
|
25
|
-
return new TestController();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
describe('| DyNTS_Controller', () => {
|
|
30
|
-
let controller: TestController;
|
|
31
|
-
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
controller = TestController.getInstance();
|
|
34
|
-
controller.setupEndpoints();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('| should initialize endpoints correctly', () => {
|
|
38
|
-
expect(controller.endpoints.length).toBe(1);
|
|
39
|
-
expect(controller.endpoints[0].name).toBe('testEndpoint');
|
|
40
|
-
expect(controller.endpoints[0].endpoint).toBe('/test-endpoint');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
/* it('| should execute task and send response', async () => {
|
|
44
|
-
const req = {};
|
|
45
|
-
const res = {
|
|
46
|
-
send: jasmine.createSpy('send'),
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
await controller.endpoints[0].tasks[0](req, res);
|
|
50
|
-
|
|
51
|
-
expect(res.send).toHaveBeenCalledWith({ message: 'Test successful' });
|
|
52
|
-
}); */
|
|
53
|
-
});
|
|
1
|
+
|
|
2
|
+
import { DyFM_HttpCallType } from '@futdevpro/fsm-dynamo';
|
|
3
|
+
|
|
4
|
+
import { DyNTS_Endpoint_Params } from '../../_models/control-models/endpoint-params.control-model';
|
|
5
|
+
import { DyNTS_Controller } from './controller.service';
|
|
6
|
+
|
|
7
|
+
class TestController extends DyNTS_Controller {
|
|
8
|
+
setupEndpoints(): void {
|
|
9
|
+
this.endpoints = [
|
|
10
|
+
new DyNTS_Endpoint_Params({
|
|
11
|
+
name: 'testEndpoint',
|
|
12
|
+
type: DyFM_HttpCallType.get,
|
|
13
|
+
endpoint: '/test-endpoint',
|
|
14
|
+
preProcesses: [],
|
|
15
|
+
tasks: [
|
|
16
|
+
async (req: any, res: any) => {
|
|
17
|
+
res.send({ message: 'Test successful' });
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
}),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static getInstance(): TestController {
|
|
25
|
+
return new TestController();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('| DyNTS_Controller', () => {
|
|
30
|
+
let controller: TestController;
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
controller = TestController.getInstance();
|
|
34
|
+
controller.setupEndpoints();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('| should initialize endpoints correctly', () => {
|
|
38
|
+
expect(controller.endpoints.length).toBe(1);
|
|
39
|
+
expect(controller.endpoints[0].name).toBe('testEndpoint');
|
|
40
|
+
expect(controller.endpoints[0].endpoint).toBe('/test-endpoint');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/* it('| should execute task and send response', async () => {
|
|
44
|
+
const req = {};
|
|
45
|
+
const res = {
|
|
46
|
+
send: jasmine.createSpy('send'),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
await controller.endpoints[0].tasks[0](req, res);
|
|
50
|
+
|
|
51
|
+
expect(res.send).toHaveBeenCalledWith({ message: 'Test successful' });
|
|
52
|
+
}); */
|
|
53
|
+
});
|