"use strict";
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncBatchedStore = void 0;
const base_js_1 = require("./base.cjs");
/**
 * Extracts and returns the underlying store from an `AsyncBatchedStore`,
 * or returns the input if it is not an `AsyncBatchedStore`.
 */
const extractStore = (input) => {
    if ("lg_name" in input && input.lg_name === "AsyncBatchedStore") {
        // @ts-expect-error is a protected property
        return input.store;
    }
    return input;
};
class AsyncBatchedStore extends base_js_1.BaseStore {
    constructor(store) {
        super();
        Object.defineProperty(this, "lg_name", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: "AsyncBatchedStore"
        });
        Object.defineProperty(this, "store", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "queue", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: new Map()
        });
        Object.defineProperty(this, "nextKey", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 0
        });
        Object.defineProperty(this, "running", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "processingTask", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        this.store = extractStore(store);
    }
    get isRunning() {
        return this.running;
    }
    /**
     * @ignore
     * Batch is not implemented here as we're only extending `BaseStore`
     * to allow it to be passed where `BaseStore` is expected, and implement
     * the convenience methods (get, search, put, delete).
     */
    async batch(_operations) {
        throw new Error("The `batch` method is not implemented on `AsyncBatchedStore`." +
            "\n Instead, it calls the `batch` method on the wrapped store." +
            "\n If you are seeing this error, something is wrong.");
    }
    async get(namespace, key) {
        return this.enqueueOperation({ namespace, key });
    }
    async search(namespacePrefix, options) {
        const { filter, limit = 10, offset = 0, query } = options || {};
        return this.enqueueOperation({
            namespacePrefix,
            filter,
            limit,
            offset,
            query,
        });
    }
    async put(namespace, key, value) {
        return this.enqueueOperation({ namespace, key, value });
    }
    async delete(namespace, key) {
        return this.enqueueOperation({
            namespace,
            key,
            value: null,
        });
    }
    start() {
        if (!this.running) {
            this.running = true;
            this.processingTask = this.processBatchQueue();
        }
    }
    async stop() {
        this.running = false;
        if (this.processingTask) {
            await this.processingTask;
        }
    }
    enqueueOperation(operation) {
        return new Promise((resolve, reject) => {
            const key = this.nextKey;
            this.nextKey += 1;
            this.queue.set(key, { operation, resolve, reject });
        });
    }
    async processBatchQueue() {
        while (this.running) {
            await new Promise((resolve) => {
                setTimeout(resolve, 0);
            });
            if (this.queue.size === 0)
                continue;
            const batch = new Map(this.queue);
            this.queue.clear();
            try {
                const operations = Array.from(batch.values()).map(({ operation }) => operation);
                const results = await this.store.batch(operations);
                batch.forEach(({ resolve }, key) => {
                    const index = Array.from(batch.keys()).indexOf(key);
                    resolve(results[index]);
                });
            }
            catch (e) {
                batch.forEach(({ reject }) => {
                    reject(e);
                });
            }
        }
    }
    // AsyncBatchedStore is internal and gets passed as args into traced tasks
    // some BaseStores contain circular references so just serialize without it
    // as this causes warnings when tracing with LangSmith.
    toJSON() {
        return {
            queue: this.queue,
            nextKey: this.nextKey,
            running: this.running,
            store: "[LangGraphStore]",
        };
    }
}
exports.AsyncBatchedStore = AsyncBatchedStore;
//# sourceMappingURL=batch.js.map