@ductape/sdk 0.0.4-v99 → 0.0.5

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.
Files changed (295) hide show
  1. package/dist/agents/agent-context.d.ts +3 -1
  2. package/dist/agents/agent-context.js +19 -3
  3. package/dist/agents/agent-context.js.map +1 -1
  4. package/dist/agents/agents.service.js +9 -5
  5. package/dist/agents/agents.service.js.map +1 -1
  6. package/dist/agents/types/agents.types.d.ts +14 -1
  7. package/dist/agents/types/agents.types.js.map +1 -1
  8. package/dist/api/services/appApi.service.js +15 -6
  9. package/dist/api/services/appApi.service.js.map +1 -1
  10. package/dist/api/services/logsApi.service.d.ts +51 -0
  11. package/dist/api/services/logsApi.service.js +19 -2
  12. package/dist/api/services/logsApi.service.js.map +1 -1
  13. package/dist/api/services/processorApi.service.d.ts +568 -2
  14. package/dist/api/services/processorApi.service.js +412 -21
  15. package/dist/api/services/processorApi.service.js.map +1 -1
  16. package/dist/api/services/productsApi.service.d.ts +20 -0
  17. package/dist/api/services/productsApi.service.js +44 -15
  18. package/dist/api/services/productsApi.service.js.map +1 -1
  19. package/dist/api/services/secretsApi.service.js +0 -11
  20. package/dist/api/services/secretsApi.service.js.map +1 -1
  21. package/dist/api/services/webhooksApi.service.js +13 -6
  22. package/dist/api/services/webhooksApi.service.js.map +1 -1
  23. package/dist/api/services/workflowApi.service.js +30 -12
  24. package/dist/api/services/workflowApi.service.js.map +1 -1
  25. package/dist/api/urls.d.ts +26 -0
  26. package/dist/api/urls.js +30 -3
  27. package/dist/api/urls.js.map +1 -1
  28. package/dist/apps/validators/joi-validators/update.appAction.validator.js +12 -1
  29. package/dist/apps/validators/joi-validators/update.appAction.validator.js.map +1 -1
  30. package/dist/brokers/brokers.service.d.ts +140 -2
  31. package/dist/brokers/brokers.service.js +444 -36
  32. package/dist/brokers/brokers.service.js.map +1 -1
  33. package/dist/brokers/types/index.d.ts +251 -0
  34. package/dist/brokers/utils/providers/rabbitmq.service.d.ts +14 -4
  35. package/dist/brokers/utils/providers/rabbitmq.service.js +22 -35
  36. package/dist/brokers/utils/providers/rabbitmq.service.js.map +1 -1
  37. package/dist/cache/cache.manager.d.ts +84 -5
  38. package/dist/cache/cache.manager.js +478 -38
  39. package/dist/cache/cache.manager.js.map +1 -1
  40. package/dist/cache/cache.service.d.ts +5 -0
  41. package/dist/cache/cache.service.js +163 -6
  42. package/dist/cache/cache.service.js.map +1 -1
  43. package/dist/cache/index.d.ts +1 -1
  44. package/dist/cache/index.js +3 -1
  45. package/dist/cache/index.js.map +1 -1
  46. package/dist/cache/types/index.d.ts +4 -0
  47. package/dist/database/databases.service.d.ts +70 -2
  48. package/dist/database/databases.service.js +150 -35
  49. package/dist/database/databases.service.js.map +1 -1
  50. package/dist/database/types/dashboard.interface.d.ts +74 -0
  51. package/dist/database/types/dashboard.interface.js +7 -0
  52. package/dist/database/types/dashboard.interface.js.map +1 -0
  53. package/dist/database/types/index.d.ts +1 -0
  54. package/dist/graph/graphs.service.d.ts +50 -12
  55. package/dist/graph/graphs.service.js +689 -203
  56. package/dist/graph/graphs.service.js.map +1 -1
  57. package/dist/graph/types/connection.interface.d.ts +2 -2
  58. package/dist/index.d.ts +286 -4
  59. package/dist/index.js +370 -21
  60. package/dist/index.js.map +1 -1
  61. package/dist/logs/logs.types.d.ts +16 -3
  62. package/dist/logs/logs.types.js +11 -0
  63. package/dist/logs/logs.types.js.map +1 -1
  64. package/dist/notifications/notifications.service.d.ts +3 -0
  65. package/dist/notifications/notifications.service.js +57 -14
  66. package/dist/notifications/notifications.service.js.map +1 -1
  67. package/dist/notifications/types/notifications.types.d.ts +50 -0
  68. package/dist/processor/services/processor.service.d.ts +132 -8
  69. package/dist/processor/services/processor.service.js +1174 -267
  70. package/dist/processor/services/processor.service.js.map +1 -1
  71. package/dist/processor/utils/processor.utils.d.ts +5 -0
  72. package/dist/processor/utils/processor.utils.js +65 -12
  73. package/dist/processor/utils/processor.utils.js.map +1 -1
  74. package/dist/processor/utils/storage.util.js +11 -2
  75. package/dist/processor/utils/storage.util.js.map +1 -1
  76. package/dist/products/services/products.service.d.ts +19 -2
  77. package/dist/products/services/products.service.js +388 -54
  78. package/dist/products/services/products.service.js.map +1 -1
  79. package/dist/products/validators/joi-validators/create.productFeature.validator.js +1 -1
  80. package/dist/products/validators/joi-validators/create.productJob.validator.js +2 -2
  81. package/dist/products/validators/joi-validators/create.productJob.validator.js.map +1 -1
  82. package/dist/products/validators/joi-validators/create.productMessageBrokerTopic.validator.js +1 -0
  83. package/dist/products/validators/joi-validators/create.productMessageBrokerTopic.validator.js.map +1 -1
  84. package/dist/products/validators/joi-validators/create.productNotification.validator.js +23 -12
  85. package/dist/products/validators/joi-validators/create.productNotification.validator.js.map +1 -1
  86. package/dist/resilience/fallback.service.d.ts +1 -0
  87. package/dist/resilience/fallback.service.js +2 -0
  88. package/dist/resilience/fallback.service.js.map +1 -1
  89. package/dist/resilience/quota.service.d.ts +1 -0
  90. package/dist/resilience/quota.service.js +2 -0
  91. package/dist/resilience/quota.service.js.map +1 -1
  92. package/dist/secrets/secrets.resolver.js +4 -1
  93. package/dist/secrets/secrets.resolver.js.map +1 -1
  94. package/dist/secrets/secrets.service.js +0 -12
  95. package/dist/secrets/secrets.service.js.map +1 -1
  96. package/dist/secrets/secrets.types.d.ts +3 -3
  97. package/dist/secrets/secrets.types.js +5 -5
  98. package/dist/secrets/secrets.types.js.map +1 -1
  99. package/dist/sessions/index.d.ts +1 -1
  100. package/dist/sessions/index.js +4 -1
  101. package/dist/sessions/index.js.map +1 -1
  102. package/dist/sessions/sessions.helper.d.ts +23 -3
  103. package/dist/sessions/sessions.helper.js +20 -3
  104. package/dist/sessions/sessions.helper.js.map +1 -1
  105. package/dist/sessions/sessions.resolver.d.ts +31 -0
  106. package/dist/sessions/sessions.resolver.js +230 -1
  107. package/dist/sessions/sessions.resolver.js.map +1 -1
  108. package/dist/sessions/sessions.service.d.ts +18 -2
  109. package/dist/sessions/sessions.service.js +121 -57
  110. package/dist/sessions/sessions.service.js.map +1 -1
  111. package/dist/sessions/types/index.d.ts +65 -21
  112. package/dist/storage/storage.service.d.ts +3 -0
  113. package/dist/storage/storage.service.js +179 -39
  114. package/dist/storage/storage.service.js.map +1 -1
  115. package/dist/types/index.types.d.ts +2 -0
  116. package/dist/types/inputs.types.d.ts +1 -0
  117. package/dist/types/inputs.types.js +3 -2
  118. package/dist/types/inputs.types.js.map +1 -1
  119. package/dist/types/processor.types.d.ts +72 -6
  120. package/dist/types/processor.types.js.map +1 -1
  121. package/dist/types/productsBuilder.types.d.ts +10 -0
  122. package/dist/types/productsBuilder.types.js +4 -0
  123. package/dist/types/productsBuilder.types.js.map +1 -1
  124. package/dist/vector/adapters/weaviate.adapter.js +22 -6
  125. package/dist/vector/adapters/weaviate.adapter.js.map +1 -1
  126. package/dist/vector/vector-database.service.d.ts +4 -2
  127. package/dist/vector/vector-database.service.js +71 -29
  128. package/dist/vector/vector-database.service.js.map +1 -1
  129. package/dist/workflows/types/workflows.types.d.ts +61 -3
  130. package/dist/workflows/types/workflows.types.js.map +1 -1
  131. package/dist/workflows/workflow-builder.js +17 -2
  132. package/dist/workflows/workflow-builder.js.map +1 -1
  133. package/dist/workflows/workflow-executor.d.ts +97 -18
  134. package/dist/workflows/workflow-executor.js +1449 -244
  135. package/dist/workflows/workflow-executor.js.map +1 -1
  136. package/dist/workflows/workflows.service.d.ts +2 -0
  137. package/dist/workflows/workflows.service.js +538 -74
  138. package/dist/workflows/workflows.service.js.map +1 -1
  139. package/package.json +11 -1
  140. package/dist/processor/services/fallback.service.d.ts +0 -5
  141. package/dist/processor/services/fallback.service.js +0 -43
  142. package/dist/processor/services/fallback.service.js.map +0 -1
  143. package/dist/processor/services/messagebrokers/aws-sqs.service.d.ts +0 -15
  144. package/dist/processor/services/messagebrokers/aws-sqs.service.js +0 -77
  145. package/dist/processor/services/messagebrokers/aws-sqs.service.js.map +0 -1
  146. package/dist/processor/services/messagebrokers/google-pubsub.service.d.ts +0 -16
  147. package/dist/processor/services/messagebrokers/google-pubsub.service.js +0 -34
  148. package/dist/processor/services/messagebrokers/google-pubsub.service.js.map +0 -1
  149. package/dist/processor/services/messagebrokers/index.d.ts +0 -3
  150. package/dist/processor/services/messagebrokers/index.js +0 -26
  151. package/dist/processor/services/messagebrokers/index.js.map +0 -1
  152. package/dist/processor/services/messagebrokers/kafka.service.d.ts +0 -14
  153. package/dist/processor/services/messagebrokers/kafka.service.js +0 -45
  154. package/dist/processor/services/messagebrokers/kafka.service.js.map +0 -1
  155. package/dist/processor/services/messagebrokers/messagebrokers.type.d.ts +0 -6
  156. package/dist/processor/services/messagebrokers/messagebrokers.type.js +0 -3
  157. package/dist/processor/services/messagebrokers/messagebrokers.type.js.map +0 -1
  158. package/dist/processor/services/messagebrokers/rabbitmq.service.d.ts +0 -14
  159. package/dist/processor/services/messagebrokers/rabbitmq.service.js +0 -67
  160. package/dist/processor/services/messagebrokers/rabbitmq.service.js.map +0 -1
  161. package/dist/processor/services/messagebrokers/redis.service.d.ts +0 -18
  162. package/dist/processor/services/messagebrokers/redis.service.js +0 -82
  163. package/dist/processor/services/messagebrokers/redis.service.js.map +0 -1
  164. package/dist/processor/services/quota.service.d.ts +0 -15
  165. package/dist/processor/services/quota.service.js +0 -63
  166. package/dist/processor/services/quota.service.js.map +0 -1
  167. package/dist/test/index.d.ts +0 -3
  168. package/dist/test/index.js +0 -11
  169. package/dist/test/index.js.map +0 -1
  170. package/dist/test/test.appBuilder.d.ts +0 -0
  171. package/dist/test/test.appBuilder.js +0 -1
  172. package/dist/test/test.appBuilder.js.map +0 -1
  173. package/dist/test/test.broker.kafka.d.ts +0 -1
  174. package/dist/test/test.broker.kafka.js +0 -172
  175. package/dist/test/test.broker.kafka.js.map +0 -1
  176. package/dist/test/test.broker.nats.d.ts +0 -1
  177. package/dist/test/test.broker.nats.js +0 -193
  178. package/dist/test/test.broker.nats.js.map +0 -1
  179. package/dist/test/test.broker.pubsub.d.ts +0 -1
  180. package/dist/test/test.broker.pubsub.js +0 -171
  181. package/dist/test/test.broker.pubsub.js.map +0 -1
  182. package/dist/test/test.broker.rabbitmq.d.ts +0 -1
  183. package/dist/test/test.broker.rabbitmq.js +0 -164
  184. package/dist/test/test.broker.rabbitmq.js.map +0 -1
  185. package/dist/test/test.broker.redis.d.ts +0 -1
  186. package/dist/test/test.broker.redis.js +0 -168
  187. package/dist/test/test.broker.redis.js.map +0 -1
  188. package/dist/test/test.broker.sqs.d.ts +0 -1
  189. package/dist/test/test.broker.sqs.js +0 -158
  190. package/dist/test/test.broker.sqs.js.map +0 -1
  191. package/dist/test/test.caches.d.ts +0 -1
  192. package/dist/test/test.caches.js +0 -231
  193. package/dist/test/test.caches.js.map +0 -1
  194. package/dist/test/test.database.d.ts +0 -1
  195. package/dist/test/test.database.dynamo.d.ts +0 -1
  196. package/dist/test/test.database.dynamo.js +0 -265
  197. package/dist/test/test.database.dynamo.js.map +0 -1
  198. package/dist/test/test.database.js +0 -140
  199. package/dist/test/test.database.js.map +0 -1
  200. package/dist/test/test.database.mongo.d.ts +0 -1
  201. package/dist/test/test.database.mongo.js +0 -371
  202. package/dist/test/test.database.mongo.js.map +0 -1
  203. package/dist/test/test.database.mysql.d.ts +0 -1
  204. package/dist/test/test.database.mysql.js +0 -415
  205. package/dist/test/test.database.mysql.js.map +0 -1
  206. package/dist/test/test.database.postgres.d.ts +0 -1
  207. package/dist/test/test.database.postgres.js +0 -412
  208. package/dist/test/test.database.postgres.js.map +0 -1
  209. package/dist/test/test.email.brevo.d.ts +0 -1
  210. package/dist/test/test.email.brevo.js +0 -326
  211. package/dist/test/test.email.brevo.js.map +0 -1
  212. package/dist/test/test.email.mailgun.d.ts +0 -1
  213. package/dist/test/test.email.mailgun.js +0 -352
  214. package/dist/test/test.email.mailgun.js.map +0 -1
  215. package/dist/test/test.email.postmark.d.ts +0 -1
  216. package/dist/test/test.email.postmark.js +0 -316
  217. package/dist/test/test.email.postmark.js.map +0 -1
  218. package/dist/test/test.email.sendgrid.d.ts +0 -1
  219. package/dist/test/test.email.sendgrid.js +0 -365
  220. package/dist/test/test.email.sendgrid.js.map +0 -1
  221. package/dist/test/test.email.smtp.d.ts +0 -1
  222. package/dist/test/test.email.smtp.js +0 -323
  223. package/dist/test/test.email.smtp.js.map +0 -1
  224. package/dist/test/test.graph.arangodb.d.ts +0 -1
  225. package/dist/test/test.graph.arangodb.js +0 -358
  226. package/dist/test/test.graph.arangodb.js.map +0 -1
  227. package/dist/test/test.graph.memgraph.d.ts +0 -1
  228. package/dist/test/test.graph.memgraph.js +0 -320
  229. package/dist/test/test.graph.memgraph.js.map +0 -1
  230. package/dist/test/test.graph.neo4j.d.ts +0 -1
  231. package/dist/test/test.graph.neo4j.js +0 -218
  232. package/dist/test/test.graph.neo4j.js.map +0 -1
  233. package/dist/test/test.graph.neptune.d.ts +0 -1
  234. package/dist/test/test.graph.neptune.js +0 -331
  235. package/dist/test/test.graph.neptune.js.map +0 -1
  236. package/dist/test/test.health.d.ts +0 -0
  237. package/dist/test/test.health.js +0 -1
  238. package/dist/test/test.health.js.map +0 -1
  239. package/dist/test/test.import.d.ts +0 -0
  240. package/dist/test/test.import.js +0 -1
  241. package/dist/test/test.import.js.map +0 -1
  242. package/dist/test/test.import.openapi.d.ts +0 -0
  243. package/dist/test/test.import.openapi.js +0 -1
  244. package/dist/test/test.import.openapi.js.map +0 -1
  245. package/dist/test/test.imports.d.ts +0 -1
  246. package/dist/test/test.imports.js +0 -21
  247. package/dist/test/test.imports.js.map +0 -1
  248. package/dist/test/test.logs.d.ts +0 -0
  249. package/dist/test/test.logs.js +0 -1
  250. package/dist/test/test.logs.js.map +0 -1
  251. package/dist/test/test.notifications.d.ts +0 -1
  252. package/dist/test/test.notifications.js +0 -198
  253. package/dist/test/test.notifications.js.map +0 -1
  254. package/dist/test/test.notifiers.d.ts +0 -0
  255. package/dist/test/test.notifiers.js +0 -1
  256. package/dist/test/test.notifiers.js.map +0 -1
  257. package/dist/test/test.processor.d.ts +0 -0
  258. package/dist/test/test.processor.js +0 -1
  259. package/dist/test/test.processor.js.map +0 -1
  260. package/dist/test/test.productBuilder.d.ts +0 -0
  261. package/dist/test/test.productBuilder.js +0 -1
  262. package/dist/test/test.productBuilder.js.map +0 -1
  263. package/dist/test/test.products.d.ts +0 -0
  264. package/dist/test/test.products.js +0 -1
  265. package/dist/test/test.products.js.map +0 -1
  266. package/dist/test/test.push.expo.d.ts +0 -1
  267. package/dist/test/test.push.expo.js +0 -442
  268. package/dist/test/test.push.expo.js.map +0 -1
  269. package/dist/test/test.push.firebase.d.ts +0 -1
  270. package/dist/test/test.push.firebase.js +0 -409
  271. package/dist/test/test.push.firebase.js.map +0 -1
  272. package/dist/test/test.session.d.ts +0 -1
  273. package/dist/test/test.session.js +0 -299
  274. package/dist/test/test.session.js.map +0 -1
  275. package/dist/test/test.sms.nexmo.d.ts +0 -1
  276. package/dist/test/test.sms.nexmo.js +0 -278
  277. package/dist/test/test.sms.nexmo.js.map +0 -1
  278. package/dist/test/test.sms.twilio.d.ts +0 -1
  279. package/dist/test/test.sms.twilio.js +0 -275
  280. package/dist/test/test.sms.twilio.js.map +0 -1
  281. package/dist/test/test.storage.d.ts +0 -1
  282. package/dist/test/test.storage.js +0 -202
  283. package/dist/test/test.storage.js.map +0 -1
  284. package/dist/test/test.triggers.d.ts +0 -1
  285. package/dist/test/test.triggers.js +0 -314
  286. package/dist/test/test.triggers.js.map +0 -1
  287. package/dist/test/test.vector.pinecone.d.ts +0 -1
  288. package/dist/test/test.vector.pinecone.js +0 -238
  289. package/dist/test/test.vector.pinecone.js.map +0 -1
  290. package/dist/test/test.vector.qdrant.d.ts +0 -1
  291. package/dist/test/test.vector.qdrant.js +0 -307
  292. package/dist/test/test.vector.qdrant.js.map +0 -1
  293. package/dist/test/test.vector.weaviate.d.ts +0 -1
  294. package/dist/test/test.vector.weaviate.js +0 -325
  295. package/dist/test/test.vector.weaviate.js.map +0 -1
