message: fix(ldap): added manual paging with pause in searchStreaming to limit memory usage
diff: import { ForwardedError } from '@backstage/errors';
  import ldap, { Client, SearchEntry, SearchOptions } from 'ldapjs';
  -import { cloneDeep } from 'lodash';
  +import { cloneDeep, merge } from 'lodash';
  import { Logger } from 'winston';
  import { BindConfig, TLSConfig } from './config';
  import { errorString } from './util';
  @@ -150,11 +150,14 @@ export class LdapClient {
  f: (entry: SearchEntry) => Promise<void> | void,
  ): Promise<void> {
  try {
  - const awaitList: Array<Promise<void> | void> = [];
  + let awaitList: Array<Promise<void> | void> = [];
  return await new Promise<void>((resolve, reject) => {
  // Note that we clone the (frozen) options, since ldapjs rudely tries to
  // overwrite parts of them
  - this.client.search(dn, cloneDeep(options), (err, res) => {
  + this.client.search(
  + dn,
  + merge(cloneDeep(options), { paged: { pagePause: true } }),
  + (err, res) => {
  if (err) {
  reject(new Error(errorString(err)));
  }
  @@ -167,6 +170,17 @@ export class LdapClient {
  awaitList.push(f(entry));
  });
  + res.on('page', (_, cb) => {
  + // awaits completion before fetching next page
  + Promise.all(awaitList)
  + .then(() => {
  + // flush list
  + awaitList = [];
  + if (cb) cb();
  + })
  + .catch(reject);
  + });
  +
  res.on('error', e => {
  reject(new Error(errorString(e)));
  });
  @@ -182,7 +196,8 @@ export class LdapClient {
  .catch(reject);
  }
  });
  - });
  + },
  + );
  });
  } catch (e) {
  throw new ForwardedError(`LDAP search at DN "${dn}" failed`, e);
  