@adobe-commerce/aio-toolkit 1.2.3 → 1.2.4

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/dist/index.d.mts CHANGED
@@ -271,6 +271,16 @@ interface AbdbRecord {
271
271
  [key: string]: unknown;
272
272
  }
273
273
  type AbdbRepositoryFilter = Record<string, unknown>;
274
+ type AbdbFindSortDirection = 'asc' | 'desc';
275
+ type AbdbFindSort = {
276
+ column: string;
277
+ direction?: AbdbFindSortDirection;
278
+ };
279
+ type AbdbFindOptions = {
280
+ current_page?: number;
281
+ page_size?: number;
282
+ sort?: AbdbFindSort;
283
+ };
274
284
 
275
285
  declare class AbdbRepository<T extends AbdbRecord = AbdbRecord> {
276
286
  private readonly _collection;
@@ -279,7 +289,7 @@ declare class AbdbRepository<T extends AbdbRecord = AbdbRecord> {
279
289
  constructor(collection: AbdbCollection, token: string, region?: string);
280
290
  getName(): string;
281
291
  getCollection(): AbdbCollection;
282
- find(filter?: AbdbRepositoryFilter): Promise<T[]>;
292
+ find(filter?: AbdbRepositoryFilter, options?: AbdbFindOptions): Promise<T[]>;
283
293
  findOne(filter: AbdbRepositoryFilter): Promise<T | null>;
284
294
  findById(id: string): Promise<T | null>;
285
295
  delete(filter?: AbdbRepositoryFilter): Promise<Record<string, any>>;
@@ -329,7 +339,7 @@ interface WebhookActionSuccessResponse {
329
339
  }
330
340
  interface WebhookActionExceptionResponse {
331
341
  op: typeof WebhookActionOperation.EXCEPTION;
332
- class?: string;
342
+ type?: string;
333
343
  message?: string;
334
344
  }
335
345
  interface WebhookActionAddResponse {
@@ -375,7 +385,7 @@ declare class WebhookAction {
375
385
 
376
386
  declare class WebhookActionResponse {
377
387
  static success(): WebhookActionSuccessResponse;
378
- static exception(message?: string, exceptionClass?: string): WebhookActionExceptionResponse;
388
+ static exception(message?: string, exceptionType?: string): WebhookActionExceptionResponse;
379
389
  static add(path: string, value: any, instance?: string): WebhookActionAddResponse;
380
390
  static replace(path: string, value: any, instance?: string): WebhookActionReplaceResponse;
381
391
  static remove(path: string): WebhookActionRemoveResponse;
@@ -1127,4 +1137,4 @@ declare class AdminUiSdk {
1127
1137
  getRegistration(): AdminUiSdkRegistration;
1128
1138
  }
1129
1139
 
1130
- export { AbdbCollection, type AbdbCollectionCallback, AbdbColumn, type AbdbColumnJson, type AbdbColumnOptions, AbdbColumnType, type AbdbRecord, AbdbRepository, type AbdbRepositoryFilter, type AbdbRunCallback, type AddColumnOptions, AdminUiSdk, type AdminUiSdkRegistration, AdobeAuth, AdobeCommerceClient, type AdobeIMSConfig, type BaseTelemetry, type BaseTelemetryValidator, BasicAuthConnection, BearerToken, type BearerTokenInfo, type CommerceEvent, type CommerceEventConfig, type CommerceEventField, type Connection, type ConsumeStats, type CreateEventResult, CreateEvents, type CreateProviderParams, type CreateProviderResult, type CreateRegistrationResult, CreateRegistrations, type ErrorResponse, EventConsumerAction, type EventData, type EventMetadata, type EventMetadataInputModel, type EventMetadataListResponse, EventMetadataManager, type ExtendedRequestError, type FileMetadata, type FileRecord, FileRepository, GenerateBasicAuthToken, type GetProviderQueryParams, type GetRegistrationQueryParams, GraphQlAction, type HALLink, type Headers, HttpMethod, HttpStatus, IOEventsApiError, type IOEventsError, ImsConnection, ImsToken, type ImsTokenResult, InfiniteLoopBreaker, type InfiniteLoopData, IoEventsGlobals, JsonMessageProcessor, type ListProvidersQueryParams, type ListRegistrationQueryParams, type MenuItem, type MessageHandler, Oauth1aConnection, OnboardCommerce, type OnboardCommerceConfig, type OnboardCommerceResult, OnboardEvents, type OnboardEventsInput, type OnboardEventsResponse, OnboardEvents as OnboardIOEvents, Openwhisk, OpenwhiskAction, type OpenwhiskConfig, type Page, Parameters, type Provider, type ProviderInputModel, ProviderManager, PublishEvent, type PublishEventResult, type PublishStats, RabbitMQClient, type RabbitMQConsumeOptions, type RabbitMQCredentials, type Registration, type RegistrationCreateModel, type RegistrationListResponse, RegistrationManager, RestClient, RuntimeAction, RuntimeActionResponse, type RuntimeActionResponseType, RuntimeApiGatewayService, ShippingCarrier, type ShippingCarrierData, ShippingCarrierMethod, type ShippingCarrierMethodAdditionalData, type ShippingCarrierMethodData, ShippingCarrierResponse, SignatureVerification, SuccessChecker, type SuccessResponse, Telemetry, TelemetryInputError, type TokenResult, Validator, WebhookAction, type WebhookActionAddResponse, type WebhookActionExceptionResponse, WebhookActionOperation, type WebhookActionRemoveResponse, type WebhookActionReplaceResponse, WebhookActionResponse, type WebhookActionResponseType, type WebhookActionSuccessResponse, type WorkspaceConfig };
1140
+ export { AbdbCollection, type AbdbCollectionCallback, AbdbColumn, type AbdbColumnJson, type AbdbColumnOptions, AbdbColumnType, type AbdbFindOptions, type AbdbFindSort, type AbdbFindSortDirection, type AbdbRecord, AbdbRepository, type AbdbRepositoryFilter, type AbdbRunCallback, type AddColumnOptions, AdminUiSdk, type AdminUiSdkRegistration, AdobeAuth, AdobeCommerceClient, type AdobeIMSConfig, type BaseTelemetry, type BaseTelemetryValidator, BasicAuthConnection, BearerToken, type BearerTokenInfo, type CommerceEvent, type CommerceEventConfig, type CommerceEventField, type Connection, type ConsumeStats, type CreateEventResult, CreateEvents, type CreateProviderParams, type CreateProviderResult, type CreateRegistrationResult, CreateRegistrations, type ErrorResponse, EventConsumerAction, type EventData, type EventMetadata, type EventMetadataInputModel, type EventMetadataListResponse, EventMetadataManager, type ExtendedRequestError, type FileMetadata, type FileRecord, FileRepository, GenerateBasicAuthToken, type GetProviderQueryParams, type GetRegistrationQueryParams, GraphQlAction, type HALLink, type Headers, HttpMethod, HttpStatus, IOEventsApiError, type IOEventsError, ImsConnection, ImsToken, type ImsTokenResult, InfiniteLoopBreaker, type InfiniteLoopData, IoEventsGlobals, JsonMessageProcessor, type ListProvidersQueryParams, type ListRegistrationQueryParams, type MenuItem, type MessageHandler, Oauth1aConnection, OnboardCommerce, type OnboardCommerceConfig, type OnboardCommerceResult, OnboardEvents, type OnboardEventsInput, type OnboardEventsResponse, OnboardEvents as OnboardIOEvents, Openwhisk, OpenwhiskAction, type OpenwhiskConfig, type Page, Parameters, type Provider, type ProviderInputModel, ProviderManager, PublishEvent, type PublishEventResult, type PublishStats, RabbitMQClient, type RabbitMQConsumeOptions, type RabbitMQCredentials, type Registration, type RegistrationCreateModel, type RegistrationListResponse, RegistrationManager, RestClient, RuntimeAction, RuntimeActionResponse, type RuntimeActionResponseType, RuntimeApiGatewayService, ShippingCarrier, type ShippingCarrierData, ShippingCarrierMethod, type ShippingCarrierMethodAdditionalData, type ShippingCarrierMethodData, ShippingCarrierResponse, SignatureVerification, SuccessChecker, type SuccessResponse, Telemetry, TelemetryInputError, type TokenResult, Validator, WebhookAction, type WebhookActionAddResponse, type WebhookActionExceptionResponse, WebhookActionOperation, type WebhookActionRemoveResponse, type WebhookActionReplaceResponse, WebhookActionResponse, type WebhookActionResponseType, type WebhookActionSuccessResponse, type WorkspaceConfig };
package/dist/index.d.ts CHANGED
@@ -271,6 +271,16 @@ interface AbdbRecord {
271
271
  [key: string]: unknown;
272
272
  }
273
273
  type AbdbRepositoryFilter = Record<string, unknown>;
274
+ type AbdbFindSortDirection = 'asc' | 'desc';
275
+ type AbdbFindSort = {
276
+ column: string;
277
+ direction?: AbdbFindSortDirection;
278
+ };
279
+ type AbdbFindOptions = {
280
+ current_page?: number;
281
+ page_size?: number;
282
+ sort?: AbdbFindSort;
283
+ };
274
284
 
275
285
  declare class AbdbRepository<T extends AbdbRecord = AbdbRecord> {
276
286
  private readonly _collection;
@@ -279,7 +289,7 @@ declare class AbdbRepository<T extends AbdbRecord = AbdbRecord> {
279
289
  constructor(collection: AbdbCollection, token: string, region?: string);
280
290
  getName(): string;
281
291
  getCollection(): AbdbCollection;
282
- find(filter?: AbdbRepositoryFilter): Promise<T[]>;
292
+ find(filter?: AbdbRepositoryFilter, options?: AbdbFindOptions): Promise<T[]>;
283
293
  findOne(filter: AbdbRepositoryFilter): Promise<T | null>;
284
294
  findById(id: string): Promise<T | null>;
285
295
  delete(filter?: AbdbRepositoryFilter): Promise<Record<string, any>>;
@@ -329,7 +339,7 @@ interface WebhookActionSuccessResponse {
329
339
  }
330
340
  interface WebhookActionExceptionResponse {
331
341
  op: typeof WebhookActionOperation.EXCEPTION;
332
- class?: string;
342
+ type?: string;
333
343
  message?: string;
334
344
  }
335
345
  interface WebhookActionAddResponse {
@@ -375,7 +385,7 @@ declare class WebhookAction {
375
385
 
376
386
  declare class WebhookActionResponse {
377
387
  static success(): WebhookActionSuccessResponse;
378
- static exception(message?: string, exceptionClass?: string): WebhookActionExceptionResponse;
388
+ static exception(message?: string, exceptionType?: string): WebhookActionExceptionResponse;
379
389
  static add(path: string, value: any, instance?: string): WebhookActionAddResponse;
380
390
  static replace(path: string, value: any, instance?: string): WebhookActionReplaceResponse;
381
391
  static remove(path: string): WebhookActionRemoveResponse;
@@ -1127,4 +1137,4 @@ declare class AdminUiSdk {
1127
1137
  getRegistration(): AdminUiSdkRegistration;
1128
1138
  }
1129
1139
 
1130
- export { AbdbCollection, type AbdbCollectionCallback, AbdbColumn, type AbdbColumnJson, type AbdbColumnOptions, AbdbColumnType, type AbdbRecord, AbdbRepository, type AbdbRepositoryFilter, type AbdbRunCallback, type AddColumnOptions, AdminUiSdk, type AdminUiSdkRegistration, AdobeAuth, AdobeCommerceClient, type AdobeIMSConfig, type BaseTelemetry, type BaseTelemetryValidator, BasicAuthConnection, BearerToken, type BearerTokenInfo, type CommerceEvent, type CommerceEventConfig, type CommerceEventField, type Connection, type ConsumeStats, type CreateEventResult, CreateEvents, type CreateProviderParams, type CreateProviderResult, type CreateRegistrationResult, CreateRegistrations, type ErrorResponse, EventConsumerAction, type EventData, type EventMetadata, type EventMetadataInputModel, type EventMetadataListResponse, EventMetadataManager, type ExtendedRequestError, type FileMetadata, type FileRecord, FileRepository, GenerateBasicAuthToken, type GetProviderQueryParams, type GetRegistrationQueryParams, GraphQlAction, type HALLink, type Headers, HttpMethod, HttpStatus, IOEventsApiError, type IOEventsError, ImsConnection, ImsToken, type ImsTokenResult, InfiniteLoopBreaker, type InfiniteLoopData, IoEventsGlobals, JsonMessageProcessor, type ListProvidersQueryParams, type ListRegistrationQueryParams, type MenuItem, type MessageHandler, Oauth1aConnection, OnboardCommerce, type OnboardCommerceConfig, type OnboardCommerceResult, OnboardEvents, type OnboardEventsInput, type OnboardEventsResponse, OnboardEvents as OnboardIOEvents, Openwhisk, OpenwhiskAction, type OpenwhiskConfig, type Page, Parameters, type Provider, type ProviderInputModel, ProviderManager, PublishEvent, type PublishEventResult, type PublishStats, RabbitMQClient, type RabbitMQConsumeOptions, type RabbitMQCredentials, type Registration, type RegistrationCreateModel, type RegistrationListResponse, RegistrationManager, RestClient, RuntimeAction, RuntimeActionResponse, type RuntimeActionResponseType, RuntimeApiGatewayService, ShippingCarrier, type ShippingCarrierData, ShippingCarrierMethod, type ShippingCarrierMethodAdditionalData, type ShippingCarrierMethodData, ShippingCarrierResponse, SignatureVerification, SuccessChecker, type SuccessResponse, Telemetry, TelemetryInputError, type TokenResult, Validator, WebhookAction, type WebhookActionAddResponse, type WebhookActionExceptionResponse, WebhookActionOperation, type WebhookActionRemoveResponse, type WebhookActionReplaceResponse, WebhookActionResponse, type WebhookActionResponseType, type WebhookActionSuccessResponse, type WorkspaceConfig };
1140
+ export { AbdbCollection, type AbdbCollectionCallback, AbdbColumn, type AbdbColumnJson, type AbdbColumnOptions, AbdbColumnType, type AbdbFindOptions, type AbdbFindSort, type AbdbFindSortDirection, type AbdbRecord, AbdbRepository, type AbdbRepositoryFilter, type AbdbRunCallback, type AddColumnOptions, AdminUiSdk, type AdminUiSdkRegistration, AdobeAuth, AdobeCommerceClient, type AdobeIMSConfig, type BaseTelemetry, type BaseTelemetryValidator, BasicAuthConnection, BearerToken, type BearerTokenInfo, type CommerceEvent, type CommerceEventConfig, type CommerceEventField, type Connection, type ConsumeStats, type CreateEventResult, CreateEvents, type CreateProviderParams, type CreateProviderResult, type CreateRegistrationResult, CreateRegistrations, type ErrorResponse, EventConsumerAction, type EventData, type EventMetadata, type EventMetadataInputModel, type EventMetadataListResponse, EventMetadataManager, type ExtendedRequestError, type FileMetadata, type FileRecord, FileRepository, GenerateBasicAuthToken, type GetProviderQueryParams, type GetRegistrationQueryParams, GraphQlAction, type HALLink, type Headers, HttpMethod, HttpStatus, IOEventsApiError, type IOEventsError, ImsConnection, ImsToken, type ImsTokenResult, InfiniteLoopBreaker, type InfiniteLoopData, IoEventsGlobals, JsonMessageProcessor, type ListProvidersQueryParams, type ListRegistrationQueryParams, type MenuItem, type MessageHandler, Oauth1aConnection, OnboardCommerce, type OnboardCommerceConfig, type OnboardCommerceResult, OnboardEvents, type OnboardEventsInput, type OnboardEventsResponse, OnboardEvents as OnboardIOEvents, Openwhisk, OpenwhiskAction, type OpenwhiskConfig, type Page, Parameters, type Provider, type ProviderInputModel, ProviderManager, PublishEvent, type PublishEventResult, type PublishStats, RabbitMQClient, type RabbitMQConsumeOptions, type RabbitMQCredentials, type Registration, type RegistrationCreateModel, type RegistrationListResponse, RegistrationManager, RestClient, RuntimeAction, RuntimeActionResponse, type RuntimeActionResponseType, RuntimeApiGatewayService, ShippingCarrier, type ShippingCarrierData, ShippingCarrierMethod, type ShippingCarrierMethodAdditionalData, type ShippingCarrierMethodData, ShippingCarrierResponse, SignatureVerification, SuccessChecker, type SuccessResponse, Telemetry, TelemetryInputError, type TokenResult, Validator, WebhookAction, type WebhookActionAddResponse, type WebhookActionExceptionResponse, WebhookActionOperation, type WebhookActionRemoveResponse, type WebhookActionReplaceResponse, WebhookActionResponse, type WebhookActionResponseType, type WebhookActionSuccessResponse, type WorkspaceConfig };
package/dist/index.js CHANGED
@@ -6048,13 +6048,31 @@ var _AbdbRepository = class _AbdbRepository {
6048
6048
  * Returns all documents matching `filter` as an array.
6049
6049
  * Passing no filter (or an empty object) returns every document in the collection.
6050
6050
  *
6051
+ * Pagination and sorting are applied in the following MongoDB cursor order:
6052
+ * `.find(filter)` → `.sort(...)` → `.skip(...)` → `.limit(...)` → `.toArray()`
6053
+ *
6051
6054
  * @param filter - Optional query filter (default: `{}`)
6055
+ * @param options - Optional pagination and sort configuration
6056
+ * @param options.sort - Column and direction to sort by (`'asc'` maps to `1`, `'desc'` to `-1`)
6057
+ * @param options.page_size - Maximum number of documents to return
6058
+ * @param options.current_page - 1-based page index; combined with `page_size` to compute `.skip()`
6052
6059
  * @returns Array of matched documents (may be empty)
6053
6060
  */
6054
- async find(filter = {}) {
6061
+ async find(filter = {}, options = {}) {
6055
6062
  return this._collection.run(
6056
6063
  async (collection) => {
6057
- return collection.find(filter).toArray();
6064
+ const { current_page, page_size, sort } = options;
6065
+ let cursor = collection.find(filter);
6066
+ if (sort?.column) {
6067
+ cursor = cursor.sort({ [sort.column]: sort.direction === "desc" ? -1 : 1 });
6068
+ }
6069
+ if (page_size !== void 0 && page_size > 0) {
6070
+ if (current_page !== void 0 && current_page > 1) {
6071
+ cursor = cursor.skip((current_page - 1) * page_size);
6072
+ }
6073
+ cursor = cursor.limit(page_size);
6074
+ }
6075
+ return cursor.toArray();
6058
6076
  },
6059
6077
  this._token,
6060
6078
  this._region
@@ -6475,7 +6493,7 @@ var _WebhookActionResponse = class _WebhookActionResponse {
6475
6493
  * processing the webhook. This helps with debugging and error tracking.
6476
6494
  *
6477
6495
  * @param message - Optional error message describing what went wrong
6478
- * @param exceptionClass - Optional exception class name for categorization (e.g., 'Magento\\Framework\\Exception\\LocalizedException')
6496
+ * @param exceptionType - Optional exception type name for categorization (e.g., 'Magento\\Framework\\Exception\\LocalizedException')
6479
6497
  * @returns An exception response object
6480
6498
  *
6481
6499
  * @example
@@ -6497,15 +6515,15 @@ var _WebhookActionResponse = class _WebhookActionResponse {
6497
6515
  * });
6498
6516
  * ```
6499
6517
  */
6500
- static exception(message, exceptionClass) {
6518
+ static exception(message, exceptionType) {
6501
6519
  const response = {
6502
6520
  op: "exception" /* EXCEPTION */
6503
6521
  };
6504
6522
  if (message !== void 0) {
6505
6523
  response.message = message;
6506
6524
  }
6507
- if (exceptionClass !== void 0) {
6508
- response.class = exceptionClass;
6525
+ if (exceptionType !== void 0) {
6526
+ response.type = exceptionType;
6509
6527
  }
6510
6528
  return response;
6511
6529
  }
@@ -11772,11 +11790,11 @@ var _RabbitMQClient = class _RabbitMQClient {
11772
11790
  this.credentials = credentials;
11773
11791
  }
11774
11792
  /**
11775
- * Opens an AMQP connection, checks queue depth, sets prefetch for concurrency control,
11776
- * and starts a push consumer. The broker delivers at most `maxParallel` unacked messages
11777
- * at a time, so processing concurrency is naturally bounded without a separate semaphore.
11778
- * The consumer is cancelled once `effectiveBatch = min(batchSize, messageCount)` messages
11779
- * are received and processed. The connection is always closed in a `finally` block.
11793
+ * Opens an AMQP connection, checks queue depth, and pulls up to
11794
+ * `effectiveBatch = min(batchSize, messageCount)` messages via channel.get.
11795
+ * Messages are processed in parallel windows of `maxParallel`. channel.get returns
11796
+ * false when the queue is empty, so the method exits deterministically without any
11797
+ * cancellation logic. The connection is always closed in a `finally` block.
11780
11798
  *
11781
11799
  * @param queueName - Name of the queue to consume from.
11782
11800
  * @param options - Consume configuration (batchSize, maxParallel, nackRequeue, exchange).
@@ -11798,16 +11816,20 @@ var _RabbitMQClient = class _RabbitMQClient {
11798
11816
  }
11799
11817
  return await this.processBatch(channel, queueName, options, handler);
11800
11818
  } finally {
11801
- await channel?.close();
11819
+ try {
11820
+ await channel?.close();
11821
+ } catch {
11822
+ }
11802
11823
  await connection.close();
11803
11824
  }
11804
11825
  }
11805
11826
  /**
11806
11827
  * Opens an AMQP connection, asserts the queue, and enqueues each payload in `payloads`.
11807
11828
  * Each payload is sent as a persistent message via `sendToQueue`. If the write buffer is
11808
- * full (`sendToQueue` returns `false`) or the call throws, the payload is recorded in
11809
- * `stats.errors` and counted as failed. The connection is always closed in a `finally`
11810
- * block regardless of outcome.
11829
+ * full (`sendToQueue` returns `false`), the message is still counted as published and the
11830
+ * method waits for the channel's `drain` event before continuing, to respect backpressure
11831
+ * without losing messages. Only genuine send errors (thrown exceptions) are counted as
11832
+ * failures. The connection is always closed in a `finally` block regardless of outcome.
11811
11833
  *
11812
11834
  * @param queueName - Name of the queue to publish to.
11813
11835
  * @param payloads - Array of string payloads to enqueue.
@@ -11820,27 +11842,30 @@ var _RabbitMQClient = class _RabbitMQClient {
11820
11842
  try {
11821
11843
  channel = await connection.createChannel();
11822
11844
  await channel.assertQueue(queueName, { durable: true });
11823
- return this.publishBatch(channel, queueName, payloads);
11845
+ return await this.publishBatch(channel, queueName, payloads);
11824
11846
  } finally {
11825
- await channel?.close();
11847
+ try {
11848
+ await channel?.close();
11849
+ } catch {
11850
+ }
11826
11851
  await connection.close();
11827
11852
  }
11828
11853
  }
11829
11854
  /**
11830
11855
  * Sends each payload to the queue via `sendToQueue`. Tracks published and failed counts.
11831
- * A payload is considered failed when `sendToQueue` returns `false` (write buffer full)
11832
- * or throws an error.
11856
+ * When `sendToQueue` returns `false` (write buffer full / backpressure), the message is
11857
+ * still counted as published — it is already accepted by the channel — and the loop
11858
+ * pauses until the channel emits `drain` before continuing, preventing unbounded memory
11859
+ * pressure. A payload is only counted as failed when `sendToQueue` throws an error.
11833
11860
  */
11834
- publishBatch(channel, queueName, payloads) {
11861
+ async publishBatch(channel, queueName, payloads) {
11835
11862
  const stats = { published: 0, failed: 0, errors: [] };
11836
11863
  for (const payload of payloads) {
11837
11864
  try {
11838
11865
  const sent = channel.sendToQueue(queueName, Buffer.from(payload), { persistent: true });
11839
- if (sent) {
11840
- stats.published++;
11841
- } else {
11842
- stats.failed++;
11843
- stats.errors.push({ payload, error: new Error("Write buffer full") });
11866
+ stats.published++;
11867
+ if (!sent) {
11868
+ await new Promise((resolve) => channel.once("drain", resolve));
11844
11869
  }
11845
11870
  } catch (error) {
11846
11871
  stats.failed++;
@@ -11860,63 +11885,37 @@ var _RabbitMQClient = class _RabbitMQClient {
11860
11885
  return `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${host}:${port}/${encodeURIComponent(vhost)}`;
11861
11886
  }
11862
11887
  /**
11863
- * Checks queue depth via `channel.checkQueue`, then sets `channel.prefetch(maxParallel)`
11864
- * for broker-side concurrency control. Registers a push consumer that receives
11865
- * `effectiveBatch = min(batchSize, messageCount)` messages. The Promise resolves after
11866
- * `channel.consume` setup completes and all in-flight handlers have settled.
11888
+ * Checks queue depth via channel.checkQueue, then pulls up to
11889
+ * `effectiveBatch = min(batchSize, messageCount)` messages using channel.get
11890
+ * (AMQP basic.get). Messages are processed in parallel windows of `maxParallel`:
11891
+ * each window pulls up to `maxParallel` messages sequentially, then processes them
11892
+ * concurrently via Promise.all before moving to the next window.
11867
11893
  *
11868
- * Because the broker delivers at most `maxParallel` unacked messages at a time, processing
11869
- * concurrency is bounded without a separate semaphore each ack/nack releases a slot.
11894
+ * channel.get returns false when the queue is empty, so the loop exits immediately
11895
+ * if siblings have drained the queueno consumer registration, no cancel, no hang.
11870
11896
  */
11871
11897
  async processBatch(channel, queueName, options, handler) {
11872
11898
  const stats = { consumed: 0, acked: 0, nacked: 0, errors: [] };
11873
- const maxParallel = Math.floor(options.maxParallel);
11874
- const batchSize = Math.floor(options.batchSize);
11899
+ const { batchSize, maxParallel } = options;
11875
11900
  const { messageCount } = await channel.checkQueue(queueName);
11876
11901
  if (messageCount === 0) return stats;
11877
11902
  const effectiveBatch = Math.min(batchSize, messageCount);
11878
- await channel.prefetch(maxParallel);
11879
- return new Promise((resolve, reject) => {
11880
- let consumerTag = "";
11881
- let cancelRequested = false;
11882
- let received = 0;
11883
- let pending = 0;
11884
- let setupDone = false;
11885
- const maybeResolve = /* @__PURE__ */ __name(() => {
11886
- if ((received >= effectiveBatch || cancelRequested) && pending === 0 && setupDone) {
11887
- resolve(stats);
11888
- }
11889
- }, "maybeResolve");
11890
- const msgCallback = /* @__PURE__ */ __name(async (msg) => {
11891
- if (!msg || received >= effectiveBatch) return;
11892
- received++;
11903
+ while (stats.consumed < effectiveBatch) {
11904
+ const windowSize = Math.min(maxParallel, effectiveBatch - stats.consumed);
11905
+ const window = [];
11906
+ for (let i = 0; i < windowSize; i++) {
11907
+ const msg = await channel.get(queueName, { noAck: false });
11908
+ if (!msg) break;
11909
+ window.push(msg);
11893
11910
  stats.consumed++;
11894
- pending++;
11895
- if (received >= effectiveBatch) {
11896
- cancelRequested = true;
11897
- if (consumerTag) {
11898
- channel.cancel(consumerTag).catch(reject);
11899
- }
11900
- }
11901
- await this.processMessage(channel, queueName, msg, stats, options, handler);
11902
- pending--;
11903
- maybeResolve();
11904
- }, "msgCallback");
11905
- channel.consume(queueName, msgCallback, { noAck: false }).then(async ({ consumerTag: tag }) => {
11906
- consumerTag = tag;
11907
- setupDone = true;
11908
- if (cancelRequested) {
11909
- channel.cancel(tag).catch(reject);
11910
- } else if (received === 0) {
11911
- const { messageCount: remaining } = await channel.checkQueue(queueName);
11912
- if (remaining === 0) {
11913
- cancelRequested = true;
11914
- channel.cancel(tag).catch(reject);
11915
- }
11916
- }
11917
- maybeResolve();
11918
- }).catch(reject);
11919
- });
11911
+ }
11912
+ if (window.length === 0) break;
11913
+ await Promise.all(
11914
+ window.map((msg) => this.processMessage(channel, queueName, msg, stats, options, handler))
11915
+ );
11916
+ if (window.length < windowSize) break;
11917
+ }
11918
+ return stats;
11920
11919
  }
11921
11920
  /**
11922
11921
  * Invokes `handler` with the queue name and decoded message content. Acks on success.