@@ -22,6 +22,8 @@ const processorApi_service_1 = require("../api/services/processorApi.service");
22
22
  const secrets_1 = require("../secrets");
23
23
  const cache_manager_1 = require("../cache/cache.manager");
24
24
  const sessions_1 = require("../sessions");
25
+ /** Log prefix for broker operations */
26
+ const LOG_PREFIX = '[BrokersService]';
25
27
  /**
26
28
  * Error class for broker operations
27
29
  */
@@ -72,6 +74,7 @@ exports.BrokerError = BrokerError;
72
74
  */
73
75
  class BrokersService {
74
76
  constructor(config) {
77
+ var _a;
75
78
  this.logService = null;
76
79
  this.productId = '';
77
80
  this.productTag = '';
@@ -80,14 +83,195 @@ class BrokersService {
80
83
  this.cacheManager = null;
81
84
  /** Private keys per product for cache encryption */
82
85
  this.privateKeys = new Map();
86
+ /** Connection pool for broker services - keyed by broker type + config hash */
87
+ this.brokerServicePool = new Map();
88
+ /** Cache for initialized broker configs - keyed by "productTag:brokerTag:envSlug" */
89
+ this.initializedBrokerCache = new Map();
90
+ /** Cache for initialized products - keyed by productTag */
91
+ this.initializedProducts = new Set();
92
+ /** Cache for registered broker consumers - keyed by consumerTag to track which consumers have been registered */
93
+ this.registeredConsumers = new Set();
94
+ /** Local cache for cache configurations to avoid repeated API calls */
95
+ this.cacheConfigCache = new Map();
96
+ /** Dedupe "Publish to broker - success" when same event is published twice in quick succession (e.g. workflow step run twice) */
97
+ this.lastPublishSuccessLogKey = null;
98
+ this.lastPublishSuccessLogTime = 0;
99
+ // ============================================================================
100
+ // BROKER MESSAGE QUERY METHODS (for workbench with decryption)
101
+ // ============================================================================
102
+ /**
103
+ * Messages namespace for workbench broker message queries
104
+ * All methods decrypt message content before returning
105
+ */
106
+ this.messages = {
107
+ /**
108
+ * Query broker messages with filtering and pagination
109
+ * Decrypts message content before returning
110
+ */
111
+ query: async (options) => {
112
+ try {
113
+ await this.initializeProductForEvents(options.product);
114
+ const result = await this.processorApiService.queryBrokerMessages({
115
+ product_tag: options.product,
116
+ env: options.env,
117
+ broker_tag: options.brokerTag,
118
+ topic_tag: options.topicTag,
119
+ producer_tag: options.producerTag,
120
+ consumer_tag: options.consumerTag,
121
+ status: options.status,
122
+ start_date: options.startDate,
123
+ end_date: options.endDate,
124
+ page: options.page,
125
+ limit: options.limit,
126
+ }, this.getUserAccess());
127
+ // Decrypt message content for each message
128
+ const messages = result.messages.map((msg) => (Object.assign(Object.assign({}, msg), { message_decrypted: msg.message_encrypted
129
+ ? this.decryptPayload(msg.message_encrypted)
130
+ : undefined })));
131
+ return {
132
+ messages,
133
+ total: result.total,
134
+ page: result.page,
135
+ limit: result.limit,
136
+ hasMore: result.hasMore,
137
+ };
138
+ }
139
+ catch (error) {
140
+ if (error instanceof BrokerError)
141
+ throw error;
142
+ throw new BrokerError(`Failed to query broker messages: ${error}`, 'QUERY_MESSAGES_FAILED', error);
143
+ }
144
+ },
145
+ /**
146
+ * Get broker producers with pagination
147
+ */
148
+ getProducers: async (options) => {
149
+ try {
150
+ await this.initializeProductForEvents(options.product);
151
+ return await this.processorApiService.getBrokerProducers({
152
+ product_tag: options.product,
153
+ env: options.env,
154
+ broker_tag: options.brokerTag,
155
+ topic_tag: options.topicTag,
156
+ page: options.page,
157
+ limit: options.limit,
158
+ }, this.getUserAccess());
159
+ }
160
+ catch (error) {
161
+ if (error instanceof BrokerError)
162
+ throw error;
163
+ throw new BrokerError(`Failed to get broker producers: ${error}`, 'GET_PRODUCERS_FAILED', error);
164
+ }
165
+ },
166
+ /**
167
+ * Get broker consumers with pagination
168
+ */
169
+ getConsumers: async (options) => {
170
+ try {
171
+ await this.initializeProductForEvents(options.product);
172
+ return await this.processorApiService.getBrokerConsumers({
173
+ product_tag: options.product,
174
+ env: options.env,
175
+ broker_tag: options.brokerTag,
176
+ topic_tag: options.topicTag,
177
+ page: options.page,
178
+ limit: options.limit,
179
+ }, this.getUserAccess());
180
+ }
181
+ catch (error) {
182
+ if (error instanceof BrokerError)
183
+ throw error;
184
+ throw new BrokerError(`Failed to get broker consumers: ${error}`, 'GET_CONSUMERS_FAILED', error);
185
+ }
186
+ },
187
+ /**
188
+ * Get broker dead letters with pagination
189
+ * Decrypts message content before returning
190
+ */
191
+ getDeadLetters: async (options) => {
192
+ try {
193
+ await this.initializeProductForEvents(options.product);
194
+ const result = await this.processorApiService.getBrokerDeadLetters({
195
+ product_tag: options.product,
196
+ env: options.env,
197
+ broker_tag: options.brokerTag,
198
+ topic_tag: options.topicTag,
199
+ consumer_tag: options.consumerTag,
200
+ start_date: options.startDate,
201
+ end_date: options.endDate,
202
+ page: options.page,
203
+ limit: options.limit,
204
+ }, this.getUserAccess());
205
+ // Decrypt message content for dead letters
206
+ const deadLetters = result.deadLetters.map((dl) => (Object.assign(Object.assign({}, dl), { original_message: dl.original_message ? Object.assign(Object.assign({}, dl.original_message), { message_decrypted: dl.original_message.message_encrypted
207
+ ? this.decryptPayload(dl.original_message.message_encrypted)
208
+ : undefined }) : dl.original_message })));
209
+ return {
210
+ deadLetters,
211
+ total: result.total,
212
+ page: result.page,
213
+ limit: result.limit,
214
+ hasMore: result.hasMore,
215
+ };
216
+ }
217
+ catch (error) {
218
+ if (error instanceof BrokerError)
219
+ throw error;
220
+ throw new BrokerError(`Failed to get broker dead letters: ${error}`, 'GET_DEAD_LETTERS_FAILED', error);
221
+ }
222
+ },
223
+ /**
224
+ * Get comprehensive broker message statistics
225
+ */
226
+ getStats: async (options) => {
227
+ try {
228
+ await this.initializeProductForEvents(options.product);
229
+ return await this.processorApiService.getBrokerComprehensiveStats({
230
+ product_tag: options.product,
231
+ env: options.env,
232
+ broker_tag: options.brokerTag,
233
+ }, this.getUserAccess());
234
+ }
235
+ catch (error) {
236
+ if (error instanceof BrokerError)
237
+ throw error;
238
+ throw new BrokerError(`Failed to get broker stats: ${error}`, 'GET_STATS_FAILED', error);
239
+ }
240
+ },
241
+ /**
242
+ * Get broker dashboard overview data
243
+ * Decrypts message content for recent messages
244
+ */
245
+ getDashboard: async (options) => {
246
+ try {
247
+ await this.initializeProductForEvents(options.product);
248
+ const result = await this.processorApiService.getBrokerDashboard({
249
+ product_tag: options.product,
250
+ env: options.env,
251
+ broker_tag: options.brokerTag,
252
+ }, this.getUserAccess());
253
+ // Decrypt recent messages
254
+ const recentMessages = (result.recent_messages || []).map((msg) => (Object.assign(Object.assign({}, msg), { message_decrypted: msg.message_encrypted
255
+ ? this.decryptPayload(msg.message_encrypted)
256
+ : undefined })));
257
+ return Object.assign(Object.assign({}, result), { recent_messages: recentMessages });
258
+ }
259
+ catch (error) {
260
+ if (error instanceof BrokerError)
261
+ throw error;
262
+ throw new BrokerError(`Failed to get broker dashboard: ${error}`, 'GET_DASHBOARD_FAILED', error);
263
+ }
264
+ },
265
+ };
83
266
  this.config = config;
84
- this.productBuilderService = new products_service_1.default({
267
+ this.productBuilderService = (_a = config.preInitializedProductBuilder) !== null && _a !== void 0 ? _a : new products_service_1.default({
85
268
  workspace_id: config.workspace_id,
86
269
  public_key: config.public_key,
87
270
  user_id: config.user_id,
88
271
  token: config.token,
89
272
  env_type: config.env_type,
90
273
  redis_client: config.redis_client,
274
+ access_key: config.access_key,
91
275
  });
92
276
  this.processorApiService = new processorApi_service_1.ProcessorApiService(config.env_type);
93
277
  // Initialize CacheManager if Redis client is provided
@@ -111,16 +295,40 @@ class BrokersService {
111
295
  token: this.config.token,
112
296
  workspace_id: this.config.workspace_id,
113
297
  public_key: this.config.public_key,
298
+ access_key: this.config.access_key,
114
299
  };
115
300
  }
116
301
  /**
117
- * Initialize product and get broker configuration
302
+ * Initialize product and get broker configuration (with caching)
118
303
  */
119
- async initializeBroker(productTag, envSlug, event) {
304
+ async initializeBroker(productTag, envSlug, event, message) {
305
+ var _a, _b;
120
306
  // Parse event to get broker and topic tags
121
307
  const { brokerTag, topicTag } = (0, broker_util_1.parseEventString)(event);
122
- // Initialize product
123
- await this.productBuilderService.initializeProductByTag(productTag);
308
+ // Check cache first (keyed by product:broker:env)
309
+ const cacheKey = `${productTag}:${brokerTag}:${envSlug}`;
310
+ const cached = this.initializedBrokerCache.get(cacheKey);
311
+ if (cached) {
312
+ // For cached brokers, just check if topic exists (might be new topic)
313
+ let topic = (_a = cached.broker.topics) === null || _a === void 0 ? void 0 : _a.find(t => t.tag === topicTag);
314
+ if (!topic) {
315
+ if (message) {
316
+ this.ensureTopicRegistered(brokerTag, topicTag, message);
317
+ }
318
+ topic = { tag: topicTag, name: topicTag, sample: message || {} };
319
+ }
320
+ // Determine topic URL
321
+ let topicUrl = topic.name;
322
+ if (cached.brokerEnv.type === types_1.MessageBrokerTypes.AWS_SQS) {
323
+ topicUrl = (0, broker_util_1.getSqsQueueUrl)(topic, envSlug);
324
+ }
325
+ return Object.assign(Object.assign({}, cached), { topic, topicUrl });
326
+ }
327
+ // Initialize product only if not already done
328
+ if (!this.initializedProducts.has(productTag)) {
329
+ await this.productBuilderService.initializeProductByTag(productTag);
330
+ this.initializedProducts.add(productTag);
331
+ }
124
332
  this.productTag = productTag;
125
333
  this.productId = this.productBuilderService.fetchProductId() || '';
126
334
  this.privateKey = this.productBuilderService.fetchPrivateKey();
@@ -129,15 +337,21 @@ class BrokersService {
129
337
  if (!broker) {
130
338
  throw new BrokerError(`Message Broker ${brokerTag} not found`, 'BROKER_NOT_FOUND');
131
339
  }
340
+ if (!broker.envs || !Array.isArray(broker.envs)) {
341
+ throw new BrokerError(`Message Broker ${brokerTag} has no environments configured`, 'BROKER_NO_ENVS');
342
+ }
132
343
  // Get environment-specific broker config
133
344
  const brokerEnv = broker.envs.find((el) => el.slug === envSlug);
134
345
  if (!brokerEnv) {
135
346
  throw new BrokerError(`Broker environment for ${envSlug} not found`, 'BROKER_ENV_NOT_FOUND');
136
347
  }
137
- // Fetch topic configuration
138
- const topic = await this.productBuilderService.fetchMessageBrokerTopic(event);
348
+ // Check if topic exists in broker's topics array
349
+ let topic = (_b = broker.topics) === null || _b === void 0 ? void 0 : _b.find(t => t.tag === topicTag);
139
350
  if (!topic) {
140
- throw new BrokerError(`Topic ${topicTag} not found in broker ${brokerTag}`, 'TOPIC_NOT_FOUND');
351
+ if (message) {
352
+ this.ensureTopicRegistered(brokerTag, topicTag, message);
353
+ }
354
+ topic = { tag: topicTag, name: topicTag, sample: message || {} };
141
355
  }
142
356
  // Resolve any secret references in broker config
143
357
  let resolvedConfig = brokerEnv.config;
@@ -148,18 +362,23 @@ class BrokersService {
148
362
  resolvedConfig = resolved.value;
149
363
  }
150
364
  else {
151
- throw new BrokerError(`Broker configuration contains secret references but secrets service is not initialized. ` +
152
- `Please ensure the Ductape client is properly initialized.`, 'SECRETS_NOT_INITIALIZED');
365
+ throw new BrokerError(`Broker configuration contains secret references but secrets service is not initialized.`, 'SECRETS_NOT_INITIALIZED');
153
366
  }
154
367
  }
155
- // Create a new brokerEnv object with resolved config
368
+ // Create resolved broker env
156
369
  const resolvedBrokerEnv = Object.assign(Object.assign({}, brokerEnv), { config: resolvedConfig });
157
370
  // Determine the topic URL/name
158
371
  let topicUrl = topic.name;
159
- // Special handling for AWS SQS which requires queue URLs
160
372
  if (brokerEnv.type === types_1.MessageBrokerTypes.AWS_SQS) {
161
373
  topicUrl = (0, broker_util_1.getSqsQueueUrl)(topic, envSlug);
162
374
  }
375
+ // Cache the result (without topic, as topics may vary per call)
376
+ this.initializedBrokerCache.set(cacheKey, {
377
+ broker,
378
+ topic, // Store last topic, but will be re-evaluated on cache hit
379
+ brokerEnv: resolvedBrokerEnv,
380
+ topicUrl,
381
+ });
163
382
  return { broker, topic, brokerEnv: resolvedBrokerEnv, topicUrl };
164
383
  }
165
384
  /**
@@ -179,26 +398,109 @@ class BrokersService {
179
398
  }
180
399
  /**
181
400
  * Validate cache tag exists in product and return cache configuration
401
+ * Uses local in-memory cache to avoid repeated API calls (5 minute TTL)
182
402
  */
183
403
  async validateCache(cacheTag) {
404
+ const cacheKey = `${this.productTag}:${cacheTag}`;
405
+ const cached = this.cacheConfigCache.get(cacheKey);
406
+ const now = Date.now();
407
+ const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
408
+ // Return cached config if still valid
409
+ if (cached && (now - cached.fetchedAt) < CACHE_TTL) {
410
+ return { expiry: cached.expiry };
411
+ }
412
+ // Fetch from API and cache the result
184
413
  const cache = await this.productBuilderService.fetchCache(cacheTag);
185
414
  if (!cache) {
186
415
  throw new BrokerError(`Cache configuration '${cacheTag}' does not exist`, 'CACHE_NOT_FOUND');
187
416
  }
417
+ this.cacheConfigCache.set(cacheKey, { expiry: cache.expiry, fetchedAt: now });
188
418
  return { expiry: cache.expiry };
189
419
  }
190
420
  /**
191
- * Get or create broker service instance
421
+ * Generate a cache key for the broker service pool
422
+ */
423
+ getBrokerPoolKey(type, config) {
424
+ var _a;
425
+ // Use type + url/host as the key (url for RabbitMQ, host for others)
426
+ const configKey = (config === null || config === void 0 ? void 0 : config.url) || (config === null || config === void 0 ? void 0 : config.host) || ((_a = config === null || config === void 0 ? void 0 : config.brokers) === null || _a === void 0 ? void 0 : _a[0]) || JSON.stringify(config);
427
+ return `${type}:${configKey}`;
428
+ }
429
+ /**
430
+ * Get or create broker service instance (with connection pooling)
192
431
  */
193
432
  async getBrokerService(type, config) {
194
433
  if ((0, broker_util_1.isBrowser)()) {
195
434
  throw new BrokerError('Broker operations are not supported in browser environment', 'BROWSER_NOT_SUPPORTED');
196
435
  }
436
+ // Check if we have a cached connection
437
+ const poolKey = this.getBrokerPoolKey(type, config);
438
+ const existingService = this.brokerServicePool.get(poolKey);
439
+ if (existingService) {
440
+ return existingService;
441
+ }
197
442
  const createBrokerService = await (0, broker_util_1.loadBrokerService)();
198
443
  if (!createBrokerService) {
199
444
  throw new BrokerError('Failed to load broker service', 'BROKER_SERVICE_LOAD_FAILED');
200
445
  }
201
- return createBrokerService(type, config);
446
+ const service = createBrokerService(type, config);
447
+ // Store in pool for reuse
448
+ this.brokerServicePool.set(poolKey, service);
449
+ return service;
450
+ }
451
+ /**
452
+ * Disconnect all pooled broker connections (e.g. at end of workflow run). Safe if pool is empty.
453
+ */
454
+ async disconnectAll() {
455
+ for (const service of this.brokerServicePool.values()) {
456
+ try {
457
+ if (typeof service.disconnect === 'function') {
458
+ await service.disconnect();
459
+ }
460
+ }
461
+ catch (_a) {
462
+ // Non-fatal
463
+ }
464
+ }
465
+ this.brokerServicePool.clear();
466
+ }
467
+ /**
468
+ * Pre-warm broker connections for the given product/env and broker tags.
469
+ * Call before step execution so the first produce step reuses connections. Same auth and secrets as publish.
470
+ */
471
+ async warmBrokerConnections(options) {
472
+ const { product, env, brokerTags } = options;
473
+ if (brokerTags.length === 0)
474
+ return;
475
+ for (const brokerTag of brokerTags) {
476
+ try {
477
+ const { brokerEnv } = await this.initializeBroker(product, env, `${brokerTag}:_warm`, {});
478
+ const service = await this.getBrokerService(brokerEnv.type, brokerEnv.config);
479
+ if (typeof service.connect === 'function')
480
+ await service.connect();
481
+ }
482
+ catch (_a) {
483
+ // Non-fatal: step will connect on first use
484
+ }
485
+ }
486
+ }
487
+ /**
488
+ * Auto-register a topic in the background (fire-and-forget)
489
+ * This is intentionally lightweight - no pre-check, no post-fetch
490
+ */
491
+ ensureTopicRegistered(brokerTag, topicTag, message) {
492
+ const fullTag = `${brokerTag}:${topicTag}`;
493
+ // Fire-and-forget: don't await, let it run in background
494
+ this.productBuilderService.createMessageBrokerTopic({
495
+ tag: fullTag,
496
+ name: topicTag,
497
+ description: `Auto-registered topic for ${fullTag}`,
498
+ sample: JSON.stringify(message || {}),
499
+ idempotent: false,
500
+ }).catch(() => {
501
+ // Silently ignore - topic might already exist or registration failed
502
+ // Either way, the publish should proceed
503
+ });
202
504
  }
203
505
  /**
204
506
  * Auto-register a producer if it doesn't exist
@@ -244,15 +546,16 @@ class BrokersService {
244
546
  * Publish a message to a broker topic
245
547
  */
246
548
  async publish(options) {
247
- var _a, _b;
549
+ var _a, _b, _c, _d;
248
550
  const process_id = (0, processor_utils_1.generateObjectId)();
249
551
  const start = Date.now();
250
552
  const { cache } = options;
251
553
  let sessionLogFields = {};
252
554
  let resolvedMessage = options.message;
555
+ // Parse event string early to have broker/topic tags available for error logging
556
+ const { brokerTag, topicTag } = (0, broker_util_1.parseEventString)(options.event);
253
557
  try {
254
- const { broker, topic, brokerEnv, topicUrl } = await this.initializeBroker(options.product, options.env, options.event);
255
- const { brokerTag, topicTag } = (0, broker_util_1.parseEventString)(options.event);
558
+ const { broker, topic, brokerEnv, topicUrl } = await this.initializeBroker(options.product, options.env, options.event, options.message);
256
559
  // Store private key for cache operations
257
560
  if (this.privateKey) {
258
561
  this.privateKeys.set(options.product, this.privateKey);
@@ -261,7 +564,12 @@ class BrokersService {
261
564
  if (options.session && this.privateKey) {
262
565
  // Convert session object { tag, token } to string format "tag:token"
263
566
  const sessionToken = `${options.session.tag}:${options.session.token}`;
264
- const sessionResult = await (0, sessions_1.processSessionForExecution)(sessionToken, this.privateKey, { message: options.message }, options.env);
567
+ const sessionResult = await (0, sessions_1.processSessionForExecution)(sessionToken, this.privateKey, { message: options.message }, options.env, {
568
+ fetchSessionSelector: async (sessionTag) => {
569
+ const sessionConfig = await this.productBuilderService.fetchSession(sessionTag);
570
+ return sessionConfig === null || sessionConfig === void 0 ? void 0 : sessionConfig.selector;
571
+ },
572
+ });
265
573
  if (sessionResult.error) {
266
574
  throw new BrokerError(`Session validation failed: ${sessionResult.error}`, 'SESSION_INVALID');
267
575
  }
@@ -271,7 +579,7 @@ class BrokersService {
271
579
  // Auto-register producer if not exists
272
580
  await this.ensureProducerRegistered(brokerTag, topicTag, options.producer);
273
581
  this.initializeLogService();
274
- const baseLogs = Object.assign({ product_tag: options.product, product_id: this.productId, workspace_id: this.config.workspace_id, env: options.env, process_id, type: types_2.LogEventTypes.MESSAGEBROKER, parent_tag: brokerTag, child_tag: topicTag, data: { event: options.event } }, sessionLogFields);
582
+ const baseLogs = Object.assign({ product_tag: options.product, product_id: this.productId, workspace_id: this.config.workspace_id, env: options.env, process_id, type: types_2.LogEventTypes.PRODUCER, parent_tag: brokerTag, child_tag: topicTag, data: { event: options.event } }, sessionLogFields);
275
583
  this.logService.add(Object.assign(Object.assign({}, baseLogs), { start, message: 'Publish to broker - initiated', status: types_2.LogEventStatus.PROCESSING }));
276
584
  // Check cache for idempotency (prevent duplicate publishes with same data)
277
585
  if (cache && this.cacheManager && this.privateKey) {
@@ -290,22 +598,47 @@ class BrokersService {
290
598
  if (cached.hit && cached.data) {
291
599
  const end = Date.now();
292
600
  this.logService.add(Object.assign(Object.assign({}, baseLogs), { start,
293
- end, message: `Publish to broker - cache hit (${cached.source})`, successful_execution: true, status: types_2.LogEventStatus.SUCCESS, data: { event: options.event, cache_source: cached.source } }));
601
+ end, message: `Publish to broker - cache hit (${cached.source})`, successful_execution: true, status: types_2.LogEventStatus.SUCCESS, data: { event: options.event, cache_source: cached.source }, cache_tag: cache, cache_key: cached.key, cache_status: true }));
294
602
  this.logService.publish();
295
603
  return cached.data;
296
604
  }
297
605
  }
606
+ // Generate message_id client-side and track asynchronously (fire-and-forget)
607
+ const producerTag = ((_a = options.producer) === null || _a === void 0 ? void 0 : _a.tag) || `producer-${brokerTag}-${topicTag}`;
608
+ const messageId = (0, processor_utils_1.generateObjectId)();
609
+ // Encrypt message on SDK side - NEVER send private_key over HTTP
610
+ const messageEncrypted = (0, processor_utils_1.encrypt)(JSON.stringify(resolvedMessage), this.privateKey);
611
+ // Track the message in the database (fire-and-forget - no await)
612
+ this.processorApiService.trackBrokerMessage({
613
+ workspace_id: this.config.workspace_id,
614
+ product_id: this.productId,
615
+ product_tag: options.product,
616
+ env: options.env,
617
+ broker_tag: brokerTag,
618
+ topic_tag: topicTag,
619
+ event: options.event,
620
+ producer_tag: producerTag,
621
+ message_encrypted: messageEncrypted,
622
+ process_id,
623
+ session_tag: (_b = options.session) === null || _b === void 0 ? void 0 : _b.tag,
624
+ metadata: { cache: options.cache },
625
+ message_id: messageId,
626
+ }, this.getUserAccess()).catch(() => {
627
+ // Silently ignore tracking errors - non-blocking
628
+ });
629
+ // Add the message_id to the message so consumers can track it
630
+ const messageWithTracking = Object.assign(Object.assign({}, resolvedMessage), { __ductape_message_id: messageId });
298
631
  // Get broker service and publish
299
632
  const brokerService = await this.getBrokerService(brokerEnv.type, brokerEnv.config);
300
- await brokerService.publish(topicUrl, resolvedMessage);
633
+ await brokerService.publish(topicUrl, messageWithTracking);
301
634
  const result = {
302
635
  success: true,
303
636
  process_id,
304
637
  };
305
- // Store in cache for idempotency
638
+ // Store in cache for idempotency (fire-and-forget)
306
639
  if (cache && this.cacheManager && this.privateKey) {
307
640
  const cacheConfig = await this.validateCache(cache);
308
- await this.cacheManager.store({
641
+ this.cacheManager.store({
309
642
  cache_tag: cache,
310
643
  product_tag: options.product,
311
644
  component_tag: `${brokerTag}:${topicTag}`,
@@ -317,18 +650,26 @@ class BrokersService {
317
650
  }, result);
318
651
  }
319
652
  const end = Date.now();
320
- this.logService.add(Object.assign(Object.assign({}, baseLogs), { start,
321
- end, message: 'Publish to broker - success', successful_execution: true, status: types_2.LogEventStatus.SUCCESS }));
653
+ const successLogKey = `${options.product}:${options.env}:${options.event}`;
654
+ const now = Date.now();
655
+ const isDuplicateSuccessLog = this.lastPublishSuccessLogKey === successLogKey &&
656
+ now - this.lastPublishSuccessLogTime < BrokersService.PUBLISH_SUCCESS_LOG_DEDUPE_MS;
657
+ if (!isDuplicateSuccessLog) {
658
+ this.logService.add(Object.assign(Object.assign({}, baseLogs), { start,
659
+ end, message: 'Publish to broker - success', successful_execution: true, status: types_2.LogEventStatus.SUCCESS }));
660
+ this.lastPublishSuccessLogKey = successLogKey;
661
+ this.lastPublishSuccessLogTime = now;
662
+ }
322
663
  this.logService.publish();
323
664
  return result;
324
665
  }
325
666
  catch (error) {
326
667
  const end = Date.now();
327
668
  this.initializeLogService();
328
- (_a = this.logService) === null || _a === void 0 ? void 0 : _a.add(Object.assign({ product_tag: options.product, workspace_id: this.config.workspace_id, env: options.env, process_id,
669
+ (_c = this.logService) === null || _c === void 0 ? void 0 : _c.add(Object.assign({ product_tag: options.product, workspace_id: this.config.workspace_id, env: options.env, process_id,
329
670
  start,
330
- end, type: types_2.LogEventTypes.MESSAGEBROKER, message: 'Publish to broker - failed', failed_execution: true, data: { event: options.event, error: String(error) }, status: types_2.LogEventStatus.FAIL }, sessionLogFields));
331
- await ((_b = this.logService) === null || _b === void 0 ? void 0 : _b.publish());
671
+ end, type: types_2.LogEventTypes.PRODUCER, parent_tag: brokerTag, child_tag: topicTag, message: 'Publish to broker - failed', failed_execution: true, data: { event: options.event, error: String(error) }, status: types_2.LogEventStatus.FAIL }, sessionLogFields));
672
+ await ((_d = this.logService) === null || _d === void 0 ? void 0 : _d.publish());
332
673
  if (error instanceof BrokerError) {
333
674
  throw error;
334
675
  }
@@ -339,11 +680,12 @@ class BrokersService {
339
680
  * Subscribe to a broker topic
340
681
  */
341
682
  async subscribe(options) {
342
- var _a, _b;
683
+ var _a, _b, _c;
343
684
  const process_id = (0, processor_utils_1.generateObjectId)();
344
685
  const start = Date.now();
345
686
  try {
346
- const { broker, topic, brokerEnv, topicUrl } = await this.initializeBroker(options.product, options.env, options.event);
687
+ // For subscribe, we don't auto-register topics - they should already exist
688
+ const { broker, topic, brokerEnv, topicUrl } = await this.initializeBroker(options.product, options.env, options.event, undefined);
347
689
  const { brokerTag, topicTag } = (0, broker_util_1.parseEventString)(options.event);
348
690
  // Auto-register consumer if not exists
349
691
  await this.ensureConsumerRegistered(brokerTag, topicTag, options.consumer);
@@ -354,15 +696,80 @@ class BrokersService {
354
696
  workspace_id: this.config.workspace_id,
355
697
  env: options.env,
356
698
  process_id,
357
- type: types_2.LogEventTypes.MESSAGEBROKER,
699
+ type: types_2.LogEventTypes.CONSUMER,
358
700
  parent_tag: brokerTag,
359
701
  child_tag: topicTag,
360
702
  data: { event: options.event },
361
703
  };
362
704
  this.logService.add(Object.assign(Object.assign({}, baseLogs), { start, message: 'Subscribe to broker - initiated', status: types_2.LogEventStatus.PROCESSING }));
363
- // Get broker service and subscribe
705
+ // Get broker service and subscribe with message tracking wrapper
364
706
  const brokerService = await this.getBrokerService(brokerEnv.type, brokerEnv.config);
365
- await brokerService.subscribe(topicUrl, options.callback);
707
+ const consumerTag = ((_a = options.consumer) === null || _a === void 0 ? void 0 : _a.tag) || `consumer-${brokerTag}-${topicTag}`;
708
+ // Pre-cache user access for callback use (avoid repeated calls)
709
+ const userAccess = this.getUserAccess();
710
+ // Wrap the callback to track message consumption (optimized for low latency)
711
+ const wrappedCallback = async (message) => {
712
+ const messageReceiveTime = Date.now();
713
+ const consumeProcessId = (0, processor_utils_1.generateObjectId)();
714
+ // Extract message_id from the message
715
+ const msgWithId = message;
716
+ const messageId = msgWithId.__ductape_message_id;
717
+ // Execute user callback FIRST - this is the critical path
718
+ let callbackSuccess = true;
719
+ let callbackError;
720
+ try {
721
+ await options.callback(message);
722
+ }
723
+ catch (err) {
724
+ callbackSuccess = false;
725
+ callbackError = err;
726
+ }
727
+ const callbackEnd = Date.now();
728
+ // Fire-and-forget: All tracking/logging happens async after callback completes
729
+ // This ensures user callback latency is not affected by our tracking overhead
730
+ setImmediate(() => {
731
+ var _a, _b;
732
+ const consumeBaseLogs = {
733
+ product_tag: options.product,
734
+ product_id: this.productId,
735
+ workspace_id: this.config.workspace_id,
736
+ env: options.env,
737
+ process_id: consumeProcessId,
738
+ type: types_2.LogEventTypes.CONSUMER,
739
+ parent_tag: brokerTag,
740
+ child_tag: topicTag,
741
+ data: { event: options.event, message_id: messageId, consumer_tag: consumerTag },
742
+ };
743
+ if (messageId) {
744
+ // Calculate actual callback processing time
745
+ const processingTime = callbackEnd - messageReceiveTime;
746
+ // Register consumer first, then update status (sequential to avoid race condition)
747
+ this.processorApiService.registerBrokerConsumer({
748
+ message_id: messageId,
749
+ consumer_tag: consumerTag,
750
+ }, userAccess).then(() => {
751
+ // Now update the status with processing time
752
+ return this.processorApiService.updateBrokerConsumerStatus({
753
+ message_id: messageId,
754
+ consumer_tag: consumerTag,
755
+ status: callbackSuccess ? 'success' : 'failed',
756
+ error: callbackError ? String(callbackError) : undefined,
757
+ processing_time: processingTime,
758
+ }, userAccess);
759
+ }).catch(() => { }); // Silently ignore tracking errors
760
+ }
761
+ // Log consumption (fire-and-forget)
762
+ (_a = this.logService) === null || _a === void 0 ? void 0 : _a.add(Object.assign(Object.assign(Object.assign({}, consumeBaseLogs), { start: messageReceiveTime, end: callbackEnd, message: messageId
763
+ ? (callbackSuccess ? 'Message consumed - success' : 'Message consumed - failed')
764
+ : 'Message consumed - untracked (no message_id)', successful_execution: callbackSuccess, failed_execution: !callbackSuccess, status: callbackSuccess ? types_2.LogEventStatus.SUCCESS : types_2.LogEventStatus.FAIL }), (callbackError && { data: Object.assign(Object.assign({}, consumeBaseLogs.data), { error: String(callbackError) }) })));
765
+ (_b = this.logService) === null || _b === void 0 ? void 0 : _b.publish();
766
+ });
767
+ // Re-throw callback error if any (so RabbitMQ can handle retry/nack)
768
+ if (callbackError) {
769
+ throw callbackError;
770
+ }
771
+ };
772
+ await brokerService.subscribe(topicUrl, wrappedCallback);
366
773
  const end = Date.now();
367
774
  this.logService.add(Object.assign(Object.assign({}, baseLogs), { start,
368
775
  end, message: 'Subscribe to broker - success', successful_execution: true, status: types_2.LogEventStatus.SUCCESS }));
@@ -375,20 +782,20 @@ class BrokersService {
375
782
  catch (error) {
376
783
  const end = Date.now();
377
784
  this.initializeLogService();
378
- (_a = this.logService) === null || _a === void 0 ? void 0 : _a.add({
785
+ (_b = this.logService) === null || _b === void 0 ? void 0 : _b.add({
379
786
  product_tag: options.product,
380
787
  workspace_id: this.config.workspace_id,
381
788
  env: options.env,
382
789
  process_id,
383
790
  start,
384
791
  end,
385
- type: types_2.LogEventTypes.MESSAGEBROKER,
792
+ type: types_2.LogEventTypes.CONSUMER,
386
793
  message: 'Subscribe to broker - failed',
387
794
  failed_execution: true,
388
795
  data: { event: options.event, error: String(error) },
389
796
  status: types_2.LogEventStatus.FAIL,
390
797
  });
391
- await ((_b = this.logService) === null || _b === void 0 ? void 0 : _b.publish());
798
+ await ((_c = this.logService) === null || _c === void 0 ? void 0 : _c.publish());
392
799
  if (error instanceof BrokerError) {
393
800
  throw error;
394
801
  }
@@ -793,5 +1200,6 @@ class BrokersService {
793
1200
  }
794
1201
  }
795
1202
  exports.BrokersService = BrokersService;
1203
+ BrokersService.PUBLISH_SUCCESS_LOG_DEDUPE_MS = 2000;
796
1204
  exports.default = BrokersService;
797
1205
  //# sourceMappingURL=brokers.service.js.map