@friggframework/core 2.0.0-next.12 → 2.0.0-next.121
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/.eslintrc.json +18 -1
- package/CLAUDE.md +830 -0
- package/README.md +996 -50
- package/admin-scripts/index.js +52 -0
- package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
- package/admin-scripts/repositories/admin-script-execution-repository-interface.js +171 -0
- package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +238 -0
- package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +278 -0
- package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
- package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
- package/application/commands/README.md +451 -0
- package/application/commands/admin-script-commands.js +359 -0
- package/application/commands/credential-commands.js +262 -0
- package/application/commands/entity-commands.js +294 -0
- package/application/commands/integration-commands.js +419 -0
- package/application/commands/integration-mapping-commands.js +25 -0
- package/application/commands/process-commands.js +135 -0
- package/application/commands/report-commands.js +188 -0
- package/application/commands/scheduler-commands.js +263 -0
- package/application/commands/usage-commands.js +56 -0
- package/application/commands/user-commands.js +312 -0
- package/application/index.js +83 -0
- package/artifacts/repositories/artifact-repository-factory.js +19 -0
- package/artifacts/repositories/artifact-repository-interface.js +27 -0
- package/artifacts/repositories/artifact-repository-local.js +42 -0
- package/artifacts/repositories/artifact-repository-s3.js +61 -0
- package/assertions/index.js +0 -3
- package/core/CLAUDE.md +715 -0
- package/core/Worker.js +55 -24
- package/core/create-handler.js +121 -38
- package/core/index.js +8 -1
- package/core/invocation-scope.js +225 -0
- package/core/parameters-to-env.js +257 -0
- package/core/secrets-to-env.js +7 -6
- package/core/ssm-preload.mjs +34 -0
- package/credential/repositories/credential-active-type.js +32 -0
- package/credential/repositories/credential-repository-documentdb.js +355 -0
- package/credential/repositories/credential-repository-factory.js +54 -0
- package/credential/repositories/credential-repository-interface.js +113 -0
- package/credential/repositories/credential-repository-mongo.js +294 -0
- package/credential/repositories/credential-repository-postgres.js +312 -0
- package/credential/repositories/credential-repository.js +300 -0
- package/credential/use-cases/get-credential-for-user.js +25 -0
- package/credential/use-cases/update-authentication-status.js +15 -0
- package/database/MONGODB_TRANSACTION_FIX.md +198 -0
- package/database/adapters/lambda-invoker.js +97 -0
- package/database/config.js +147 -0
- package/database/documentdb-encryption-service.js +334 -0
- package/database/documentdb-utils.js +196 -0
- package/database/encryption/README.md +863 -0
- package/database/encryption/documentdb-encryption-service.md +3575 -0
- package/database/encryption/encryption-schema-registry.js +404 -0
- package/database/encryption/field-encryption-service.js +254 -0
- package/database/encryption/integration-mapping-encryption.js +97 -0
- package/database/encryption/logger.js +82 -0
- package/database/encryption/prisma-encryption-extension.js +241 -0
- package/database/index.js +21 -21
- package/database/prisma.js +182 -0
- package/database/repositories/health-check-repository-documentdb.js +138 -0
- package/database/repositories/health-check-repository-factory.js +48 -0
- package/database/repositories/health-check-repository-interface.js +82 -0
- package/database/repositories/health-check-repository-mongodb.js +89 -0
- package/database/repositories/health-check-repository-postgres.js +82 -0
- package/database/repositories/migration-status-repository-s3.js +137 -0
- package/database/use-cases/check-database-health-use-case.js +29 -0
- package/database/use-cases/check-database-state-use-case.js +81 -0
- package/database/use-cases/check-encryption-health-use-case.js +83 -0
- package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
- package/database/use-cases/get-migration-status-use-case.js +93 -0
- package/database/use-cases/resolve-migration-via-worker-use-case.js +49 -0
- package/database/use-cases/run-database-migration-use-case.js +139 -0
- package/database/use-cases/test-encryption-use-case.js +253 -0
- package/database/use-cases/trigger-database-migration-use-case.js +157 -0
- package/database/utils/mongodb-collection-utils.js +94 -0
- package/database/utils/mongodb-schema-init.js +108 -0
- package/database/utils/prisma-runner.js +491 -0
- package/database/utils/prisma-schema-parser.js +182 -0
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
- package/encrypt/Cryptor.js +34 -168
- package/encrypt/index.js +1 -2
- package/errors/client-safe-error.js +26 -0
- package/errors/fetch-error.js +59 -57
- package/errors/index.js +6 -0
- package/errors/mapping-already-exists-error.js +14 -0
- package/generated/prisma-mongodb/client.d.ts +1 -0
- package/generated/prisma-mongodb/client.js +5 -0
- package/generated/prisma-mongodb/default.d.ts +1 -0
- package/generated/prisma-mongodb/default.js +5 -0
- package/generated/prisma-mongodb/edge.d.ts +1 -0
- package/generated/prisma-mongodb/edge.js +386 -0
- package/generated/prisma-mongodb/index-browser.js +368 -0
- package/generated/prisma-mongodb/index.d.ts +27065 -0
- package/generated/prisma-mongodb/index.js +411 -0
- package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-mongodb/package.json +183 -0
- package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
- package/generated/prisma-mongodb/runtime/edge.js +35 -0
- package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
- package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
- package/generated/prisma-mongodb/runtime/library.js +147 -0
- package/generated/prisma-mongodb/runtime/react-native.js +84 -0
- package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
- package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
- package/generated/prisma-mongodb/schema.prisma +455 -0
- package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
- package/generated/prisma-mongodb/wasm.d.ts +1 -0
- package/generated/prisma-mongodb/wasm.js +393 -0
- package/generated/prisma-postgresql/client.d.ts +1 -0
- package/generated/prisma-postgresql/client.js +5 -0
- package/generated/prisma-postgresql/default.d.ts +1 -0
- package/generated/prisma-postgresql/default.js +5 -0
- package/generated/prisma-postgresql/edge.d.ts +1 -0
- package/generated/prisma-postgresql/edge.js +407 -0
- package/generated/prisma-postgresql/index-browser.js +389 -0
- package/generated/prisma-postgresql/index.d.ts +29904 -0
- package/generated/prisma-postgresql/index.js +432 -0
- package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-postgresql/package.json +183 -0
- package/generated/prisma-postgresql/query_engine_bg.js +2 -0
- package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
- package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
- package/generated/prisma-postgresql/runtime/edge.js +35 -0
- package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
- package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
- package/generated/prisma-postgresql/runtime/library.js +147 -0
- package/generated/prisma-postgresql/runtime/react-native.js +84 -0
- package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
- package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
- package/generated/prisma-postgresql/schema.prisma +436 -0
- package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
- package/generated/prisma-postgresql/wasm.d.ts +1 -0
- package/generated/prisma-postgresql/wasm.js +414 -0
- package/handlers/WEBHOOKS.md +682 -0
- package/handlers/app-definition-loader.js +103 -0
- package/handlers/app-handler-helpers.js +20 -6
- package/handlers/backend-utils.js +272 -46
- package/handlers/database-migration-handler.js +236 -0
- package/handlers/integration-event-dispatcher.js +68 -0
- package/handlers/middleware/admin-auth.js +73 -0
- package/handlers/routers/HEALTHCHECK.md +342 -0
- package/handlers/routers/auth.js +4 -15
- package/handlers/routers/db-migration.handler.js +29 -0
- package/handlers/routers/db-migration.js +329 -0
- package/handlers/routers/health.js +518 -0
- package/handlers/routers/integration-defined-routers.js +85 -10
- package/handlers/routers/integration-webhook-routers.js +87 -0
- package/handlers/routers/user.js +27 -5
- package/handlers/routers/websocket.js +31 -9
- package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
- package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
- package/handlers/workers/db-migration.js +438 -0
- package/handlers/workers/dlq-processor.js +89 -0
- package/handlers/workers/integration-defined-workers.js +13 -7
- package/index.js +123 -47
- package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +238 -0
- package/infrastructure/scheduler/index.js +33 -0
- package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
- package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
- package/integrations/EXTENSIONS.md +240 -0
- package/integrations/WEBHOOK-QUICKSTART.md +151 -0
- package/integrations/extension.js +254 -0
- package/integrations/index.js +20 -10
- package/integrations/integration-base.js +777 -74
- package/integrations/integration-router.js +399 -180
- package/integrations/options.js +1 -1
- package/integrations/repositories/config-patch-shared.js +43 -0
- package/integrations/repositories/integration-mapping-query-pipeline.js +152 -0
- package/integrations/repositories/integration-mapping-query.js +193 -0
- package/integrations/repositories/integration-mapping-repository-documentdb.js +406 -0
- package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
- package/integrations/repositories/integration-mapping-repository-interface.js +183 -0
- package/integrations/repositories/integration-mapping-repository-mongo.js +284 -0
- package/integrations/repositories/integration-mapping-repository-postgres.js +403 -0
- package/integrations/repositories/integration-mapping-repository.js +185 -0
- package/integrations/repositories/integration-repository-documentdb.js +354 -0
- package/integrations/repositories/integration-repository-factory.js +51 -0
- package/integrations/repositories/integration-repository-interface.js +219 -0
- package/integrations/repositories/integration-repository-mongo.js +502 -0
- package/integrations/repositories/integration-repository-postgres.js +550 -0
- package/integrations/repositories/process-repository-documentdb.js +311 -0
- package/integrations/repositories/process-repository-factory.js +53 -0
- package/integrations/repositories/process-repository-interface.js +136 -0
- package/integrations/repositories/process-repository-mongo.js +262 -0
- package/integrations/repositories/process-repository-postgres.js +380 -0
- package/integrations/repositories/process-update-ops-shared.js +112 -0
- package/integrations/repositories/report-id.js +13 -0
- package/integrations/tests/doubles/config-capturing-integration.js +81 -0
- package/integrations/tests/doubles/dummy-integration-class.js +113 -0
- package/integrations/tests/doubles/test-integration-repository.js +146 -0
- package/integrations/use-cases/add-entities-to-integration.js +92 -0
- package/integrations/use-cases/create-integration.js +253 -0
- package/integrations/use-cases/create-process.js +130 -0
- package/integrations/use-cases/delete-integration-for-user.js +130 -0
- package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
- package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
- package/integrations/use-cases/get-integration-for-user.js +78 -0
- package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
- package/integrations/use-cases/get-integration-instance.js +83 -0
- package/integrations/use-cases/get-integrations-for-user.js +88 -0
- package/integrations/use-cases/get-possible-integrations.js +27 -0
- package/integrations/use-cases/get-process.js +89 -0
- package/integrations/use-cases/index.js +19 -0
- package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
- package/integrations/use-cases/load-integration-context.js +71 -0
- package/integrations/use-cases/patch-integration-config.js +39 -0
- package/integrations/use-cases/process-errors.js +28 -0
- package/integrations/use-cases/remove-entities-from-integration.js +70 -0
- package/integrations/use-cases/update-integration-config.js +32 -0
- package/integrations/use-cases/update-integration-messages.js +44 -0
- package/integrations/use-cases/update-integration-status.js +32 -0
- package/integrations/use-cases/update-integration.js +92 -0
- package/integrations/use-cases/update-process-metrics.js +222 -0
- package/integrations/use-cases/update-process-state.js +163 -0
- package/integrations/utils/assert-entity-ids-input.js +42 -0
- package/integrations/utils/map-integration-dto.js +37 -0
- package/jest-global-setup-noop.js +3 -0
- package/jest-global-teardown-noop.js +3 -0
- package/jest.config.js +2 -0
- package/logs/.eslintrc.json +26 -1
- package/logs/__fixtures__/events.js +82 -0
- package/logs/__fixtures__/matchers.js +45 -0
- package/logs/__fixtures__/secrets.js +59 -0
- package/logs/__fixtures__/vectors.js +329 -0
- package/logs/__fixtures__/with-env.js +45 -0
- package/logs/context.js +109 -0
- package/logs/contract-keys.js +67 -0
- package/logs/debug-shims.js +46 -0
- package/logs/denied-keys.js +21 -0
- package/logs/index.js +14 -3
- package/logs/jest-logger-setup.js +25 -0
- package/logs/levels.js +71 -0
- package/logs/logger-runtime.js +137 -0
- package/logs/logger.js +134 -46
- package/logs/record.js +276 -0
- package/logs/redact.js +328 -0
- package/logs/serialize.js +329 -0
- package/logs/sinks.js +93 -0
- package/logs/summarize-event.js +163 -0
- package/{module-plugin → modules}/index.js +0 -10
- package/modules/module-factory.js +56 -0
- package/modules/module.js +320 -0
- package/modules/repositories/module-repository-documentdb.js +350 -0
- package/modules/repositories/module-repository-factory.js +40 -0
- package/modules/repositories/module-repository-interface.js +145 -0
- package/modules/repositories/module-repository-mongo.js +436 -0
- package/modules/repositories/module-repository-postgres.js +481 -0
- package/modules/repositories/module-repository.js +369 -0
- package/modules/requester/api-key.js +52 -0
- package/modules/requester/oauth-2.js +561 -0
- package/modules/requester/requester.js +605 -0
- package/{module-plugin → modules}/test/mock-api/api.js +8 -3
- package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
- package/modules/tests/doubles/test-module-factory.js +16 -0
- package/modules/tests/doubles/test-module-repository.js +39 -0
- package/modules/use-cases/get-entities-for-user.js +32 -0
- package/modules/use-cases/get-entity-options-by-id.js +71 -0
- package/modules/use-cases/get-entity-options-by-type.js +34 -0
- package/modules/use-cases/get-module-instance-from-type.js +34 -0
- package/modules/use-cases/get-module.js +74 -0
- package/modules/use-cases/process-authorization-callback.js +294 -0
- package/modules/use-cases/refresh-entity-options.js +72 -0
- package/modules/use-cases/test-module-auth.js +72 -0
- package/modules/utils/map-module-dto.js +20 -0
- package/modules/utils/to-credential-id.js +14 -0
- package/package.json +92 -52
- package/prisma-mongodb/schema.prisma +455 -0
- package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
- package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
- package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
- package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
- package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
- package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
- package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
- package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
- package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
- package/prisma-postgresql/migrations/20260705000000_create_usage_counter/migration.sql +26 -0
- package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
- package/prisma-postgresql/migrations/migration_lock.toml +3 -0
- package/prisma-postgresql/schema.prisma +436 -0
- package/queues/queue-delivery.js +41 -0
- package/queues/queuer-util.js +89 -21
- package/reporting/README.md +154 -0
- package/reporting/builtin-reports.js +6 -0
- package/reporting/index.js +13 -0
- package/reporting/report-base.js +49 -0
- package/reporting/reports/integrations-report.js +221 -0
- package/syncs/manager.js +468 -443
- package/syncs/repositories/sync-repository-documentdb.js +240 -0
- package/syncs/repositories/sync-repository-factory.js +43 -0
- package/syncs/repositories/sync-repository-interface.js +109 -0
- package/syncs/repositories/sync-repository-mongo.js +239 -0
- package/syncs/repositories/sync-repository-postgres.js +319 -0
- package/syncs/sync.js +0 -1
- package/telemetry/README.md +331 -0
- package/telemetry/bind-telemetry-context.js +77 -0
- package/telemetry/canonical-counters.js +52 -0
- package/telemetry/exporters.js +85 -0
- package/telemetry/index.js +26 -0
- package/telemetry/instrument-handler.js +104 -0
- package/telemetry/no-op-telemetry.js +71 -0
- package/telemetry/north-star.js +103 -0
- package/telemetry/otel-telemetry.js +232 -0
- package/telemetry/plugin-subscribers.js +77 -0
- package/telemetry/telemetry-config.js +120 -0
- package/telemetry/telemetry-context.js +51 -0
- package/telemetry/telemetry-event-bus.js +58 -0
- package/telemetry/telemetry-runtime.js +164 -0
- package/telemetry/telemetry-service.js +52 -0
- package/telemetry/usage-rollup-subscriber.js +116 -0
- package/token/repositories/token-repository-documentdb.js +137 -0
- package/token/repositories/token-repository-factory.js +40 -0
- package/token/repositories/token-repository-interface.js +131 -0
- package/token/repositories/token-repository-mongo.js +219 -0
- package/token/repositories/token-repository-postgres.js +264 -0
- package/token/repositories/token-repository.js +219 -0
- package/types/associations/index.d.ts +0 -17
- package/types/core/index.d.ts +12 -4
- package/types/database/index.d.ts +10 -2
- package/types/encrypt/index.d.ts +5 -3
- package/types/errors/index.d.ts +24 -10
- package/types/integrations/index.d.ts +3 -8
- package/types/logs/index.d.ts +61 -2
- package/types/module-plugin/index.d.ts +20 -69
- package/types/syncs/index.d.ts +0 -17
- package/usage/README.md +54 -0
- package/usage/index.js +17 -0
- package/usage/repositories/usage-repository-documentdb.js +194 -0
- package/usage/repositories/usage-repository-factory.js +25 -0
- package/usage/repositories/usage-repository-interface.js +37 -0
- package/usage/repositories/usage-repository-prisma.js +146 -0
- package/usage/tracked-metrics.js +38 -0
- package/usage/usage-windows.js +24 -0
- package/user/repositories/user-repository-documentdb.js +426 -0
- package/user/repositories/user-repository-factory.js +52 -0
- package/user/repositories/user-repository-interface.js +214 -0
- package/user/repositories/user-repository-mongo.js +323 -0
- package/user/repositories/user-repository-postgres.js +377 -0
- package/user/tests/doubles/test-user-repository.js +72 -0
- package/user/use-cases/authenticate-user.js +143 -0
- package/user/use-cases/authenticate-with-shared-secret.js +48 -0
- package/user/use-cases/create-individual-user.js +61 -0
- package/user/use-cases/create-organization-user.js +47 -0
- package/user/use-cases/create-token-for-user-id.js +30 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
- package/user/use-cases/get-user-from-bearer-token.js +82 -0
- package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
- package/user/use-cases/login-user.js +122 -0
- package/user/user.js +125 -0
- package/utils/backend-path.js +38 -0
- package/utils/index.js +6 -0
- package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
- package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
- package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
- package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
- package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
- package/websocket/repositories/websocket-connection-repository.js +161 -0
- package/assertions/is-equal.js +0 -17
- package/associations/model.js +0 -54
- package/database/models/IndividualUser.js +0 -76
- package/database/models/OrganizationUser.js +0 -29
- package/database/models/State.js +0 -9
- package/database/models/Token.js +0 -70
- package/database/models/UserModel.js +0 -7
- package/database/models/WebsocketConnection.js +0 -49
- package/database/mongo.js +0 -45
- package/database/mongoose.js +0 -5
- package/encrypt/Cryptor.test.js +0 -32
- package/encrypt/encrypt.js +0 -132
- package/encrypt/encrypt.test.js +0 -1069
- package/encrypt/test-encrypt.js +0 -107
- package/errors/base-error.test.js +0 -32
- package/errors/fetch-error.test.js +0 -79
- package/errors/halt-error.test.js +0 -11
- package/errors/validation-errors.test.js +0 -120
- package/handlers/routers/middleware/loadUser.js +0 -15
- package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
- package/integrations/create-frigg-backend.js +0 -31
- package/integrations/integration-factory.js +0 -251
- package/integrations/integration-mapping.js +0 -43
- package/integrations/integration-model.js +0 -46
- package/integrations/integration-user.js +0 -144
- package/integrations/test/integration-base.test.js +0 -144
- package/lambda/TimeoutCatcher.test.js +0 -68
- package/logs/logger.test.js +0 -76
- package/module-plugin/auther.js +0 -393
- package/module-plugin/credential.js +0 -22
- package/module-plugin/entity-manager.js +0 -70
- package/module-plugin/entity.js +0 -46
- package/module-plugin/manager.js +0 -169
- package/module-plugin/module-factory.js +0 -61
- package/module-plugin/requester/api-key.js +0 -36
- package/module-plugin/requester/oauth-2.js +0 -219
- package/module-plugin/requester/requester.js +0 -165
- package/module-plugin/requester/requester.test.js +0 -28
- package/module-plugin/test/auther.test.js +0 -97
- package/syncs/model.js +0 -62
- /package/{module-plugin → modules}/ModuleConstants.js +0 -0
- /package/{module-plugin → modules}/requester/basic.js +0 -0
- /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
package/core/Worker.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { SQSClient, GetQueueUrlCommand, SendMessageCommand } = require('@aws-sdk/client-sqs');
|
|
2
2
|
const _ = require('lodash');
|
|
3
3
|
const { RequiredPropertyError } = require('../errors');
|
|
4
4
|
const { get } = require('../assertions');
|
|
5
|
+
const { readQueueDelivery } = require('../queues/queue-delivery');
|
|
6
|
+
const { runMessageScope } = require('./invocation-scope');
|
|
7
|
+
const { getLogger } = require('../logs');
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
const
|
|
9
|
+
const sqs = new SQSClient({ region: process.env.AWS_REGION });
|
|
10
|
+
const log = getLogger('frigg.worker');
|
|
8
11
|
|
|
9
12
|
class Worker {
|
|
10
13
|
async getQueueURL(params) {
|
|
@@ -12,25 +15,59 @@ class Worker {
|
|
|
12
15
|
// let params = {
|
|
13
16
|
// QueueName: process.env.QueueName
|
|
14
17
|
// };
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
reject(err);
|
|
19
|
-
} else {
|
|
20
|
-
resolve(data.QueueUrl);
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
});
|
|
18
|
+
const command = new GetQueueUrlCommand(params);
|
|
19
|
+
const data = await sqs.send(command);
|
|
20
|
+
return data.QueueUrl;
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
async run(params, context = {}) {
|
|
27
24
|
const records = get(params, 'Records');
|
|
25
|
+
const batchItemFailures = [];
|
|
26
|
+
|
|
27
|
+
console.log(
|
|
28
|
+
`[Worker] run: processing ${records.length} record(s)`
|
|
29
|
+
);
|
|
28
30
|
|
|
29
31
|
for (const record of records) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
await runMessageScope(record, async () => {
|
|
33
|
+
// messageId, receiveCount and the event come from the scope.
|
|
34
|
+
log.debug('Record started', { eventName: 'frigg.worker.record_started' });
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const runParams = JSON.parse(record.body);
|
|
38
|
+
this._validateParams(runParams);
|
|
39
|
+
await this._run(runParams, context, readQueueDelivery(record));
|
|
40
|
+
log.debug('Record succeeded', { eventName: 'frigg.worker.record_succeeded' });
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error.isHaltError) {
|
|
43
|
+
// HaltError means "discard this message, don't retry".
|
|
44
|
+
// Treat as success so SQS deletes it from the queue.
|
|
45
|
+
// Logged explicitly — silent discards made prod debugging
|
|
46
|
+
// extremely hard; keep this visible.
|
|
47
|
+
log.error('Record halted (discarded, no retry)', {
|
|
48
|
+
eventName: 'frigg.worker.record_halted',
|
|
49
|
+
statusCode: error.statusCode,
|
|
50
|
+
error,
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// The message goes back to SQS, so WARN (ADR-048 §4).
|
|
55
|
+
log.warn('Record failed, returned for retry', {
|
|
56
|
+
eventName: 'frigg.worker.record_failed',
|
|
57
|
+
error,
|
|
58
|
+
});
|
|
59
|
+
batchItemFailures.push({ itemIdentifier: record.messageId });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
33
62
|
}
|
|
63
|
+
|
|
64
|
+
if (batchItemFailures.length > 0) {
|
|
65
|
+
console.warn(
|
|
66
|
+
`[Worker] run: returning ${batchItemFailures.length} batchItemFailure(s) of ${records.length}`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { batchItemFailures };
|
|
34
71
|
}
|
|
35
72
|
|
|
36
73
|
async _run(params, context = {}) {
|
|
@@ -54,15 +91,9 @@ class Worker {
|
|
|
54
91
|
}
|
|
55
92
|
|
|
56
93
|
async sendAsyncSQSMessage(params) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
reject(err);
|
|
61
|
-
} else {
|
|
62
|
-
resolve(data.MessageId);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
94
|
+
const command = new SendMessageCommand(params);
|
|
95
|
+
const data = await sqs.send(command);
|
|
96
|
+
return data.MessageId;
|
|
66
97
|
}
|
|
67
98
|
|
|
68
99
|
// Throw an exception if the params do not validate
|
package/core/create-handler.js
CHANGED
|
@@ -2,9 +2,25 @@
|
|
|
2
2
|
// REMOVING FOR NOW UNTIL WE ADD WEBPACK BACK IN
|
|
3
3
|
// require('source-map-support').install();
|
|
4
4
|
|
|
5
|
-
const {
|
|
6
|
-
const {
|
|
5
|
+
const { getLogger, toSanitizedSurrogate } = require('../logs');
|
|
6
|
+
const {
|
|
7
|
+
summarizeLambdaEvent,
|
|
8
|
+
toScopeInvocation,
|
|
9
|
+
toRequestDetails,
|
|
10
|
+
} = require('../logs/summarize-event');
|
|
11
|
+
const {
|
|
12
|
+
runInvocationScope,
|
|
13
|
+
DEFAULT_FLUSH_TIMEOUT_MS,
|
|
14
|
+
} = require('./invocation-scope');
|
|
7
15
|
const { secretsToEnv } = require('./secrets-to-env');
|
|
16
|
+
const { parametersToEnv } = require('./parameters-to-env');
|
|
17
|
+
const {
|
|
18
|
+
getTelemetry,
|
|
19
|
+
getUsageRollupSubscriber,
|
|
20
|
+
getPluginTelemetrySubscribers,
|
|
21
|
+
} = require('../telemetry/telemetry-runtime');
|
|
22
|
+
|
|
23
|
+
const log = getLogger('frigg.handler');
|
|
8
24
|
|
|
9
25
|
const createHandler = (optionByName = {}) => {
|
|
10
26
|
const {
|
|
@@ -12,6 +28,9 @@ const createHandler = (optionByName = {}) => {
|
|
|
12
28
|
isUserFacingResponse = true,
|
|
13
29
|
method,
|
|
14
30
|
shouldUseDatabase = true,
|
|
31
|
+
telemetry,
|
|
32
|
+
flushTimeoutMs = DEFAULT_FLUSH_TIMEOUT_MS,
|
|
33
|
+
usageRollup,
|
|
15
34
|
} = optionByName;
|
|
16
35
|
|
|
17
36
|
if (!method) {
|
|
@@ -19,50 +38,114 @@ const createHandler = (optionByName = {}) => {
|
|
|
19
38
|
}
|
|
20
39
|
|
|
21
40
|
return async (event, context) => {
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
const eventSummary = summarizeLambdaEvent(event);
|
|
42
|
+
const activeTelemetry = telemetry || getTelemetry();
|
|
43
|
+
const activeUsageRollup =
|
|
44
|
+
usageRollup !== undefined
|
|
45
|
+
? usageRollup
|
|
46
|
+
: getUsageRollupSubscriber();
|
|
24
47
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
48
|
+
// Wire adopter-declared telemetry subscribers once per cold start.
|
|
49
|
+
// Memoized in the singleton, so this is a cheap
|
|
50
|
+
// no-op after the first invocation.
|
|
51
|
+
getPluginTelemetrySubscribers();
|
|
30
52
|
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
const scopeFields = {
|
|
54
|
+
requestId: context?.awsRequestId,
|
|
55
|
+
handlerName: eventName,
|
|
56
|
+
method: eventSummary.method,
|
|
57
|
+
route: eventSummary.route,
|
|
58
|
+
routeKey: eventSummary.routeKey,
|
|
59
|
+
invocation: toScopeInvocation(eventSummary),
|
|
60
|
+
};
|
|
61
|
+
// Path, query keys and header names go only on the entry and failure
|
|
62
|
+
// records; the logger adds them to the scope's invocation.
|
|
63
|
+
const requestDetails = toRequestDetails(eventSummary);
|
|
33
64
|
|
|
34
|
-
|
|
35
|
-
|
|
65
|
+
return runInvocationScope(
|
|
66
|
+
scopeFields,
|
|
67
|
+
async () => {
|
|
68
|
+
try {
|
|
69
|
+
log.info('Handler invoked', {
|
|
70
|
+
eventName: 'frigg.handler.invoked',
|
|
71
|
+
invocation: requestDetails,
|
|
72
|
+
});
|
|
36
73
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
74
|
+
// If enabled (i.e. if SECRET_ARN is set in process.env) Fetch secrets from AWS Secrets Manager, and set them as environment variables.
|
|
75
|
+
await secretsToEnv();
|
|
40
76
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
} catch (error) {
|
|
44
|
-
flushDebugLog(error);
|
|
45
|
-
|
|
46
|
-
// Don't leak implementation details to end users.
|
|
47
|
-
if (isUserFacingResponse) {
|
|
48
|
-
return {
|
|
49
|
-
statusCode: 500,
|
|
50
|
-
body: JSON.stringify({
|
|
51
|
-
error: 'An Internal Error Occurred',
|
|
52
|
-
}),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
77
|
+
// If enabled (i.e. if SSM_PARAMETER_PREFIX and FRIGG_SSM_OFFLOADED_KEYS are set) fetch offloaded params from SSM Parameter Store into process.env.
|
|
78
|
+
await parametersToEnv();
|
|
55
79
|
|
|
56
|
-
|
|
80
|
+
// Lazy-required so DB-free handlers never load the Prisma client.
|
|
81
|
+
if (shouldUseDatabase) {
|
|
82
|
+
const { connectPrisma } = require('../database/prisma');
|
|
83
|
+
await connectPrisma();
|
|
84
|
+
}
|
|
57
85
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
86
|
+
// Helps reuse the database connection. Lowers response times.
|
|
87
|
+
context.callbackWaitsForEmptyEventLoop = false;
|
|
62
88
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
89
|
+
// Run the Lambda
|
|
90
|
+
return await method(event, context);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Allow client-safe errors to pass through with their actual message
|
|
93
|
+
if (isUserFacingResponse && error.isClientSafe === true) {
|
|
94
|
+
const statusCode = error.statusCode || 400;
|
|
95
|
+
log.warn('Request rejected', {
|
|
96
|
+
eventName: 'frigg.handler.rejected',
|
|
97
|
+
statusCode,
|
|
98
|
+
error,
|
|
99
|
+
});
|
|
100
|
+
return {
|
|
101
|
+
statusCode,
|
|
102
|
+
body: JSON.stringify({
|
|
103
|
+
error: error.message,
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Server-to-server: halt errors succeed and won't be
|
|
109
|
+
// retried, so the halt itself is the failure record.
|
|
110
|
+
if (!isUserFacingResponse && error.isHaltError === true) {
|
|
111
|
+
log.error('Handler halted', {
|
|
112
|
+
eventName: 'frigg.handler.halted',
|
|
113
|
+
invocation: requestDetails,
|
|
114
|
+
error,
|
|
115
|
+
});
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
log.error('Handler failed', {
|
|
120
|
+
eventName: 'frigg.handler.failed',
|
|
121
|
+
invocation: requestDetails,
|
|
122
|
+
error,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Don't leak implementation details to end users.
|
|
126
|
+
if (isUserFacingResponse) {
|
|
127
|
+
return {
|
|
128
|
+
statusCode: 500,
|
|
129
|
+
body: JSON.stringify({
|
|
130
|
+
error: 'An Internal Error Occurred',
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// The Lambda runtime writes a rethrown error itself, so
|
|
136
|
+
// rethrow a sanitized copy (ADR-048 §6 item 11).
|
|
137
|
+
throw toSanitizedSurrogate(error);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
telemetry: activeTelemetry,
|
|
142
|
+
usageRollup: activeUsageRollup,
|
|
143
|
+
eventSummary,
|
|
144
|
+
shouldUseDatabase,
|
|
145
|
+
flushTimeoutMs,
|
|
146
|
+
context,
|
|
147
|
+
}
|
|
148
|
+
);
|
|
66
149
|
};
|
|
67
150
|
};
|
|
68
151
|
|
package/core/index.js
CHANGED
|
@@ -2,5 +2,12 @@ const { Delegate } = require('./Delegate');
|
|
|
2
2
|
const { Worker } = require('./Worker');
|
|
3
3
|
const { loadInstalledModules } = require('./load-installed-modules');
|
|
4
4
|
const { createHandler } = require('./create-handler');
|
|
5
|
+
const { runInvocationScope } = require('./invocation-scope');
|
|
5
6
|
|
|
6
|
-
module.exports = {
|
|
7
|
+
module.exports = {
|
|
8
|
+
Delegate,
|
|
9
|
+
Worker,
|
|
10
|
+
loadInstalledModules,
|
|
11
|
+
createHandler,
|
|
12
|
+
runInvocationScope,
|
|
13
|
+
};
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
const { runInContext, LOGGER_SCOPE_KEY } = require('../logs/context');
|
|
2
|
+
const { summarizeMessageBody } = require('../logs/summarize-event');
|
|
3
|
+
const { flushSinks, hasFlushableSinks } = require('../logs/logger-runtime');
|
|
4
|
+
|
|
5
|
+
// Bounds the tail latency telemetry adds to every warm invocation. Kept low so
|
|
6
|
+
// an unreachable OTLP endpoint (e.g. a VPC Lambda with no NAT/egress) costs at
|
|
7
|
+
// most this, not multiple seconds. Override with OTEL_FLUSH_TIMEOUT_MS.
|
|
8
|
+
const DEFAULT_FLUSH_TIMEOUT_MS =
|
|
9
|
+
Number(process.env.OTEL_FLUSH_TIMEOUT_MS) || 500;
|
|
10
|
+
|
|
11
|
+
// Time kept back from the Lambda deadline, so a slow flush never becomes a
|
|
12
|
+
// Lambda timeout.
|
|
13
|
+
const FLUSH_MARGIN_MS = 50;
|
|
14
|
+
|
|
15
|
+
// setTimeout fires at once for a delay above this.
|
|
16
|
+
const MAX_TIMER_MS = 2 ** 31 - 1;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Fold the invocation's buffered usage counters into the durable store, then
|
|
20
|
+
* clear the buffer. On an SQS redelivery (ApproximateReceiveCount > 1) we
|
|
21
|
+
* DISCARD rather than flush — the prior delivery already counted, and the usage
|
|
22
|
+
* accuracy contract is "approximate, skip obvious redeliveries". Fully guarded.
|
|
23
|
+
*/
|
|
24
|
+
async function flushUsageRollup(subscriber, eventSummary, shouldUseDatabase) {
|
|
25
|
+
if (!subscriber) return;
|
|
26
|
+
try {
|
|
27
|
+
// Persisting usage requires a DB connection. DB-free handlers (e.g. the
|
|
28
|
+
// webhook-receipt route) never called connectPrisma, so drop the buffer
|
|
29
|
+
// instead of issuing a connectionless Prisma write.
|
|
30
|
+
if (!shouldUseDatabase) {
|
|
31
|
+
subscriber.discard();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Discard only when EVERY record in the batch is a redelivery. The buffer
|
|
35
|
+
// is invocation-scoped (not per-message), so discarding on *any*
|
|
36
|
+
// redelivery would drop the fresh records' counts too (silent
|
|
37
|
+
// under-count). For a mixed batch we flush: preserving fresh counts and
|
|
38
|
+
// at worst re-counting the one redelivered record is strictly better than
|
|
39
|
+
// losing fresh data for an approximate store. (Integration queue workers
|
|
40
|
+
// are batchSize:1 today, so a batch is all-or-nothing; this keeps it
|
|
41
|
+
// correct if batchSize is ever raised.)
|
|
42
|
+
const records = Array.isArray(eventSummary?.records)
|
|
43
|
+
? eventSummary.records
|
|
44
|
+
: [];
|
|
45
|
+
const allRedelivered =
|
|
46
|
+
records.length > 0 &&
|
|
47
|
+
records.every((r) => Number(r.receiveCount) > 1);
|
|
48
|
+
if (allRedelivered) {
|
|
49
|
+
subscriber.discard();
|
|
50
|
+
} else {
|
|
51
|
+
await subscriber.flush();
|
|
52
|
+
}
|
|
53
|
+
} catch (_) {
|
|
54
|
+
// Usage rollup must never break the handler.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isTelemetryEnabled(telemetry) {
|
|
59
|
+
try {
|
|
60
|
+
return Boolean(
|
|
61
|
+
telemetry &&
|
|
62
|
+
typeof telemetry.isEnabled === 'function' &&
|
|
63
|
+
telemetry.isEnabled()
|
|
64
|
+
);
|
|
65
|
+
} catch (_) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Flush telemetry before the Lambda container freezes. Because
|
|
72
|
+
* `callbackWaitsForEmptyEventLoop=false` stops the event loop the moment the
|
|
73
|
+
* handler returns, OTel's timer-driven batch processors would never fire — so
|
|
74
|
+
* spans/metrics must be flushed here. No timer of its own: the caller bounds it
|
|
75
|
+
* with `withDeadline`. Fully guarded, so a flush failure never breaks the
|
|
76
|
+
* handler.
|
|
77
|
+
*/
|
|
78
|
+
async function flushTelemetry(telemetry, { signal } = {}) {
|
|
79
|
+
if (!isTelemetryEnabled(telemetry) || signal?.aborted) return;
|
|
80
|
+
try {
|
|
81
|
+
await telemetry.forceFlush();
|
|
82
|
+
} catch (_) {
|
|
83
|
+
// Telemetry flush must never break the handler.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Run `fn(signal)` for at most `ms`. Owns the only timer and clears it when the
|
|
89
|
+
* work settles. Aborts the signal at the deadline. Never rejects, and a late
|
|
90
|
+
* rejection of the work is swallowed.
|
|
91
|
+
*/
|
|
92
|
+
function withDeadline(ms, fn) {
|
|
93
|
+
const controller = new AbortController();
|
|
94
|
+
return new Promise((resolve) => {
|
|
95
|
+
let timer;
|
|
96
|
+
const finish = () => {
|
|
97
|
+
clearTimeout(timer);
|
|
98
|
+
resolve();
|
|
99
|
+
};
|
|
100
|
+
timer = setTimeout(() => {
|
|
101
|
+
controller.abort();
|
|
102
|
+
finish();
|
|
103
|
+
}, Math.min(ms, MAX_TIMER_MS));
|
|
104
|
+
let work;
|
|
105
|
+
try {
|
|
106
|
+
work = Promise.resolve(fn(controller.signal));
|
|
107
|
+
} catch (_) {
|
|
108
|
+
work = Promise.resolve();
|
|
109
|
+
}
|
|
110
|
+
work.then(finish, finish);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function remainingTimeMs(context) {
|
|
115
|
+
try {
|
|
116
|
+
const remaining = context?.getRemainingTimeInMillis?.();
|
|
117
|
+
return typeof remaining === 'number' ? remaining : Infinity;
|
|
118
|
+
} catch (_) {
|
|
119
|
+
return Infinity;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function flushInvocation({
|
|
124
|
+
telemetry,
|
|
125
|
+
usageRollup,
|
|
126
|
+
eventSummary,
|
|
127
|
+
shouldUseDatabase,
|
|
128
|
+
flushTimeoutMs,
|
|
129
|
+
context,
|
|
130
|
+
}) {
|
|
131
|
+
// ADR-048 §11: the deadline is fixed at flush start. The usage rollup
|
|
132
|
+
// emits no telemetry, so it runs in parallel with no bound of its own.
|
|
133
|
+
const deadline = Math.min(
|
|
134
|
+
flushTimeoutMs,
|
|
135
|
+
remainingTimeMs(context) - FLUSH_MARGIN_MS
|
|
136
|
+
);
|
|
137
|
+
await Promise.all([
|
|
138
|
+
flushUsageRollup(usageRollup, eventSummary, shouldUseDatabase),
|
|
139
|
+
flushBounded(telemetry, deadline),
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function flushBounded(telemetry, deadline) {
|
|
144
|
+
const flushes = [];
|
|
145
|
+
if (isTelemetryEnabled(telemetry)) {
|
|
146
|
+
flushes.push((signal) => flushTelemetry(telemetry, { signal }));
|
|
147
|
+
}
|
|
148
|
+
if (hasFlushableSinks()) {
|
|
149
|
+
flushes.push((signal) => flushSinks({ signal }));
|
|
150
|
+
}
|
|
151
|
+
if (!flushes.length || !(deadline > 0)) return undefined;
|
|
152
|
+
return withDeadline(deadline, (signal) =>
|
|
153
|
+
Promise.allSettled(flushes.map((flush) => flush(signal)))
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Open the logger scope for one invocation, run `fn` inside it, then flush.
|
|
159
|
+
* `fields` (requestId, handlerName, method, route, routeKey, invocation, ...)
|
|
160
|
+
* go into the scope's logger sub-object and never reach the telemetry bus.
|
|
161
|
+
*/
|
|
162
|
+
async function runInvocationScope(fields, fn, opts = {}) {
|
|
163
|
+
const {
|
|
164
|
+
telemetry,
|
|
165
|
+
usageRollup,
|
|
166
|
+
eventSummary,
|
|
167
|
+
shouldUseDatabase = true,
|
|
168
|
+
flushTimeoutMs = DEFAULT_FLUSH_TIMEOUT_MS,
|
|
169
|
+
context,
|
|
170
|
+
} = opts;
|
|
171
|
+
return runInContext({ [LOGGER_SCOPE_KEY]: { ...(fields || {}) } }, async () => {
|
|
172
|
+
try {
|
|
173
|
+
return await fn();
|
|
174
|
+
} finally {
|
|
175
|
+
// Every step is guarded, so a flush never changes the result.
|
|
176
|
+
await flushInvocation({
|
|
177
|
+
telemetry,
|
|
178
|
+
usageRollup,
|
|
179
|
+
eventSummary,
|
|
180
|
+
shouldUseDatabase,
|
|
181
|
+
flushTimeoutMs,
|
|
182
|
+
context,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function toCount(value) {
|
|
189
|
+
const count = Number(value);
|
|
190
|
+
return value !== undefined && value !== null && Number.isFinite(count)
|
|
191
|
+
? count
|
|
192
|
+
: undefined;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Open the logger scope for one SQS message: messageId, receiveCount and the
|
|
197
|
+
* Frigg ids the body carries. No flush; the invocation scope owns that.
|
|
198
|
+
*/
|
|
199
|
+
function runMessageScope(record, fn) {
|
|
200
|
+
const { event, processId, integrationId } = summarizeMessageBody(
|
|
201
|
+
record?.body
|
|
202
|
+
);
|
|
203
|
+
return runInContext(
|
|
204
|
+
{
|
|
205
|
+
[LOGGER_SCOPE_KEY]: {
|
|
206
|
+
messageId: record?.messageId,
|
|
207
|
+
receiveCount: toCount(record?.attributes?.ApproximateReceiveCount),
|
|
208
|
+
integrationEvent: event,
|
|
209
|
+
processId,
|
|
210
|
+
integrationId,
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
fn
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
module.exports = {
|
|
218
|
+
runInvocationScope,
|
|
219
|
+
runMessageScope,
|
|
220
|
+
withDeadline,
|
|
221
|
+
flushTelemetry,
|
|
222
|
+
flushUsageRollup,
|
|
223
|
+
FLUSH_MARGIN_MS,
|
|
224
|
+
DEFAULT_FLUSH_TIMEOUT_MS,
|
|
225
|
+
};
|