Effect CommunityEC
Effect Community2mo ago
26 replies
spaceemotion

Converting OperationBatcher to Effect-style with Streams and Generators

Trying to convert some of our code to "Effect-style" - and I am a bit stuck with this operation batcher we have:
export type Resolvers<T = void> = ReturnType<typeof withResolvers<T>>;

export const withResolvers = /* typeof Promise.withResolvers === 'function' ? Promise.withResolvers : */ (<T = void>() => {
  let resolve: (val: T) => void;
  let reject: (err: unknown) => void;

  const promise = new Promise<T>((res, rej) => {
    resolve = res;
    reject = rej;
  });

  return {
    promise,
    resolve: resolve!,
    reject: reject!,
  };
});

export class OperationBatcher<TEntry, TReturn = void> {
  protected readonly pending: Map<TEntry, Resolvers<TReturn>>
  protected timer: ReturnType<typeof setTimeout> | null;

  constructor(
    protected readonly callback: (
      batch: [entry: TEntry, resolvers: Resolvers<TReturn>][],
    ) => unknown,
  ) {
    this.pending = new Map();
    this.timer = null;
  }

  schedule(item: TEntry): Resolvers<TReturn> {
    let resolvers = this.pending.get(item);

    if (resolvers === undefined) {
      resolvers = withResolvers<TReturn>();

      this.pending.set(item, resolvers);
    }

    if (this.timer === null) {
      this.timer = setTimeout(() => {
        this.timer = null;

        if (this.pending.size === 0) {
          return;
        }

        this.callback(Array.from(this.pending.entries()));

        this.pending.clear();
      }, 0);
    }

    return resolvers;
  }
}


I want this to be something I can reuse across the app, like OperationBatcher.make(Effect.gen(....)) .

I already found that there's a Schedule.timerBatched but that doesn't look quite right, and I feel like this is almost more like something that should internally be handled like a Stream (with each chunk being the entries of that current 'event tick'?)

How does one go about converting this, and what's the correct approach here?

Thanks in advance!
Was this page helpful?