type PromiseResolvers<T = void> = ReturnType<Promise.withResolvers<T>>;
class OperationBatcher<TEntry, TReturn = void> {
pending: Map<TEntry, PromiseResolvers<TReturn>>
timer: ReturnType<typeof setTimeout> | null;
constructor(
protected readonly callback: (
batch: [entry: TEntry, resolvers: PromiseResolvers<TReturn>][],
) => Effect.Effect<void, unknown>,
) {
this.pending = new Map();
this.timer = null;
}
schedule(item: TEntry): PromiseResolvers<TReturn> {
let resolvers = this.pending.get(item);
if (resolvers !== undefined) {
return resolvers;
}
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;
}
}
type PromiseResolvers<T = void> = ReturnType<Promise.withResolvers<T>>;
class OperationBatcher<TEntry, TReturn = void> {
pending: Map<TEntry, PromiseResolvers<TReturn>>
timer: ReturnType<typeof setTimeout> | null;
constructor(
protected readonly callback: (
batch: [entry: TEntry, resolvers: PromiseResolvers<TReturn>][],
) => Effect.Effect<void, unknown>,
) {
this.pending = new Map();
this.timer = null;
}
schedule(item: TEntry): PromiseResolvers<TReturn> {
let resolvers = this.pending.get(item);
if (resolvers !== undefined) {
return resolvers;
}
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;
}
}